Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
apply.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Texas Instruments
3  * Author: Tomi Valkeinen <[email protected]>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #define DSS_SUBSYS_NAME "APPLY"
19 
20 #include <linux/kernel.h>
21 #include <linux/slab.h>
22 #include <linux/spinlock.h>
23 #include <linux/jiffies.h>
24 
25 #include <video/omapdss.h>
26 
27 #include "dss.h"
28 #include "dss_features.h"
29 
30 /*
31  * We have 4 levels of cache for the dispc settings. First two are in SW and
32  * the latter two in HW.
33  *
34  * set_info()
35  * v
36  * +--------------------+
37  * | user_info |
38  * +--------------------+
39  * v
40  * apply()
41  * v
42  * +--------------------+
43  * | info |
44  * +--------------------+
45  * v
46  * write_regs()
47  * v
48  * +--------------------+
49  * | shadow registers |
50  * +--------------------+
51  * v
52  * VFP or lcd/digit_enable
53  * v
54  * +--------------------+
55  * | registers |
56  * +--------------------+
57  */
58 
59 struct ovl_priv_data {
60 
63 
64  bool info_dirty;
66 
68 
71 
72  bool enabled;
75 
76  /*
77  * True if overlay is to be enabled. Used to check and calculate configs
78  * for the overlay before it is enabled in the HW.
79  */
80  bool enabling;
81 };
82 
83 struct mgr_priv_data {
84 
87 
88  bool info_dirty;
90 
92 
93  /* If true, GO bit is up and shadow registers cannot be written.
94  * Never true for manual update displays */
95  bool busy;
96 
97  /* If true, dispc output is enabled */
98  bool updating;
99 
100  /* If true, a display is enabled using this manager */
101  bool enabled;
102 
105 
108 };
109 
110 static struct {
113 
115 } dss_data;
116 
117 /* protects dss_data */
118 static spinlock_t data_lock;
119 /* lock for blocking functions */
120 static DEFINE_MUTEX(apply_lock);
121 static DECLARE_COMPLETION(extra_updated_completion);
122 
123 static void dss_register_vsync_isr(void);
124 
125 static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
126 {
127  return &dss_data.ovl_priv_data_array[ovl->id];
128 }
129 
130 static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
131 {
132  return &dss_data.mgr_priv_data_array[mgr->id];
133 }
134 
135 void dss_apply_init(void)
136 {
137  const int num_ovls = dss_feat_get_num_ovls();
138  struct mgr_priv_data *mp;
139  int i;
140 
141  spin_lock_init(&data_lock);
142 
143  for (i = 0; i < num_ovls; ++i) {
144  struct ovl_priv_data *op;
145 
146  op = &dss_data.ovl_priv_data_array[i];
147 
148  op->info.global_alpha = 255;
149 
150  switch (i) {
151  case 0:
152  op->info.zorder = 0;
153  break;
154  case 1:
155  op->info.zorder =
157  break;
158  case 2:
159  op->info.zorder =
161  break;
162  case 3:
163  op->info.zorder =
165  break;
166  }
167 
168  op->user_info = op->info;
169  }
170 
171  /*
172  * Initialize some of the lcd_config fields for TV manager, this lets
173  * us prevent checking if the manager is LCD or TV at some places
174  */
175  mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
176 
177  mp->lcd_config.video_port_width = 24;
178  mp->lcd_config.clock_info.lck_div = 1;
179  mp->lcd_config.clock_info.pck_div = 1;
180 }
181 
182 /*
183  * A LCD manager's stallmode decides whether it is in manual or auto update. TV
184  * manager is always auto update, stallmode field for TV manager is false by
185  * default
186  */
187 static bool ovl_manual_update(struct omap_overlay *ovl)
188 {
189  struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
190 
191  return mp->lcd_config.stallmode;
192 }
193 
194 static bool mgr_manual_update(struct omap_overlay_manager *mgr)
195 {
196  struct mgr_priv_data *mp = get_mgr_priv(mgr);
197 
198  return mp->lcd_config.stallmode;
199 }
200 
201 static int dss_check_settings_low(struct omap_overlay_manager *mgr,
202  bool applying)
203 {
204  struct omap_overlay_info *oi;
205  struct omap_overlay_manager_info *mi;
206  struct omap_overlay *ovl;
207  struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
208  struct ovl_priv_data *op;
209  struct mgr_priv_data *mp;
210 
211  mp = get_mgr_priv(mgr);
212 
213  if (!mp->enabled)
214  return 0;
215 
216  if (applying && mp->user_info_dirty)
217  mi = &mp->user_info;
218  else
219  mi = &mp->info;
220 
221  /* collect the infos to be tested into the array */
222  list_for_each_entry(ovl, &mgr->overlays, list) {
223  op = get_ovl_priv(ovl);
224 
225  if (!op->enabled && !op->enabling)
226  oi = NULL;
227  else if (applying && op->user_info_dirty)
228  oi = &op->user_info;
229  else
230  oi = &op->info;
231 
232  ois[ovl->id] = oi;
233  }
234 
235  return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
236 }
237 
238 /*
239  * check manager and overlay settings using overlay_info from data->info
240  */
241 static int dss_check_settings(struct omap_overlay_manager *mgr)
242 {
243  return dss_check_settings_low(mgr, false);
244 }
245 
246 /*
247  * check manager and overlay settings using overlay_info from ovl->info if
248  * dirty and from data->info otherwise
249  */
250 static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
251 {
252  return dss_check_settings_low(mgr, true);
253 }
254 
255 static bool need_isr(void)
256 {
257  const int num_mgrs = dss_feat_get_num_mgrs();
258  int i;
259 
260  for (i = 0; i < num_mgrs; ++i) {
261  struct omap_overlay_manager *mgr;
262  struct mgr_priv_data *mp;
263  struct omap_overlay *ovl;
264 
266  mp = get_mgr_priv(mgr);
267 
268  if (!mp->enabled)
269  continue;
270 
271  if (mgr_manual_update(mgr)) {
272  /* to catch FRAMEDONE */
273  if (mp->updating)
274  return true;
275  } else {
276  /* to catch GO bit going down */
277  if (mp->busy)
278  return true;
279 
280  /* to write new values to registers */
281  if (mp->info_dirty)
282  return true;
283 
284  /* to set GO bit */
285  if (mp->shadow_info_dirty)
286  return true;
287 
288  /*
289  * NOTE: we don't check extra_info flags for disabled
290  * managers, once the manager is enabled, the extra_info
291  * related manager changes will be taken in by HW.
292  */
293 
294  /* to write new values to registers */
295  if (mp->extra_info_dirty)
296  return true;
297 
298  /* to set GO bit */
299  if (mp->shadow_extra_info_dirty)
300  return true;
301 
302  list_for_each_entry(ovl, &mgr->overlays, list) {
303  struct ovl_priv_data *op;
304 
305  op = get_ovl_priv(ovl);
306 
307  /*
308  * NOTE: we check extra_info flags even for
309  * disabled overlays, as extra_infos need to be
310  * always written.
311  */
312 
313  /* to write new values to registers */
314  if (op->extra_info_dirty)
315  return true;
316 
317  /* to set GO bit */
318  if (op->shadow_extra_info_dirty)
319  return true;
320 
321  if (!op->enabled)
322  continue;
323 
324  /* to write new values to registers */
325  if (op->info_dirty)
326  return true;
327 
328  /* to set GO bit */
329  if (op->shadow_info_dirty)
330  return true;
331  }
332  }
333  }
334 
335  return false;
336 }
337 
338 static bool need_go(struct omap_overlay_manager *mgr)
339 {
340  struct omap_overlay *ovl;
341  struct mgr_priv_data *mp;
342  struct ovl_priv_data *op;
343 
344  mp = get_mgr_priv(mgr);
345 
347  return true;
348 
349  list_for_each_entry(ovl, &mgr->overlays, list) {
350  op = get_ovl_priv(ovl);
352  return true;
353  }
354 
355  return false;
356 }
357 
358 /* returns true if an extra_info field is currently being updated */
359 static bool extra_info_update_ongoing(void)
360 {
361  const int num_mgrs = dss_feat_get_num_mgrs();
362  int i;
363 
364  for (i = 0; i < num_mgrs; ++i) {
365  struct omap_overlay_manager *mgr;
366  struct omap_overlay *ovl;
367  struct mgr_priv_data *mp;
368 
370  mp = get_mgr_priv(mgr);
371 
372  if (!mp->enabled)
373  continue;
374 
375  if (!mp->updating)
376  continue;
377 
379  return true;
380 
381  list_for_each_entry(ovl, &mgr->overlays, list) {
382  struct ovl_priv_data *op = get_ovl_priv(ovl);
383 
385  return true;
386  }
387  }
388 
389  return false;
390 }
391 
392 /* wait until no extra_info updates are pending */
393 static void wait_pending_extra_info_updates(void)
394 {
395  bool updating;
396  unsigned long flags;
397  unsigned long t;
398  int r;
399 
400  spin_lock_irqsave(&data_lock, flags);
401 
402  updating = extra_info_update_ongoing();
403 
404  if (!updating) {
405  spin_unlock_irqrestore(&data_lock, flags);
406  return;
407  }
408 
409  init_completion(&extra_updated_completion);
410 
411  spin_unlock_irqrestore(&data_lock, flags);
412 
413  t = msecs_to_jiffies(500);
414  r = wait_for_completion_timeout(&extra_updated_completion, t);
415  if (r == 0)
416  DSSWARN("timeout in wait_pending_extra_info_updates\n");
417  else if (r < 0)
418  DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
419 }
420 
422 {
423  unsigned long timeout = msecs_to_jiffies(500);
424  struct mgr_priv_data *mp = get_mgr_priv(mgr);
425  u32 irq;
426  unsigned long flags;
427  int r;
428  int i;
429 
430  spin_lock_irqsave(&data_lock, flags);
431 
432  if (mgr_manual_update(mgr)) {
433  spin_unlock_irqrestore(&data_lock, flags);
434  return 0;
435  }
436 
437  if (!mp->enabled) {
438  spin_unlock_irqrestore(&data_lock, flags);
439  return 0;
440  }
441 
442  spin_unlock_irqrestore(&data_lock, flags);
443 
444  r = dispc_runtime_get();
445  if (r)
446  return r;
447 
448  irq = dispc_mgr_get_vsync_irq(mgr->id);
449 
450  i = 0;
451  while (1) {
452  bool shadow_dirty, dirty;
453 
454  spin_lock_irqsave(&data_lock, flags);
455  dirty = mp->info_dirty;
456  shadow_dirty = mp->shadow_info_dirty;
457  spin_unlock_irqrestore(&data_lock, flags);
458 
459  if (!dirty && !shadow_dirty) {
460  r = 0;
461  break;
462  }
463 
464  /* 4 iterations is the worst case:
465  * 1 - initial iteration, dirty = true (between VFP and VSYNC)
466  * 2 - first VSYNC, dirty = true
467  * 3 - dirty = false, shadow_dirty = true
468  * 4 - shadow_dirty = false */
469  if (i++ == 3) {
470  DSSERR("mgr(%d)->wait_for_go() not finishing\n",
471  mgr->id);
472  r = 0;
473  break;
474  }
475 
477  if (r == -ERESTARTSYS)
478  break;
479 
480  if (r) {
481  DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
482  break;
483  }
484  }
485 
487 
488  return r;
489 }
490 
492 {
493  unsigned long timeout = msecs_to_jiffies(500);
494  struct ovl_priv_data *op;
495  struct mgr_priv_data *mp;
496  u32 irq;
497  unsigned long flags;
498  int r;
499  int i;
500 
501  if (!ovl->manager)
502  return 0;
503 
504  mp = get_mgr_priv(ovl->manager);
505 
506  spin_lock_irqsave(&data_lock, flags);
507 
508  if (ovl_manual_update(ovl)) {
509  spin_unlock_irqrestore(&data_lock, flags);
510  return 0;
511  }
512 
513  if (!mp->enabled) {
514  spin_unlock_irqrestore(&data_lock, flags);
515  return 0;
516  }
517 
518  spin_unlock_irqrestore(&data_lock, flags);
519 
520  r = dispc_runtime_get();
521  if (r)
522  return r;
523 
524  irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
525 
526  op = get_ovl_priv(ovl);
527  i = 0;
528  while (1) {
529  bool shadow_dirty, dirty;
530 
531  spin_lock_irqsave(&data_lock, flags);
532  dirty = op->info_dirty;
533  shadow_dirty = op->shadow_info_dirty;
534  spin_unlock_irqrestore(&data_lock, flags);
535 
536  if (!dirty && !shadow_dirty) {
537  r = 0;
538  break;
539  }
540 
541  /* 4 iterations is the worst case:
542  * 1 - initial iteration, dirty = true (between VFP and VSYNC)
543  * 2 - first VSYNC, dirty = true
544  * 3 - dirty = false, shadow_dirty = true
545  * 4 - shadow_dirty = false */
546  if (i++ == 3) {
547  DSSERR("ovl(%d)->wait_for_go() not finishing\n",
548  ovl->id);
549  r = 0;
550  break;
551  }
552 
554  if (r == -ERESTARTSYS)
555  break;
556 
557  if (r) {
558  DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
559  break;
560  }
561  }
562 
564 
565  return r;
566 }
567 
568 static void dss_ovl_write_regs(struct omap_overlay *ovl)
569 {
570  struct ovl_priv_data *op = get_ovl_priv(ovl);
571  struct omap_overlay_info *oi;
572  bool replication;
573  struct mgr_priv_data *mp;
574  int r;
575 
576  DSSDBGF("%d", ovl->id);
577 
578  if (!op->enabled || !op->info_dirty)
579  return;
580 
581  oi = &op->info;
582 
583  mp = get_mgr_priv(ovl->manager);
584 
585  replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
586 
587  r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
588  if (r) {
589  /*
590  * We can't do much here, as this function can be called from
591  * vsync interrupt.
592  */
593  DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
594 
595  /* This will leave fifo configurations in a nonoptimal state */
596  op->enabled = false;
597  dispc_ovl_enable(ovl->id, false);
598  return;
599  }
600 
601  op->info_dirty = false;
602  if (mp->updating)
603  op->shadow_info_dirty = true;
604 }
605 
606 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
607 {
608  struct ovl_priv_data *op = get_ovl_priv(ovl);
609  struct mgr_priv_data *mp;
610 
611  DSSDBGF("%d", ovl->id);
612 
613  if (!op->extra_info_dirty)
614  return;
615 
616  /* note: write also when op->enabled == false, so that the ovl gets
617  * disabled */
618 
619  dispc_ovl_enable(ovl->id, op->enabled);
622 
623  mp = get_mgr_priv(ovl->manager);
624 
625  op->extra_info_dirty = false;
626  if (mp->updating)
627  op->shadow_extra_info_dirty = true;
628 }
629 
630 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
631 {
632  struct mgr_priv_data *mp = get_mgr_priv(mgr);
633  struct omap_overlay *ovl;
634 
635  DSSDBGF("%d", mgr->id);
636 
637  if (!mp->enabled)
638  return;
639 
640  WARN_ON(mp->busy);
641 
642  /* Commit overlay settings */
643  list_for_each_entry(ovl, &mgr->overlays, list) {
644  dss_ovl_write_regs(ovl);
645  dss_ovl_write_regs_extra(ovl);
646  }
647 
648  if (mp->info_dirty) {
649  dispc_mgr_setup(mgr->id, &mp->info);
650 
651  mp->info_dirty = false;
652  if (mp->updating)
653  mp->shadow_info_dirty = true;
654  }
655 }
656 
657 static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
658 {
659  struct mgr_priv_data *mp = get_mgr_priv(mgr);
660 
661  DSSDBGF("%d", mgr->id);
662 
663  if (!mp->extra_info_dirty)
664  return;
665 
666  dispc_mgr_set_timings(mgr->id, &mp->timings);
667 
668  /* lcd_config parameters */
669  if (dss_mgr_is_lcd(mgr->id)) {
670  dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
671 
672  dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
674  mp->lcd_config.fifohandcheck);
675 
676  dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
677 
679  mp->lcd_config.video_port_width);
680 
681  dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
682 
684  }
685 
686  mp->extra_info_dirty = false;
687  if (mp->updating)
688  mp->shadow_extra_info_dirty = true;
689 }
690 
691 static void dss_write_regs(void)
692 {
693  const int num_mgrs = omap_dss_get_num_overlay_managers();
694  int i;
695 
696  for (i = 0; i < num_mgrs; ++i) {
697  struct omap_overlay_manager *mgr;
698  struct mgr_priv_data *mp;
699  int r;
700 
702  mp = get_mgr_priv(mgr);
703 
704  if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
705  continue;
706 
707  r = dss_check_settings(mgr);
708  if (r) {
709  DSSERR("cannot write registers for manager %s: "
710  "illegal configuration\n", mgr->name);
711  continue;
712  }
713 
714  dss_mgr_write_regs(mgr);
715  dss_mgr_write_regs_extra(mgr);
716  }
717 }
718 
719 static void dss_set_go_bits(void)
720 {
721  const int num_mgrs = omap_dss_get_num_overlay_managers();
722  int i;
723 
724  for (i = 0; i < num_mgrs; ++i) {
725  struct omap_overlay_manager *mgr;
726  struct mgr_priv_data *mp;
727 
729  mp = get_mgr_priv(mgr);
730 
731  if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
732  continue;
733 
734  if (!need_go(mgr))
735  continue;
736 
737  mp->busy = true;
738 
739  if (!dss_data.irq_enabled && need_isr())
740  dss_register_vsync_isr();
741 
742  dispc_mgr_go(mgr->id);
743  }
744 
745 }
746 
747 static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
748 {
749  struct omap_overlay *ovl;
750  struct mgr_priv_data *mp;
751  struct ovl_priv_data *op;
752 
753  mp = get_mgr_priv(mgr);
754  mp->shadow_info_dirty = false;
755  mp->shadow_extra_info_dirty = false;
756 
757  list_for_each_entry(ovl, &mgr->overlays, list) {
758  op = get_ovl_priv(ovl);
759  op->shadow_info_dirty = false;
760  op->shadow_extra_info_dirty = false;
761  }
762 }
763 
765 {
766  struct mgr_priv_data *mp = get_mgr_priv(mgr);
767  unsigned long flags;
768  int r;
769 
770  spin_lock_irqsave(&data_lock, flags);
771 
772  WARN_ON(mp->updating);
773 
774  r = dss_check_settings(mgr);
775  if (r) {
776  DSSERR("cannot start manual update: illegal configuration\n");
777  spin_unlock_irqrestore(&data_lock, flags);
778  return;
779  }
780 
781  dss_mgr_write_regs(mgr);
782  dss_mgr_write_regs_extra(mgr);
783 
784  mp->updating = true;
785 
786  if (!dss_data.irq_enabled && need_isr())
787  dss_register_vsync_isr();
788 
789  dispc_mgr_enable(mgr->id, true);
790 
791  mgr_clear_shadow_dirty(mgr);
792 
793  spin_unlock_irqrestore(&data_lock, flags);
794 }
795 
796 static void dss_apply_irq_handler(void *data, u32 mask);
797 
798 static void dss_register_vsync_isr(void)
799 {
800  const int num_mgrs = dss_feat_get_num_mgrs();
801  u32 mask;
802  int r, i;
803 
804  mask = 0;
805  for (i = 0; i < num_mgrs; ++i)
806  mask |= dispc_mgr_get_vsync_irq(i);
807 
808  for (i = 0; i < num_mgrs; ++i)
809  mask |= dispc_mgr_get_framedone_irq(i);
810 
811  r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
812  WARN_ON(r);
813 
814  dss_data.irq_enabled = true;
815 }
816 
817 static void dss_unregister_vsync_isr(void)
818 {
819  const int num_mgrs = dss_feat_get_num_mgrs();
820  u32 mask;
821  int r, i;
822 
823  mask = 0;
824  for (i = 0; i < num_mgrs; ++i)
825  mask |= dispc_mgr_get_vsync_irq(i);
826 
827  for (i = 0; i < num_mgrs; ++i)
828  mask |= dispc_mgr_get_framedone_irq(i);
829 
830  r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
831  WARN_ON(r);
832 
833  dss_data.irq_enabled = false;
834 }
835 
836 static void dss_apply_irq_handler(void *data, u32 mask)
837 {
838  const int num_mgrs = dss_feat_get_num_mgrs();
839  int i;
840  bool extra_updating;
841 
842  spin_lock(&data_lock);
843 
844  /* clear busy, updating flags, shadow_dirty flags */
845  for (i = 0; i < num_mgrs; i++) {
846  struct omap_overlay_manager *mgr;
847  struct mgr_priv_data *mp;
848  bool was_updating;
849 
851  mp = get_mgr_priv(mgr);
852 
853  if (!mp->enabled)
854  continue;
855 
856  was_updating = mp->updating;
858 
859  if (!mgr_manual_update(mgr)) {
860  bool was_busy = mp->busy;
861  mp->busy = dispc_mgr_go_busy(i);
862 
863  if (was_busy && !mp->busy)
864  mgr_clear_shadow_dirty(mgr);
865  }
866  }
867 
868  dss_write_regs();
869  dss_set_go_bits();
870 
871  extra_updating = extra_info_update_ongoing();
872  if (!extra_updating)
873  complete_all(&extra_updated_completion);
874 
875  if (!need_isr())
876  dss_unregister_vsync_isr();
877 
878  spin_unlock(&data_lock);
879 }
880 
881 static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
882 {
883  struct ovl_priv_data *op;
884 
885  op = get_ovl_priv(ovl);
886 
887  if (!op->user_info_dirty)
888  return;
889 
890  op->user_info_dirty = false;
891  op->info_dirty = true;
892  op->info = op->user_info;
893 }
894 
895 static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
896 {
897  struct mgr_priv_data *mp;
898 
899  mp = get_mgr_priv(mgr);
900 
901  if (!mp->user_info_dirty)
902  return;
903 
904  mp->user_info_dirty = false;
905  mp->info_dirty = true;
906  mp->info = mp->user_info;
907 }
908 
910 {
911  unsigned long flags;
912  struct omap_overlay *ovl;
913  int r;
914 
915  DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
916 
917  spin_lock_irqsave(&data_lock, flags);
918 
919  r = dss_check_settings_apply(mgr);
920  if (r) {
921  spin_unlock_irqrestore(&data_lock, flags);
922  DSSERR("failed to apply settings: illegal configuration.\n");
923  return r;
924  }
925 
926  /* Configure overlays */
927  list_for_each_entry(ovl, &mgr->overlays, list)
928  omap_dss_mgr_apply_ovl(ovl);
929 
930  /* Configure manager */
931  omap_dss_mgr_apply_mgr(mgr);
932 
933  dss_write_regs();
934  dss_set_go_bits();
935 
936  spin_unlock_irqrestore(&data_lock, flags);
937 
938  return 0;
939 }
940 
941 static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
942 {
943  struct ovl_priv_data *op;
944 
945  op = get_ovl_priv(ovl);
946 
947  if (op->enabled == enable)
948  return;
949 
950  op->enabled = enable;
951  op->extra_info_dirty = true;
952 }
953 
954 static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
956 {
957  struct ovl_priv_data *op = get_ovl_priv(ovl);
958 
959  if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
960  return;
961 
962  op->fifo_low = fifo_low;
963  op->fifo_high = fifo_high;
964  op->extra_info_dirty = true;
965 }
966 
967 static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
968 {
969  struct ovl_priv_data *op = get_ovl_priv(ovl);
971  bool use_fifo_merge = false;
972 
973  if (!op->enabled && !op->enabling)
974  return;
975 
976  dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
977  use_fifo_merge, ovl_manual_update(ovl));
978 
979  dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
980 }
981 
982 static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
983 {
984  struct omap_overlay *ovl;
985  struct mgr_priv_data *mp;
986 
987  mp = get_mgr_priv(mgr);
988 
989  if (!mp->enabled)
990  return;
991 
992  list_for_each_entry(ovl, &mgr->overlays, list)
993  dss_ovl_setup_fifo(ovl);
994 }
995 
996 static void dss_setup_fifos(void)
997 {
998  const int num_mgrs = omap_dss_get_num_overlay_managers();
999  struct omap_overlay_manager *mgr;
1000  int i;
1001 
1002  for (i = 0; i < num_mgrs; ++i) {
1004  dss_mgr_setup_fifos(mgr);
1005  }
1006 }
1007 
1009 {
1010  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1011  unsigned long flags;
1012  int r;
1013 
1014  mutex_lock(&apply_lock);
1015 
1016  if (mp->enabled)
1017  goto out;
1018 
1019  spin_lock_irqsave(&data_lock, flags);
1020 
1021  mp->enabled = true;
1022 
1023  r = dss_check_settings(mgr);
1024  if (r) {
1025  DSSERR("failed to enable manager %d: check_settings failed\n",
1026  mgr->id);
1027  goto err;
1028  }
1029 
1030  dss_setup_fifos();
1031 
1032  dss_write_regs();
1033  dss_set_go_bits();
1034 
1035  if (!mgr_manual_update(mgr))
1036  mp->updating = true;
1037 
1038  spin_unlock_irqrestore(&data_lock, flags);
1039 
1040  if (!mgr_manual_update(mgr))
1041  dispc_mgr_enable(mgr->id, true);
1042 
1043 out:
1044  mutex_unlock(&apply_lock);
1045 
1046  return 0;
1047 
1048 err:
1049  mp->enabled = false;
1050  spin_unlock_irqrestore(&data_lock, flags);
1051  mutex_unlock(&apply_lock);
1052  return r;
1053 }
1054 
1056 {
1057  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1058  unsigned long flags;
1059 
1060  mutex_lock(&apply_lock);
1061 
1062  if (!mp->enabled)
1063  goto out;
1064 
1065  if (!mgr_manual_update(mgr))
1066  dispc_mgr_enable(mgr->id, false);
1067 
1068  spin_lock_irqsave(&data_lock, flags);
1069 
1070  mp->updating = false;
1071  mp->enabled = false;
1072 
1073  spin_unlock_irqrestore(&data_lock, flags);
1074 
1075 out:
1076  mutex_unlock(&apply_lock);
1077 }
1078 
1081 {
1082  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1083  unsigned long flags;
1084  int r;
1085 
1086  r = dss_mgr_simple_check(mgr, info);
1087  if (r)
1088  return r;
1089 
1090  spin_lock_irqsave(&data_lock, flags);
1091 
1092  mp->user_info = *info;
1093  mp->user_info_dirty = true;
1094 
1095  spin_unlock_irqrestore(&data_lock, flags);
1096 
1097  return 0;
1098 }
1099 
1102 {
1103  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1104  unsigned long flags;
1105 
1106  spin_lock_irqsave(&data_lock, flags);
1107 
1108  *info = mp->user_info;
1109 
1110  spin_unlock_irqrestore(&data_lock, flags);
1111 }
1112 
1114  struct omap_dss_output *output)
1115 {
1116  int r;
1117 
1118  mutex_lock(&apply_lock);
1119 
1120  if (mgr->output) {
1121  DSSERR("manager %s is already connected to an output\n",
1122  mgr->name);
1123  r = -EINVAL;
1124  goto err;
1125  }
1126 
1127  if ((mgr->supported_outputs & output->id) == 0) {
1128  DSSERR("output does not support manager %s\n",
1129  mgr->name);
1130  r = -EINVAL;
1131  goto err;
1132  }
1133 
1134  output->manager = mgr;
1135  mgr->output = output;
1136 
1137  mutex_unlock(&apply_lock);
1138 
1139  return 0;
1140 err:
1141  mutex_unlock(&apply_lock);
1142  return r;
1143 }
1144 
1146 {
1147  int r;
1148  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1149  unsigned long flags;
1150 
1151  mutex_lock(&apply_lock);
1152 
1153  if (!mgr->output) {
1154  DSSERR("failed to unset output, output not set\n");
1155  r = -EINVAL;
1156  goto err;
1157  }
1158 
1159  spin_lock_irqsave(&data_lock, flags);
1160 
1161  if (mp->enabled) {
1162  DSSERR("output can't be unset when manager is enabled\n");
1163  r = -EINVAL;
1164  goto err1;
1165  }
1166 
1167  spin_unlock_irqrestore(&data_lock, flags);
1168 
1169  mgr->output->manager = NULL;
1170  mgr->output = NULL;
1171 
1172  mutex_unlock(&apply_lock);
1173 
1174  return 0;
1175 err1:
1176  spin_unlock_irqrestore(&data_lock, flags);
1177 err:
1178  mutex_unlock(&apply_lock);
1179 
1180  return r;
1181 }
1182 
1183 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1184  const struct omap_video_timings *timings)
1185 {
1186  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1187 
1188  mp->timings = *timings;
1189  mp->extra_info_dirty = true;
1190 }
1191 
1193  const struct omap_video_timings *timings)
1194 {
1195  unsigned long flags;
1196  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1197 
1198  spin_lock_irqsave(&data_lock, flags);
1199 
1200  if (mp->updating) {
1201  DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1202  mgr->name);
1203  goto out;
1204  }
1205 
1206  dss_apply_mgr_timings(mgr, timings);
1207 out:
1208  spin_unlock_irqrestore(&data_lock, flags);
1209 }
1210 
1211 static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1212  const struct dss_lcd_mgr_config *config)
1213 {
1214  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1215 
1216  mp->lcd_config = *config;
1217  mp->extra_info_dirty = true;
1218 }
1219 
1221  const struct dss_lcd_mgr_config *config)
1222 {
1223  unsigned long flags;
1224  struct mgr_priv_data *mp = get_mgr_priv(mgr);
1225 
1226  spin_lock_irqsave(&data_lock, flags);
1227 
1228  if (mp->enabled) {
1229  DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1230  mgr->name);
1231  goto out;
1232  }
1233 
1234  dss_apply_mgr_lcd_config(mgr, config);
1235 out:
1236  spin_unlock_irqrestore(&data_lock, flags);
1237 }
1238 
1240  struct omap_overlay_info *info)
1241 {
1242  struct ovl_priv_data *op = get_ovl_priv(ovl);
1243  unsigned long flags;
1244  int r;
1245 
1246  r = dss_ovl_simple_check(ovl, info);
1247  if (r)
1248  return r;
1249 
1250  spin_lock_irqsave(&data_lock, flags);
1251 
1252  op->user_info = *info;
1253  op->user_info_dirty = true;
1254 
1255  spin_unlock_irqrestore(&data_lock, flags);
1256 
1257  return 0;
1258 }
1259 
1261  struct omap_overlay_info *info)
1262 {
1263  struct ovl_priv_data *op = get_ovl_priv(ovl);
1264  unsigned long flags;
1265 
1266  spin_lock_irqsave(&data_lock, flags);
1267 
1268  *info = op->user_info;
1269 
1270  spin_unlock_irqrestore(&data_lock, flags);
1271 }
1272 
1274  struct omap_overlay_manager *mgr)
1275 {
1276  struct ovl_priv_data *op = get_ovl_priv(ovl);
1277  unsigned long flags;
1278  int r;
1279 
1280  if (!mgr)
1281  return -EINVAL;
1282 
1283  mutex_lock(&apply_lock);
1284 
1285  if (ovl->manager) {
1286  DSSERR("overlay '%s' already has a manager '%s'\n",
1287  ovl->name, ovl->manager->name);
1288  r = -EINVAL;
1289  goto err;
1290  }
1291 
1292  spin_lock_irqsave(&data_lock, flags);
1293 
1294  if (op->enabled) {
1295  spin_unlock_irqrestore(&data_lock, flags);
1296  DSSERR("overlay has to be disabled to change the manager\n");
1297  r = -EINVAL;
1298  goto err;
1299  }
1300 
1301  op->channel = mgr->id;
1302  op->extra_info_dirty = true;
1303 
1304  ovl->manager = mgr;
1305  list_add_tail(&ovl->list, &mgr->overlays);
1306 
1307  spin_unlock_irqrestore(&data_lock, flags);
1308 
1309  /* XXX: When there is an overlay on a DSI manual update display, and
1310  * the overlay is first disabled, then moved to tv, and enabled, we
1311  * seem to get SYNC_LOST_DIGIT error.
1312  *
1313  * Waiting doesn't seem to help, but updating the manual update display
1314  * after disabling the overlay seems to fix this. This hints that the
1315  * overlay is perhaps somehow tied to the LCD output until the output
1316  * is updated.
1317  *
1318  * Userspace workaround for this is to update the LCD after disabling
1319  * the overlay, but before moving the overlay to TV.
1320  */
1321 
1322  mutex_unlock(&apply_lock);
1323 
1324  return 0;
1325 err:
1326  mutex_unlock(&apply_lock);
1327  return r;
1328 }
1329 
1331 {
1332  struct ovl_priv_data *op = get_ovl_priv(ovl);
1333  unsigned long flags;
1334  int r;
1335 
1336  mutex_lock(&apply_lock);
1337 
1338  if (!ovl->manager) {
1339  DSSERR("failed to detach overlay: manager not set\n");
1340  r = -EINVAL;
1341  goto err;
1342  }
1343 
1344  spin_lock_irqsave(&data_lock, flags);
1345 
1346  if (op->enabled) {
1347  spin_unlock_irqrestore(&data_lock, flags);
1348  DSSERR("overlay has to be disabled to unset the manager\n");
1349  r = -EINVAL;
1350  goto err;
1351  }
1352 
1353  spin_unlock_irqrestore(&data_lock, flags);
1354 
1355  /* wait for pending extra_info updates to ensure the ovl is disabled */
1356  wait_pending_extra_info_updates();
1357 
1358  spin_lock_irqsave(&data_lock, flags);
1359 
1360  op->channel = -1;
1361 
1362  ovl->manager = NULL;
1363  list_del(&ovl->list);
1364 
1365  spin_unlock_irqrestore(&data_lock, flags);
1366 
1367  mutex_unlock(&apply_lock);
1368 
1369  return 0;
1370 err:
1371  mutex_unlock(&apply_lock);
1372  return r;
1373 }
1374 
1376 {
1377  struct ovl_priv_data *op = get_ovl_priv(ovl);
1378  unsigned long flags;
1379  bool e;
1380 
1381  spin_lock_irqsave(&data_lock, flags);
1382 
1383  e = op->enabled;
1384 
1385  spin_unlock_irqrestore(&data_lock, flags);
1386 
1387  return e;
1388 }
1389 
1391 {
1392  struct ovl_priv_data *op = get_ovl_priv(ovl);
1393  unsigned long flags;
1394  int r;
1395 
1396  mutex_lock(&apply_lock);
1397 
1398  if (op->enabled) {
1399  r = 0;
1400  goto err1;
1401  }
1402 
1403  if (ovl->manager == NULL || ovl->manager->output == NULL) {
1404  r = -EINVAL;
1405  goto err1;
1406  }
1407 
1408  spin_lock_irqsave(&data_lock, flags);
1409 
1410  op->enabling = true;
1411 
1412  r = dss_check_settings(ovl->manager);
1413  if (r) {
1414  DSSERR("failed to enable overlay %d: check_settings failed\n",
1415  ovl->id);
1416  goto err2;
1417  }
1418 
1419  dss_setup_fifos();
1420 
1421  op->enabling = false;
1422  dss_apply_ovl_enable(ovl, true);
1423 
1424  dss_write_regs();
1425  dss_set_go_bits();
1426 
1427  spin_unlock_irqrestore(&data_lock, flags);
1428 
1429  mutex_unlock(&apply_lock);
1430 
1431  return 0;
1432 err2:
1433  op->enabling = false;
1434  spin_unlock_irqrestore(&data_lock, flags);
1435 err1:
1436  mutex_unlock(&apply_lock);
1437  return r;
1438 }
1439 
1441 {
1442  struct ovl_priv_data *op = get_ovl_priv(ovl);
1443  unsigned long flags;
1444  int r;
1445 
1446  mutex_lock(&apply_lock);
1447 
1448  if (!op->enabled) {
1449  r = 0;
1450  goto err;
1451  }
1452 
1453  if (ovl->manager == NULL || ovl->manager->output == NULL) {
1454  r = -EINVAL;
1455  goto err;
1456  }
1457 
1458  spin_lock_irqsave(&data_lock, flags);
1459 
1460  dss_apply_ovl_enable(ovl, false);
1461  dss_write_regs();
1462  dss_set_go_bits();
1463 
1464  spin_unlock_irqrestore(&data_lock, flags);
1465 
1466  mutex_unlock(&apply_lock);
1467 
1468  return 0;
1469 
1470 err:
1471  mutex_unlock(&apply_lock);
1472  return r;
1473 }
1474