aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-11-17 10:35:28 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-12-02 01:54:53 -0500
commit39518356ccd6e439abae24e1a24d84dcd12ff207 (patch)
treee7579f97b57961cf6b07a48fa2728cb9758c7277 /drivers/video/omap2/dss
parentf17d04fbbb201c05700359e94e2747c210f99852 (diff)
OMAPDSS: APPLY: add checking of ovls/mgrs settings
Add checks for overlay and manager settings. The checks are a bit complex, as we need to observe the bigger picture instead of overlays and managers independently. Things like the used display and the zorder of other overlays affect the validity of the settings. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r--drivers/video/omap2/dss/apply.c215
1 files changed, 212 insertions, 3 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 242cb1c983c0..6eb48586501c 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -166,6 +166,169 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
166 return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 166 return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
167} 167}
168 168
169/* Check if overlay parameters are compatible with display */
170static int dss_ovl_check(struct omap_overlay *ovl,
171 struct omap_overlay_info *info, struct omap_dss_device *dssdev)
172{
173 u16 outw, outh;
174 u16 dw, dh;
175
176 if (dssdev == NULL)
177 return 0;
178
179 dssdev->driver->get_resolution(dssdev, &dw, &dh);
180
181 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
182 outw = info->width;
183 outh = info->height;
184 } else {
185 if (info->out_width == 0)
186 outw = info->width;
187 else
188 outw = info->out_width;
189
190 if (info->out_height == 0)
191 outh = info->height;
192 else
193 outh = info->out_height;
194 }
195
196 if (dw < info->pos_x + outw) {
197 DSSERR("overlay %d horizontally not inside the display area "
198 "(%d + %d >= %d)\n",
199 ovl->id, info->pos_x, outw, dw);
200 return -EINVAL;
201 }
202
203 if (dh < info->pos_y + outh) {
204 DSSERR("overlay %d vertically not inside the display area "
205 "(%d + %d >= %d)\n",
206 ovl->id, info->pos_y, outh, dh);
207 return -EINVAL;
208 }
209
210 return 0;
211}
212
213static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
214 struct omap_overlay_info **overlay_infos)
215{
216 struct omap_overlay *ovl1, *ovl2;
217 struct ovl_priv_data *op1, *op2;
218 struct omap_overlay_info *info1, *info2;
219
220 list_for_each_entry(ovl1, &mgr->overlays, list) {
221 op1 = get_ovl_priv(ovl1);
222 info1 = overlay_infos[ovl1->id];
223
224 if (info1 == NULL)
225 continue;
226
227 list_for_each_entry(ovl2, &mgr->overlays, list) {
228 if (ovl1 == ovl2)
229 continue;
230
231 op2 = get_ovl_priv(ovl2);
232 info2 = overlay_infos[ovl2->id];
233
234 if (info2 == NULL)
235 continue;
236
237 if (info1->zorder == info2->zorder) {
238 DSSERR("overlays %d and %d have the same "
239 "zorder %d\n",
240 ovl1->id, ovl2->id, info1->zorder);
241 return -EINVAL;
242 }
243 }
244 }
245
246 return 0;
247}
248
249static int dss_mgr_check(struct omap_overlay_manager *mgr,
250 struct omap_dss_device *dssdev,
251 struct omap_overlay_manager_info *info,
252 struct omap_overlay_info **overlay_infos)
253{
254 struct omap_overlay *ovl;
255 int r;
256
257 if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
258 r = dss_mgr_check_zorder(mgr, overlay_infos);
259 if (r)
260 return r;
261 }
262
263 list_for_each_entry(ovl, &mgr->overlays, list) {
264 struct omap_overlay_info *oi;
265 int r;
266
267 oi = overlay_infos[ovl->id];
268
269 if (oi == NULL)
270 continue;
271
272 r = dss_ovl_check(ovl, oi, dssdev);
273 if (r)
274 return r;
275 }
276
277 return 0;
278}
279static int dss_check_settings_low(struct omap_overlay_manager *mgr,
280 struct omap_dss_device *dssdev, bool applying)
281{
282 struct omap_overlay_info *oi;
283 struct omap_overlay_manager_info *mi;
284 struct omap_overlay *ovl;
285 struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
286 struct ovl_priv_data *op;
287 struct mgr_priv_data *mp;
288
289 mp = get_mgr_priv(mgr);
290
291 if (applying && mp->user_info_dirty)
292 mi = &mp->user_info;
293 else
294 mi = &mp->info;
295
296 /* collect the infos to be tested into the array */
297 list_for_each_entry(ovl, &mgr->overlays, list) {
298 op = get_ovl_priv(ovl);
299
300 if (!op->enabled)
301 oi = NULL;
302 else if (applying && op->user_info_dirty)
303 oi = &op->user_info;
304 else
305 oi = &op->info;
306
307 ois[ovl->id] = oi;
308 }
309
310 return dss_mgr_check(mgr, dssdev, mi, ois);
311}
312
313/*
314 * check manager and overlay settings using overlay_info from data->info
315 */
316static int dss_check_settings(struct omap_overlay_manager *mgr,
317 struct omap_dss_device *dssdev)
318{
319 return dss_check_settings_low(mgr, dssdev, false);
320}
321
322/*
323 * check manager and overlay settings using overlay_info from ovl->info if
324 * dirty and from data->info otherwise
325 */
326static int dss_check_settings_apply(struct omap_overlay_manager *mgr,
327 struct omap_dss_device *dssdev)
328{
329 return dss_check_settings_low(mgr, dssdev, true);
330}
331
169static bool need_isr(void) 332static bool need_isr(void)
170{ 333{
171 const int num_mgrs = dss_feat_get_num_mgrs(); 334 const int num_mgrs = dss_feat_get_num_mgrs();
@@ -517,6 +680,7 @@ static void dss_write_regs(void)
517 for (i = 0; i < num_mgrs; ++i) { 680 for (i = 0; i < num_mgrs; ++i) {
518 struct omap_overlay_manager *mgr; 681 struct omap_overlay_manager *mgr;
519 struct mgr_priv_data *mp; 682 struct mgr_priv_data *mp;
683 int r;
520 684
521 mgr = omap_dss_get_overlay_manager(i); 685 mgr = omap_dss_get_overlay_manager(i);
522 mp = get_mgr_priv(mgr); 686 mp = get_mgr_priv(mgr);
@@ -524,6 +688,13 @@ static void dss_write_regs(void)
524 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) 688 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
525 continue; 689 continue;
526 690
691 r = dss_check_settings(mgr, mgr->device);
692 if (r) {
693 DSSERR("cannot write registers for manager %s: "
694 "illegal configuration\n", mgr->name);
695 continue;
696 }
697
527 dss_mgr_write_regs(mgr); 698 dss_mgr_write_regs(mgr);
528 699
529 if (need_go(mgr)) { 700 if (need_go(mgr)) {
@@ -541,11 +712,19 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
541{ 712{
542 struct mgr_priv_data *mp = get_mgr_priv(mgr); 713 struct mgr_priv_data *mp = get_mgr_priv(mgr);
543 unsigned long flags; 714 unsigned long flags;
715 int r;
544 716
545 spin_lock_irqsave(&data_lock, flags); 717 spin_lock_irqsave(&data_lock, flags);
546 718
547 WARN_ON(mp->updating); 719 WARN_ON(mp->updating);
548 720
721 r = dss_check_settings(mgr, mgr->device);
722 if (r) {
723 DSSERR("cannot start manual update: illegal configuration\n");
724 spin_unlock_irqrestore(&data_lock, flags);
725 return;
726 }
727
549 dss_mgr_write_regs(mgr); 728 dss_mgr_write_regs(mgr);
550 729
551 mp->updating = true; 730 mp->updating = true;
@@ -690,11 +869,19 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
690{ 869{
691 unsigned long flags; 870 unsigned long flags;
692 struct omap_overlay *ovl; 871 struct omap_overlay *ovl;
872 int r;
693 873
694 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); 874 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
695 875
696 spin_lock_irqsave(&data_lock, flags); 876 spin_lock_irqsave(&data_lock, flags);
697 877
878 r = dss_check_settings_apply(mgr, mgr->device);
879 if (r) {
880 spin_unlock_irqrestore(&data_lock, flags);
881 DSSERR("failed to apply settings: illegal configuration.\n");
882 return r;
883 }
884
698 /* Configure overlays */ 885 /* Configure overlays */
699 list_for_each_entry(ovl, &mgr->overlays, list) 886 list_for_each_entry(ovl, &mgr->overlays, list)
700 omap_dss_mgr_apply_ovl(ovl); 887 omap_dss_mgr_apply_ovl(ovl);
@@ -784,6 +971,7 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
784{ 971{
785 struct mgr_priv_data *mp = get_mgr_priv(mgr); 972 struct mgr_priv_data *mp = get_mgr_priv(mgr);
786 unsigned long flags; 973 unsigned long flags;
974 int r;
787 975
788 mutex_lock(&apply_lock); 976 mutex_lock(&apply_lock);
789 977
@@ -793,6 +981,16 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
793 spin_lock_irqsave(&data_lock, flags); 981 spin_lock_irqsave(&data_lock, flags);
794 982
795 mp->enabled = true; 983 mp->enabled = true;
984 r = dss_check_settings(mgr, mgr->device);
985 mp->enabled = false;
986 if (r) {
987 DSSERR("failed to enable manager %d: check_settings failed\n",
988 mgr->id);
989 spin_unlock_irqrestore(&data_lock, flags);
990 goto out;
991 }
992
993 mp->enabled = true;
796 994
797 dss_mgr_setup_fifos(mgr); 995 dss_mgr_setup_fifos(mgr);
798 996
@@ -1142,16 +1340,25 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1142 1340
1143 if (op->enabled) { 1341 if (op->enabled) {
1144 r = 0; 1342 r = 0;
1145 goto err; 1343 goto err1;
1146 } 1344 }
1147 1345
1148 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1346 if (ovl->manager == NULL || ovl->manager->device == NULL) {
1149 r = -EINVAL; 1347 r = -EINVAL;
1150 goto err; 1348 goto err1;
1151 } 1349 }
1152 1350
1153 spin_lock_irqsave(&data_lock, flags); 1351 spin_lock_irqsave(&data_lock, flags);
1154 1352
1353 op->enabled = true;
1354 r = dss_check_settings(ovl->manager, ovl->manager->device);
1355 op->enabled = false;
1356 if (r) {
1357 DSSERR("failed to enable overlay %d: check_settings failed\n",
1358 ovl->id);
1359 goto err2;
1360 }
1361
1155 dss_apply_ovl_enable(ovl, true); 1362 dss_apply_ovl_enable(ovl, true);
1156 1363
1157 dss_ovl_setup_fifo(ovl); 1364 dss_ovl_setup_fifo(ovl);
@@ -1163,7 +1370,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1163 mutex_unlock(&apply_lock); 1370 mutex_unlock(&apply_lock);
1164 1371
1165 return 0; 1372 return 0;
1166err: 1373err2:
1374 spin_unlock_irqrestore(&data_lock, flags);
1375err1:
1167 mutex_unlock(&apply_lock); 1376 mutex_unlock(&apply_lock);
1168 return r; 1377 return r;
1169} 1378}