diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 19:57:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 19:57:51 -0400 |
commit | 804ce9866d56130032c9c8afc90a1297b7deed56 (patch) | |
tree | 6dd70984f411d2a3624d3f8db7facc3d6396b9ad /drivers/video/omap2/dss/apply.c | |
parent | f5e7e844a571124ffc117d4696787d6afc4fc5ae (diff) | |
parent | c895305e806b4346006d3cfba2b432d52268ecd3 (diff) |
Merge tag 'fbdev-updates-for-3.5' of git://github.com/schandinat/linux-2.6
Pull fbdev updates from Florian Tobias Schandinat:
- driver for AUO-K1900 and AUO-K1901 epaper controller
- large updates for OMAP (e.g. decouple HDMI audio and video)
- some updates for Exynos and SH Mobile
- various other small fixes and cleanups
* tag 'fbdev-updates-for-3.5' of git://github.com/schandinat/linux-2.6: (130 commits)
video: bfin_adv7393fb: Fix cleanup code
video: exynos_dp: reduce delay time when configuring video setting
video: exynos_dp: move sw reset prioir to enabling sw defined function
video: exynos_dp: use devm_ functions
fb: handle NULL pointers in framebuffer release
OMAPDSS: HDMI: OMAP4: Update IRQ flags for the HPD IRQ request
OMAPDSS: Apply VENC timings even if panel is disabled
OMAPDSS: VENC/DISPC: Delay dividing Y resolution for managers connected to VENC
OMAPDSS: DISPC: Support rotation through TILER
OMAPDSS: VRFB: remove compiler warnings when CONFIG_BUG=n
OMAPFB: remove compiler warnings when CONFIG_BUG=n
OMAPDSS: remove compiler warnings when CONFIG_BUG=n
OMAPDSS: DISPC: fix usage of dispc_ovl_set_accu_uv
OMAPDSS: use DSI_FIFO_BUG workaround only for manual update displays
OMAPDSS: DSI: Support command mode interleaving during video mode blanking periods
OMAPDSS: DISPC: Update Accumulator configuration for chroma plane
drivers/video: fsl-diu-fb: don't initialize the THRESHOLDS registers
video: exynos mipi dsi: support reverse panel type
video: exynos mipi dsi: Properly interpret the interrupt source flags
video: exynos mipi dsi: Avoid races in probe()
...
Diffstat (limited to 'drivers/video/omap2/dss/apply.c')
-rw-r--r-- | drivers/video/omap2/dss/apply.c | 134 |
1 files changed, 101 insertions, 33 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index b10b3bc1931..ab22cc224f3 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c | |||
@@ -99,6 +99,11 @@ struct mgr_priv_data { | |||
99 | 99 | ||
100 | /* If true, a display is enabled using this manager */ | 100 | /* If true, a display is enabled using this manager */ |
101 | bool enabled; | 101 | bool enabled; |
102 | |||
103 | bool extra_info_dirty; | ||
104 | bool shadow_extra_info_dirty; | ||
105 | |||
106 | struct omap_video_timings timings; | ||
102 | }; | 107 | }; |
103 | 108 | ||
104 | static struct { | 109 | static struct { |
@@ -176,7 +181,7 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr) | |||
176 | } | 181 | } |
177 | 182 | ||
178 | static int dss_check_settings_low(struct omap_overlay_manager *mgr, | 183 | static int dss_check_settings_low(struct omap_overlay_manager *mgr, |
179 | struct omap_dss_device *dssdev, bool applying) | 184 | bool applying) |
180 | { | 185 | { |
181 | struct omap_overlay_info *oi; | 186 | struct omap_overlay_info *oi; |
182 | struct omap_overlay_manager_info *mi; | 187 | struct omap_overlay_manager_info *mi; |
@@ -187,6 +192,9 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr, | |||
187 | 192 | ||
188 | mp = get_mgr_priv(mgr); | 193 | mp = get_mgr_priv(mgr); |
189 | 194 | ||
195 | if (!mp->enabled) | ||
196 | return 0; | ||
197 | |||
190 | if (applying && mp->user_info_dirty) | 198 | if (applying && mp->user_info_dirty) |
191 | mi = &mp->user_info; | 199 | mi = &mp->user_info; |
192 | else | 200 | else |
@@ -206,26 +214,24 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr, | |||
206 | ois[ovl->id] = oi; | 214 | ois[ovl->id] = oi; |
207 | } | 215 | } |
208 | 216 | ||
209 | return dss_mgr_check(mgr, dssdev, mi, ois); | 217 | return dss_mgr_check(mgr, mi, &mp->timings, ois); |
210 | } | 218 | } |
211 | 219 | ||
212 | /* | 220 | /* |
213 | * check manager and overlay settings using overlay_info from data->info | 221 | * check manager and overlay settings using overlay_info from data->info |
214 | */ | 222 | */ |
215 | static int dss_check_settings(struct omap_overlay_manager *mgr, | 223 | static int dss_check_settings(struct omap_overlay_manager *mgr) |
216 | struct omap_dss_device *dssdev) | ||
217 | { | 224 | { |
218 | return dss_check_settings_low(mgr, dssdev, false); | 225 | return dss_check_settings_low(mgr, false); |
219 | } | 226 | } |
220 | 227 | ||
221 | /* | 228 | /* |
222 | * check manager and overlay settings using overlay_info from ovl->info if | 229 | * check manager and overlay settings using overlay_info from ovl->info if |
223 | * dirty and from data->info otherwise | 230 | * dirty and from data->info otherwise |
224 | */ | 231 | */ |
225 | static int dss_check_settings_apply(struct omap_overlay_manager *mgr, | 232 | static int dss_check_settings_apply(struct omap_overlay_manager *mgr) |
226 | struct omap_dss_device *dssdev) | ||
227 | { | 233 | { |
228 | return dss_check_settings_low(mgr, dssdev, true); | 234 | return dss_check_settings_low(mgr, true); |
229 | } | 235 | } |
230 | 236 | ||
231 | static bool need_isr(void) | 237 | static bool need_isr(void) |
@@ -261,6 +267,20 @@ static bool need_isr(void) | |||
261 | if (mp->shadow_info_dirty) | 267 | if (mp->shadow_info_dirty) |
262 | return true; | 268 | return true; |
263 | 269 | ||
270 | /* | ||
271 | * NOTE: we don't check extra_info flags for disabled | ||
272 | * managers, once the manager is enabled, the extra_info | ||
273 | * related manager changes will be taken in by HW. | ||
274 | */ | ||
275 | |||
276 | /* to write new values to registers */ | ||
277 | if (mp->extra_info_dirty) | ||
278 | return true; | ||
279 | |||
280 | /* to set GO bit */ | ||
281 | if (mp->shadow_extra_info_dirty) | ||
282 | return true; | ||
283 | |||
264 | list_for_each_entry(ovl, &mgr->overlays, list) { | 284 | list_for_each_entry(ovl, &mgr->overlays, list) { |
265 | struct ovl_priv_data *op; | 285 | struct ovl_priv_data *op; |
266 | 286 | ||
@@ -305,7 +325,7 @@ static bool need_go(struct omap_overlay_manager *mgr) | |||
305 | 325 | ||
306 | mp = get_mgr_priv(mgr); | 326 | mp = get_mgr_priv(mgr); |
307 | 327 | ||
308 | if (mp->shadow_info_dirty) | 328 | if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty) |
309 | return true; | 329 | return true; |
310 | 330 | ||
311 | list_for_each_entry(ovl, &mgr->overlays, list) { | 331 | list_for_each_entry(ovl, &mgr->overlays, list) { |
@@ -320,20 +340,16 @@ static bool need_go(struct omap_overlay_manager *mgr) | |||
320 | /* returns true if an extra_info field is currently being updated */ | 340 | /* returns true if an extra_info field is currently being updated */ |
321 | static bool extra_info_update_ongoing(void) | 341 | static bool extra_info_update_ongoing(void) |
322 | { | 342 | { |
323 | const int num_ovls = omap_dss_get_num_overlays(); | 343 | const int num_mgrs = dss_feat_get_num_mgrs(); |
324 | struct ovl_priv_data *op; | ||
325 | struct omap_overlay *ovl; | ||
326 | struct mgr_priv_data *mp; | ||
327 | int i; | 344 | int i; |
328 | 345 | ||
329 | for (i = 0; i < num_ovls; ++i) { | 346 | for (i = 0; i < num_mgrs; ++i) { |
330 | ovl = omap_dss_get_overlay(i); | 347 | struct omap_overlay_manager *mgr; |
331 | op = get_ovl_priv(ovl); | 348 | struct omap_overlay *ovl; |
332 | 349 | struct mgr_priv_data *mp; | |
333 | if (!ovl->manager) | ||
334 | continue; | ||
335 | 350 | ||
336 | mp = get_mgr_priv(ovl->manager); | 351 | mgr = omap_dss_get_overlay_manager(i); |
352 | mp = get_mgr_priv(mgr); | ||
337 | 353 | ||
338 | if (!mp->enabled) | 354 | if (!mp->enabled) |
339 | continue; | 355 | continue; |
@@ -341,8 +357,15 @@ static bool extra_info_update_ongoing(void) | |||
341 | if (!mp->updating) | 357 | if (!mp->updating) |
342 | continue; | 358 | continue; |
343 | 359 | ||
344 | if (op->extra_info_dirty || op->shadow_extra_info_dirty) | 360 | if (mp->extra_info_dirty || mp->shadow_extra_info_dirty) |
345 | return true; | 361 | return true; |
362 | |||
363 | list_for_each_entry(ovl, &mgr->overlays, list) { | ||
364 | struct ovl_priv_data *op = get_ovl_priv(ovl); | ||
365 | |||
366 | if (op->extra_info_dirty || op->shadow_extra_info_dirty) | ||
367 | return true; | ||
368 | } | ||
346 | } | 369 | } |
347 | 370 | ||
348 | return false; | 371 | return false; |
@@ -525,11 +548,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) | |||
525 | 548 | ||
526 | oi = &op->info; | 549 | oi = &op->info; |
527 | 550 | ||
551 | mp = get_mgr_priv(ovl->manager); | ||
552 | |||
528 | replication = dss_use_replication(ovl->manager->device, oi->color_mode); | 553 | replication = dss_use_replication(ovl->manager->device, oi->color_mode); |
529 | 554 | ||
530 | ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; | 555 | ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; |
531 | 556 | ||
532 | r = dispc_ovl_setup(ovl->id, oi, ilace, replication); | 557 | r = dispc_ovl_setup(ovl->id, oi, ilace, replication, &mp->timings); |
533 | if (r) { | 558 | if (r) { |
534 | /* | 559 | /* |
535 | * We can't do much here, as this function can be called from | 560 | * We can't do much here, as this function can be called from |
@@ -543,8 +568,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) | |||
543 | return; | 568 | return; |
544 | } | 569 | } |
545 | 570 | ||
546 | mp = get_mgr_priv(ovl->manager); | ||
547 | |||
548 | op->info_dirty = false; | 571 | op->info_dirty = false; |
549 | if (mp->updating) | 572 | if (mp->updating) |
550 | op->shadow_info_dirty = true; | 573 | op->shadow_info_dirty = true; |
@@ -601,6 +624,22 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) | |||
601 | } | 624 | } |
602 | } | 625 | } |
603 | 626 | ||
627 | static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr) | ||
628 | { | ||
629 | struct mgr_priv_data *mp = get_mgr_priv(mgr); | ||
630 | |||
631 | DSSDBGF("%d", mgr->id); | ||
632 | |||
633 | if (!mp->extra_info_dirty) | ||
634 | return; | ||
635 | |||
636 | dispc_mgr_set_timings(mgr->id, &mp->timings); | ||
637 | |||
638 | mp->extra_info_dirty = false; | ||
639 | if (mp->updating) | ||
640 | mp->shadow_extra_info_dirty = true; | ||
641 | } | ||
642 | |||
604 | static void dss_write_regs_common(void) | 643 | static void dss_write_regs_common(void) |
605 | { | 644 | { |
606 | const int num_mgrs = omap_dss_get_num_overlay_managers(); | 645 | const int num_mgrs = omap_dss_get_num_overlay_managers(); |
@@ -646,7 +685,7 @@ static void dss_write_regs(void) | |||
646 | if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) | 685 | if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) |
647 | continue; | 686 | continue; |
648 | 687 | ||
649 | r = dss_check_settings(mgr, mgr->device); | 688 | r = dss_check_settings(mgr); |
650 | if (r) { | 689 | if (r) { |
651 | DSSERR("cannot write registers for manager %s: " | 690 | DSSERR("cannot write registers for manager %s: " |
652 | "illegal configuration\n", mgr->name); | 691 | "illegal configuration\n", mgr->name); |
@@ -654,6 +693,7 @@ static void dss_write_regs(void) | |||
654 | } | 693 | } |
655 | 694 | ||
656 | dss_mgr_write_regs(mgr); | 695 | dss_mgr_write_regs(mgr); |
696 | dss_mgr_write_regs_extra(mgr); | ||
657 | } | 697 | } |
658 | } | 698 | } |
659 | 699 | ||
@@ -693,6 +733,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) | |||
693 | 733 | ||
694 | mp = get_mgr_priv(mgr); | 734 | mp = get_mgr_priv(mgr); |
695 | mp->shadow_info_dirty = false; | 735 | mp->shadow_info_dirty = false; |
736 | mp->shadow_extra_info_dirty = false; | ||
696 | 737 | ||
697 | list_for_each_entry(ovl, &mgr->overlays, list) { | 738 | list_for_each_entry(ovl, &mgr->overlays, list) { |
698 | op = get_ovl_priv(ovl); | 739 | op = get_ovl_priv(ovl); |
@@ -711,7 +752,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) | |||
711 | 752 | ||
712 | WARN_ON(mp->updating); | 753 | WARN_ON(mp->updating); |
713 | 754 | ||
714 | r = dss_check_settings(mgr, mgr->device); | 755 | r = dss_check_settings(mgr); |
715 | if (r) { | 756 | if (r) { |
716 | DSSERR("cannot start manual update: illegal configuration\n"); | 757 | DSSERR("cannot start manual update: illegal configuration\n"); |
717 | spin_unlock_irqrestore(&data_lock, flags); | 758 | spin_unlock_irqrestore(&data_lock, flags); |
@@ -719,6 +760,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) | |||
719 | } | 760 | } |
720 | 761 | ||
721 | dss_mgr_write_regs(mgr); | 762 | dss_mgr_write_regs(mgr); |
763 | dss_mgr_write_regs_extra(mgr); | ||
722 | 764 | ||
723 | dss_write_regs_common(); | 765 | dss_write_regs_common(); |
724 | 766 | ||
@@ -857,7 +899,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
857 | 899 | ||
858 | spin_lock_irqsave(&data_lock, flags); | 900 | spin_lock_irqsave(&data_lock, flags); |
859 | 901 | ||
860 | r = dss_check_settings_apply(mgr, mgr->device); | 902 | r = dss_check_settings_apply(mgr); |
861 | if (r) { | 903 | if (r) { |
862 | spin_unlock_irqrestore(&data_lock, flags); | 904 | spin_unlock_irqrestore(&data_lock, flags); |
863 | DSSERR("failed to apply settings: illegal configuration.\n"); | 905 | DSSERR("failed to apply settings: illegal configuration.\n"); |
@@ -918,16 +960,13 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, | |||
918 | bool use_fifo_merge) | 960 | bool use_fifo_merge) |
919 | { | 961 | { |
920 | struct ovl_priv_data *op = get_ovl_priv(ovl); | 962 | struct ovl_priv_data *op = get_ovl_priv(ovl); |
921 | struct omap_dss_device *dssdev; | ||
922 | u32 fifo_low, fifo_high; | 963 | u32 fifo_low, fifo_high; |
923 | 964 | ||
924 | if (!op->enabled && !op->enabling) | 965 | if (!op->enabled && !op->enabling) |
925 | return; | 966 | return; |
926 | 967 | ||
927 | dssdev = ovl->manager->device; | ||
928 | |||
929 | dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, | 968 | dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, |
930 | use_fifo_merge); | 969 | use_fifo_merge, ovl_manual_update(ovl)); |
931 | 970 | ||
932 | dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); | 971 | dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); |
933 | } | 972 | } |
@@ -1050,7 +1089,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) | |||
1050 | 1089 | ||
1051 | mp->enabled = true; | 1090 | mp->enabled = true; |
1052 | 1091 | ||
1053 | r = dss_check_settings(mgr, mgr->device); | 1092 | r = dss_check_settings(mgr); |
1054 | if (r) { | 1093 | if (r) { |
1055 | DSSERR("failed to enable manager %d: check_settings failed\n", | 1094 | DSSERR("failed to enable manager %d: check_settings failed\n", |
1056 | mgr->id); | 1095 | mgr->id); |
@@ -1225,6 +1264,35 @@ err: | |||
1225 | return r; | 1264 | return r; |
1226 | } | 1265 | } |
1227 | 1266 | ||
1267 | static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, | ||
1268 | struct omap_video_timings *timings) | ||
1269 | { | ||
1270 | struct mgr_priv_data *mp = get_mgr_priv(mgr); | ||
1271 | |||
1272 | mp->timings = *timings; | ||
1273 | mp->extra_info_dirty = true; | ||
1274 | } | ||
1275 | |||
1276 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | ||
1277 | struct omap_video_timings *timings) | ||
1278 | { | ||
1279 | unsigned long flags; | ||
1280 | |||
1281 | mutex_lock(&apply_lock); | ||
1282 | |||
1283 | spin_lock_irqsave(&data_lock, flags); | ||
1284 | |||
1285 | dss_apply_mgr_timings(mgr, timings); | ||
1286 | |||
1287 | dss_write_regs(); | ||
1288 | dss_set_go_bits(); | ||
1289 | |||
1290 | spin_unlock_irqrestore(&data_lock, flags); | ||
1291 | |||
1292 | wait_pending_extra_info_updates(); | ||
1293 | |||
1294 | mutex_unlock(&apply_lock); | ||
1295 | } | ||
1228 | 1296 | ||
1229 | int dss_ovl_set_info(struct omap_overlay *ovl, | 1297 | int dss_ovl_set_info(struct omap_overlay *ovl, |
1230 | struct omap_overlay_info *info) | 1298 | struct omap_overlay_info *info) |
@@ -1393,7 +1461,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) | |||
1393 | 1461 | ||
1394 | op->enabling = true; | 1462 | op->enabling = true; |
1395 | 1463 | ||
1396 | r = dss_check_settings(ovl->manager, ovl->manager->device); | 1464 | r = dss_check_settings(ovl->manager); |
1397 | if (r) { | 1465 | if (r) { |
1398 | DSSERR("failed to enable overlay %d: check_settings failed\n", | 1466 | DSSERR("failed to enable overlay %d: check_settings failed\n", |
1399 | ovl->id); | 1467 | ovl->id); |