Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/video/omap2/dss/manager.c
0004  *
0005  * Copyright (C) 2009 Nokia Corporation
0006  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
0007  *
0008  * Some code and ideas taken from drivers/video/omap/ driver
0009  * by Imre Deak.
0010  */
0011 
0012 #define DSS_SUBSYS_NAME "MANAGER"
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/slab.h>
0016 #include <linux/module.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/jiffies.h>
0019 
0020 #include <video/omapfb_dss.h>
0021 
0022 #include "dss.h"
0023 #include "dss_features.h"
0024 
0025 static int num_managers;
0026 static struct omap_overlay_manager *managers;
0027 
0028 int dss_init_overlay_managers(void)
0029 {
0030     int i;
0031 
0032     num_managers = dss_feat_get_num_mgrs();
0033 
0034     managers = kcalloc(num_managers, sizeof(struct omap_overlay_manager),
0035                GFP_KERNEL);
0036 
0037     BUG_ON(managers == NULL);
0038 
0039     for (i = 0; i < num_managers; ++i) {
0040         struct omap_overlay_manager *mgr = &managers[i];
0041 
0042         switch (i) {
0043         case 0:
0044             mgr->name = "lcd";
0045             mgr->id = OMAP_DSS_CHANNEL_LCD;
0046             break;
0047         case 1:
0048             mgr->name = "tv";
0049             mgr->id = OMAP_DSS_CHANNEL_DIGIT;
0050             break;
0051         case 2:
0052             mgr->name = "lcd2";
0053             mgr->id = OMAP_DSS_CHANNEL_LCD2;
0054             break;
0055         case 3:
0056             mgr->name = "lcd3";
0057             mgr->id = OMAP_DSS_CHANNEL_LCD3;
0058             break;
0059         }
0060 
0061         mgr->supported_displays =
0062             dss_feat_get_supported_displays(mgr->id);
0063         mgr->supported_outputs =
0064             dss_feat_get_supported_outputs(mgr->id);
0065 
0066         INIT_LIST_HEAD(&mgr->overlays);
0067     }
0068 
0069     return 0;
0070 }
0071 
0072 int dss_init_overlay_managers_sysfs(struct platform_device *pdev)
0073 {
0074     int i, r;
0075 
0076     for (i = 0; i < num_managers; ++i) {
0077         struct omap_overlay_manager *mgr = &managers[i];
0078 
0079         r = dss_manager_kobj_init(mgr, pdev);
0080         if (r)
0081             DSSERR("failed to create sysfs file\n");
0082     }
0083 
0084     return 0;
0085 }
0086 
0087 void dss_uninit_overlay_managers(void)
0088 {
0089     kfree(managers);
0090     managers = NULL;
0091     num_managers = 0;
0092 }
0093 
0094 void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev)
0095 {
0096     int i;
0097 
0098     for (i = 0; i < num_managers; ++i) {
0099         struct omap_overlay_manager *mgr = &managers[i];
0100 
0101         dss_manager_kobj_uninit(mgr);
0102     }
0103 }
0104 
0105 int omap_dss_get_num_overlay_managers(void)
0106 {
0107     return num_managers;
0108 }
0109 EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
0110 
0111 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
0112 {
0113     if (num >= num_managers)
0114         return NULL;
0115 
0116     return &managers[num];
0117 }
0118 EXPORT_SYMBOL(omap_dss_get_overlay_manager);
0119 
0120 int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
0121         const struct omap_overlay_manager_info *info)
0122 {
0123     if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
0124         /*
0125          * OMAP3 supports only graphics source transparency color key
0126          * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
0127          * Alpha Mode.
0128          */
0129         if (info->partial_alpha_enabled && info->trans_enabled
0130             && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
0131             DSSERR("check_manager: illegal transparency key\n");
0132             return -EINVAL;
0133         }
0134     }
0135 
0136     return 0;
0137 }
0138 
0139 static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
0140         struct omap_overlay_info **overlay_infos)
0141 {
0142     struct omap_overlay *ovl1, *ovl2;
0143     struct omap_overlay_info *info1, *info2;
0144 
0145     list_for_each_entry(ovl1, &mgr->overlays, list) {
0146         info1 = overlay_infos[ovl1->id];
0147 
0148         if (info1 == NULL)
0149             continue;
0150 
0151         list_for_each_entry(ovl2, &mgr->overlays, list) {
0152             if (ovl1 == ovl2)
0153                 continue;
0154 
0155             info2 = overlay_infos[ovl2->id];
0156 
0157             if (info2 == NULL)
0158                 continue;
0159 
0160             if (info1->zorder == info2->zorder) {
0161                 DSSERR("overlays %d and %d have the same "
0162                         "zorder %d\n",
0163                     ovl1->id, ovl2->id, info1->zorder);
0164                 return -EINVAL;
0165             }
0166         }
0167     }
0168 
0169     return 0;
0170 }
0171 
0172 int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
0173         const struct omap_video_timings *timings)
0174 {
0175     if (!dispc_mgr_timings_ok(mgr->id, timings)) {
0176         DSSERR("check_manager: invalid timings\n");
0177         return -EINVAL;
0178     }
0179 
0180     return 0;
0181 }
0182 
0183 static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr,
0184         const struct dss_lcd_mgr_config *config)
0185 {
0186     struct dispc_clock_info cinfo = config->clock_info;
0187     int dl = config->video_port_width;
0188     bool stallmode = config->stallmode;
0189     bool fifohandcheck = config->fifohandcheck;
0190 
0191     if (cinfo.lck_div < 1 || cinfo.lck_div > 255)
0192         return -EINVAL;
0193 
0194     if (cinfo.pck_div < 1 || cinfo.pck_div > 255)
0195         return -EINVAL;
0196 
0197     if (dl != 12 && dl != 16 && dl != 18 && dl != 24)
0198         return -EINVAL;
0199 
0200     /* fifohandcheck should be used only with stallmode */
0201     if (!stallmode && fifohandcheck)
0202         return -EINVAL;
0203 
0204     /*
0205      * io pad mode can be only checked by using dssdev connected to the
0206      * manager. Ignore checking these for now, add checks when manager
0207      * is capable of holding information related to the connected interface
0208      */
0209 
0210     return 0;
0211 }
0212 
0213 int dss_mgr_check(struct omap_overlay_manager *mgr,
0214         struct omap_overlay_manager_info *info,
0215         const struct omap_video_timings *mgr_timings,
0216         const struct dss_lcd_mgr_config *lcd_config,
0217         struct omap_overlay_info **overlay_infos)
0218 {
0219     struct omap_overlay *ovl;
0220     int r;
0221 
0222     if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
0223         r = dss_mgr_check_zorder(mgr, overlay_infos);
0224         if (r)
0225             return r;
0226     }
0227 
0228     r = dss_mgr_check_timings(mgr, mgr_timings);
0229     if (r)
0230         return r;
0231 
0232     r = dss_mgr_check_lcd_config(mgr, lcd_config);
0233     if (r)
0234         return r;
0235 
0236     list_for_each_entry(ovl, &mgr->overlays, list) {
0237         struct omap_overlay_info *oi;
0238         int r;
0239 
0240         oi = overlay_infos[ovl->id];
0241 
0242         if (oi == NULL)
0243             continue;
0244 
0245         r = dss_ovl_check(ovl, oi, mgr_timings);
0246         if (r)
0247             return r;
0248     }
0249 
0250     return 0;
0251 }