0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0126
0127
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
0201 if (!stallmode && fifohandcheck)
0202 return -EINVAL;
0203
0204
0205
0206
0207
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 }