Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / video / omap2 / dss / overlay.c
1 /*
2  * linux/drivers/video/omap2/dss/overlay.c
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #define DSS_SUBSYS_NAME "OVERLAY"
24
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/err.h>
28 #include <linux/sysfs.h>
29 #include <linux/kobject.h>
30 #include <linux/platform_device.h>
31 #include <linux/delay.h>
32 #include <linux/slab.h>
33
34 #include <video/omapdss.h>
35 #include <plat/cpu.h>
36
37 #include "dss.h"
38 #include "dss_features.h"
39
40 static int num_overlays;
41 static struct list_head overlay_list;
42
43 static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
44 {
45         return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
46 }
47
48 static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
49 {
50         return snprintf(buf, PAGE_SIZE, "%s\n",
51                         ovl->manager ? ovl->manager->name : "<none>");
52 }
53
54 static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
55                 size_t size)
56 {
57         int i, r;
58         struct omap_overlay_manager *mgr = NULL;
59         struct omap_overlay_manager *old_mgr;
60         int len = size;
61
62         if (buf[size-1] == '\n')
63                 --len;
64
65         if (len > 0) {
66                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
67                         mgr = omap_dss_get_overlay_manager(i);
68
69                         if (sysfs_streq(buf, mgr->name))
70                                 break;
71
72                         mgr = NULL;
73                 }
74         }
75
76         if (len > 0 && mgr == NULL)
77                 return -EINVAL;
78
79         if (mgr)
80                 DSSDBG("manager %s found\n", mgr->name);
81
82         if (mgr == ovl->manager)
83                 return size;
84
85         old_mgr = ovl->manager;
86
87         r = dispc_runtime_get();
88         if (r)
89                 return r;
90
91         /* detach old manager */
92         if (old_mgr) {
93                 r = ovl->unset_manager(ovl);
94                 if (r) {
95                         DSSERR("detach failed\n");
96                         goto err;
97                 }
98
99                 r = old_mgr->apply(old_mgr);
100                 if (r)
101                         goto err;
102         }
103
104         if (mgr) {
105                 r = ovl->set_manager(ovl, mgr);
106                 if (r) {
107                         DSSERR("Failed to attach overlay\n");
108                         goto err;
109                 }
110
111                 r = mgr->apply(mgr);
112                 if (r)
113                         goto err;
114         }
115
116         dispc_runtime_put();
117
118         return size;
119
120 err:
121         dispc_runtime_put();
122         return r;
123 }
124
125 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
126 {
127         return snprintf(buf, PAGE_SIZE, "%d,%d\n",
128                         ovl->info.width, ovl->info.height);
129 }
130
131 static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
132 {
133         return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
134 }
135
136 static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
137 {
138         return snprintf(buf, PAGE_SIZE, "%d,%d\n",
139                         ovl->info.pos_x, ovl->info.pos_y);
140 }
141
142 static ssize_t overlay_position_store(struct omap_overlay *ovl,
143                 const char *buf, size_t size)
144 {
145         int r;
146         char *last;
147         struct omap_overlay_info info;
148
149         ovl->get_overlay_info(ovl, &info);
150
151         info.pos_x = simple_strtoul(buf, &last, 10);
152         ++last;
153         if (last - buf >= size)
154                 return -EINVAL;
155
156         info.pos_y = simple_strtoul(last, &last, 10);
157
158         r = ovl->set_overlay_info(ovl, &info);
159         if (r)
160                 return r;
161
162         if (ovl->manager) {
163                 r = ovl->manager->apply(ovl->manager);
164                 if (r)
165                         return r;
166         }
167
168         return size;
169 }
170
171 static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
172 {
173         return snprintf(buf, PAGE_SIZE, "%d,%d\n",
174                         ovl->info.out_width, ovl->info.out_height);
175 }
176
177 static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
178                 const char *buf, size_t size)
179 {
180         int r;
181         char *last;
182         struct omap_overlay_info info;
183
184         ovl->get_overlay_info(ovl, &info);
185
186         info.out_width = simple_strtoul(buf, &last, 10);
187         ++last;
188         if (last - buf >= size)
189                 return -EINVAL;
190
191         info.out_height = simple_strtoul(last, &last, 10);
192
193         r = ovl->set_overlay_info(ovl, &info);
194         if (r)
195                 return r;
196
197         if (ovl->manager) {
198                 r = ovl->manager->apply(ovl->manager);
199                 if (r)
200                         return r;
201         }
202
203         return size;
204 }
205
206 static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
207 {
208         return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
209 }
210
211 static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
212                 size_t size)
213 {
214         int r;
215         bool enable;
216         struct omap_overlay_info info;
217
218         ovl->get_overlay_info(ovl, &info);
219
220         r = strtobool(buf, &enable);
221         if (r)
222                 return r;
223
224         info.enabled = enable;
225
226         r = ovl->set_overlay_info(ovl, &info);
227         if (r)
228                 return r;
229
230         if (ovl->manager) {
231                 r = ovl->manager->apply(ovl->manager);
232                 if (r)
233                         return r;
234         }
235
236         return size;
237 }
238
239 static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240 {
241         return snprintf(buf, PAGE_SIZE, "%d\n",
242                         ovl->info.global_alpha);
243 }
244
245 static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
246                 const char *buf, size_t size)
247 {
248         int r;
249         u8 alpha;
250         struct omap_overlay_info info;
251
252         if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
253                 return -ENODEV;
254
255         r = kstrtou8(buf, 0, &alpha);
256         if (r)
257                 return r;
258
259         ovl->get_overlay_info(ovl, &info);
260
261         info.global_alpha = alpha;
262
263         r = ovl->set_overlay_info(ovl, &info);
264         if (r)
265                 return r;
266
267         if (ovl->manager) {
268                 r = ovl->manager->apply(ovl->manager);
269                 if (r)
270                         return r;
271         }
272
273         return size;
274 }
275
276 static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
277                 char *buf)
278 {
279         return snprintf(buf, PAGE_SIZE, "%d\n",
280                         ovl->info.pre_mult_alpha);
281 }
282
283 static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
284                 const char *buf, size_t size)
285 {
286         int r;
287         u8 alpha;
288         struct omap_overlay_info info;
289
290         if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
291                 return -ENODEV;
292
293         r = kstrtou8(buf, 0, &alpha);
294         if (r)
295                 return r;
296
297         ovl->get_overlay_info(ovl, &info);
298
299         info.pre_mult_alpha = alpha;
300
301         r = ovl->set_overlay_info(ovl, &info);
302         if (r)
303                 return r;
304
305         if (ovl->manager) {
306                 r = ovl->manager->apply(ovl->manager);
307                 if (r)
308                         return r;
309         }
310
311         return size;
312 }
313
314 static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
315 {
316         return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
317 }
318
319 static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
320                 const char *buf, size_t size)
321 {
322         int r;
323         u8 zorder;
324         struct omap_overlay_info info;
325
326         if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
327                 return -ENODEV;
328
329         r = kstrtou8(buf, 0, &zorder);
330         if (r)
331                 return r;
332
333         ovl->get_overlay_info(ovl, &info);
334
335         info.zorder = zorder;
336
337         r = ovl->set_overlay_info(ovl, &info);
338         if (r)
339                 return r;
340
341         if (ovl->manager) {
342                 r = ovl->manager->apply(ovl->manager);
343                 if (r)
344                         return r;
345         }
346
347         return size;
348 }
349
350 struct overlay_attribute {
351         struct attribute attr;
352         ssize_t (*show)(struct omap_overlay *, char *);
353         ssize_t (*store)(struct omap_overlay *, const char *, size_t);
354 };
355
356 #define OVERLAY_ATTR(_name, _mode, _show, _store) \
357         struct overlay_attribute overlay_attr_##_name = \
358         __ATTR(_name, _mode, _show, _store)
359
360 static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
361 static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
362                 overlay_manager_show, overlay_manager_store);
363 static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
364 static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
365 static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
366                 overlay_position_show, overlay_position_store);
367 static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
368                 overlay_output_size_show, overlay_output_size_store);
369 static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
370                 overlay_enabled_show, overlay_enabled_store);
371 static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
372                 overlay_global_alpha_show, overlay_global_alpha_store);
373 static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
374                 overlay_pre_mult_alpha_show,
375                 overlay_pre_mult_alpha_store);
376 static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
377                 overlay_zorder_show, overlay_zorder_store);
378
379 static struct attribute *overlay_sysfs_attrs[] = {
380         &overlay_attr_name.attr,
381         &overlay_attr_manager.attr,
382         &overlay_attr_input_size.attr,
383         &overlay_attr_screen_width.attr,
384         &overlay_attr_position.attr,
385         &overlay_attr_output_size.attr,
386         &overlay_attr_enabled.attr,
387         &overlay_attr_global_alpha.attr,
388         &overlay_attr_pre_mult_alpha.attr,
389         &overlay_attr_zorder.attr,
390         NULL
391 };
392
393 static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
394                 char *buf)
395 {
396         struct omap_overlay *overlay;
397         struct overlay_attribute *overlay_attr;
398
399         overlay = container_of(kobj, struct omap_overlay, kobj);
400         overlay_attr = container_of(attr, struct overlay_attribute, attr);
401
402         if (!overlay_attr->show)
403                 return -ENOENT;
404
405         return overlay_attr->show(overlay, buf);
406 }
407
408 static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
409                 const char *buf, size_t size)
410 {
411         struct omap_overlay *overlay;
412         struct overlay_attribute *overlay_attr;
413
414         overlay = container_of(kobj, struct omap_overlay, kobj);
415         overlay_attr = container_of(attr, struct overlay_attribute, attr);
416
417         if (!overlay_attr->store)
418                 return -ENOENT;
419
420         return overlay_attr->store(overlay, buf, size);
421 }
422
423 static const struct sysfs_ops overlay_sysfs_ops = {
424         .show = overlay_attr_show,
425         .store = overlay_attr_store,
426 };
427
428 static struct kobj_type overlay_ktype = {
429         .sysfs_ops = &overlay_sysfs_ops,
430         .default_attrs = overlay_sysfs_attrs,
431 };
432
433 /* Check if overlay parameters are compatible with display */
434 int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
435 {
436         struct omap_overlay_info *info;
437         u16 outw, outh;
438         u16 dw, dh;
439         int i;
440
441         if (!dssdev)
442                 return 0;
443
444         if (!ovl->info.enabled)
445                 return 0;
446
447         info = &ovl->info;
448
449         if (info->paddr == 0) {
450                 DSSDBG("check_overlay failed: paddr 0\n");
451                 return -EINVAL;
452         }
453
454         dssdev->driver->get_resolution(dssdev, &dw, &dh);
455
456         DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
457                         ovl->id,
458                         info->pos_x, info->pos_y,
459                         info->width, info->height,
460                         info->out_width, info->out_height,
461                         dw, dh);
462
463         if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
464                 outw = info->width;
465                 outh = info->height;
466         } else {
467                 if (info->out_width == 0)
468                         outw = info->width;
469                 else
470                         outw = info->out_width;
471
472                 if (info->out_height == 0)
473                         outh = info->height;
474                 else
475                         outh = info->out_height;
476         }
477
478         if (dw < info->pos_x + outw) {
479                 DSSDBG("check_overlay failed 1: %d < %d + %d\n",
480                                 dw, info->pos_x, outw);
481                 return -EINVAL;
482         }
483
484         if (dh < info->pos_y + outh) {
485                 DSSDBG("check_overlay failed 2: %d < %d + %d\n",
486                                 dh, info->pos_y, outh);
487                 return -EINVAL;
488         }
489
490         if ((ovl->supported_modes & info->color_mode) == 0) {
491                 DSSERR("overlay doesn't support mode %d\n", info->color_mode);
492                 return -EINVAL;
493         }
494
495         if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
496                 if (info->zorder < 0 || info->zorder > 3) {
497                         DSSERR("zorder out of range: %d\n",
498                                 info->zorder);
499                         return -EINVAL;
500                 }
501                 /*
502                  * Check that zorder doesn't match with zorder of any other
503                  * overlay which is enabled and is also connected to the same
504                  * manager
505                  */
506                 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
507                         struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
508
509                         if (tmp_ovl->id != ovl->id &&
510                                         tmp_ovl->manager == ovl->manager &&
511                                         tmp_ovl->info.enabled == true &&
512                                         tmp_ovl->info.zorder == info->zorder) {
513                                 DSSERR("%s and %s have same zorder: %d\n",
514                                         ovl->name, tmp_ovl->name, info->zorder);
515                                 return -EINVAL;
516                         }
517                 }
518         }
519
520         return 0;
521 }
522
523 static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
524                 struct omap_overlay_info *info)
525 {
526         int r;
527         struct omap_overlay_info old_info;
528
529         old_info = ovl->info;
530         ovl->info = *info;
531
532         if (ovl->manager) {
533                 r = dss_check_overlay(ovl, ovl->manager->device);
534                 if (r) {
535                         ovl->info = old_info;
536                         return r;
537                 }
538         }
539
540         ovl->info_dirty = true;
541
542         return 0;
543 }
544
545 static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
546                 struct omap_overlay_info *info)
547 {
548         *info = ovl->info;
549 }
550
551 static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
552 {
553         return dss_mgr_wait_for_go_ovl(ovl);
554 }
555
556 static int omap_dss_set_manager(struct omap_overlay *ovl,
557                 struct omap_overlay_manager *mgr)
558 {
559         if (!mgr)
560                 return -EINVAL;
561
562         if (ovl->manager) {
563                 DSSERR("overlay '%s' already has a manager '%s'\n",
564                                 ovl->name, ovl->manager->name);
565                 return -EINVAL;
566         }
567
568         if (ovl->info.enabled) {
569                 DSSERR("overlay has to be disabled to change the manager\n");
570                 return -EINVAL;
571         }
572
573         ovl->manager = mgr;
574         ovl->manager_changed = true;
575
576         /* XXX: When there is an overlay on a DSI manual update display, and
577          * the overlay is first disabled, then moved to tv, and enabled, we
578          * seem to get SYNC_LOST_DIGIT error.
579          *
580          * Waiting doesn't seem to help, but updating the manual update display
581          * after disabling the overlay seems to fix this. This hints that the
582          * overlay is perhaps somehow tied to the LCD output until the output
583          * is updated.
584          *
585          * Userspace workaround for this is to update the LCD after disabling
586          * the overlay, but before moving the overlay to TV.
587          */
588
589         return 0;
590 }
591
592 static int omap_dss_unset_manager(struct omap_overlay *ovl)
593 {
594         if (!ovl->manager) {
595                 DSSERR("failed to detach overlay: manager not set\n");
596                 return -EINVAL;
597         }
598
599         if (ovl->info.enabled) {
600                 DSSERR("overlay has to be disabled to unset the manager\n");
601                 return -EINVAL;
602         }
603
604         ovl->manager = NULL;
605         ovl->manager_changed = true;
606
607         return 0;
608 }
609
610 int omap_dss_get_num_overlays(void)
611 {
612         return num_overlays;
613 }
614 EXPORT_SYMBOL(omap_dss_get_num_overlays);
615
616 struct omap_overlay *omap_dss_get_overlay(int num)
617 {
618         int i = 0;
619         struct omap_overlay *ovl;
620
621         list_for_each_entry(ovl, &overlay_list, list) {
622                 if (i++ == num)
623                         return ovl;
624         }
625
626         return NULL;
627 }
628 EXPORT_SYMBOL(omap_dss_get_overlay);
629
630 static void omap_dss_add_overlay(struct omap_overlay *overlay)
631 {
632         ++num_overlays;
633         list_add_tail(&overlay->list, &overlay_list);
634 }
635
636 static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
637
638 void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
639 {
640         mgr->num_overlays = dss_feat_get_num_ovls();
641         mgr->overlays = dispc_overlays;
642 }
643
644 #ifdef L4_EXAMPLE
645 static struct omap_overlay *l4_overlays[1];
646 void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
647 {
648         mgr->num_overlays = 1;
649         mgr->overlays = l4_overlays;
650 }
651 #endif
652
653 void dss_init_overlays(struct platform_device *pdev)
654 {
655         int i, r;
656
657         INIT_LIST_HEAD(&overlay_list);
658
659         num_overlays = 0;
660
661         for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
662                 struct omap_overlay *ovl;
663                 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
664
665                 BUG_ON(ovl == NULL);
666
667                 switch (i) {
668                 case 0:
669                         ovl->name = "gfx";
670                         ovl->id = OMAP_DSS_GFX;
671                         ovl->info.global_alpha = 255;
672                         ovl->info.zorder = 0;
673                         break;
674                 case 1:
675                         ovl->name = "vid1";
676                         ovl->id = OMAP_DSS_VIDEO1;
677                         ovl->info.global_alpha = 255;
678                         ovl->info.zorder =
679                                 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
680                         break;
681                 case 2:
682                         ovl->name = "vid2";
683                         ovl->id = OMAP_DSS_VIDEO2;
684                         ovl->info.global_alpha = 255;
685                         ovl->info.zorder =
686                                 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
687                         break;
688                 case 3:
689                         ovl->name = "vid3";
690                         ovl->id = OMAP_DSS_VIDEO3;
691                         ovl->info.global_alpha = 255;
692                         ovl->info.zorder =
693                                 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
694                         break;
695                 }
696
697                 ovl->set_manager = &omap_dss_set_manager;
698                 ovl->unset_manager = &omap_dss_unset_manager;
699                 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
700                 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
701                 ovl->wait_for_go = &dss_ovl_wait_for_go;
702
703                 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
704                 ovl->supported_modes =
705                         dss_feat_get_supported_color_modes(ovl->id);
706
707                 omap_dss_add_overlay(ovl);
708
709                 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
710                                 &pdev->dev.kobj, "overlay%d", i);
711
712                 if (r) {
713                         DSSERR("failed to create sysfs file\n");
714                         continue;
715                 }
716
717                 dispc_overlays[i] = ovl;
718         }
719
720 #ifdef L4_EXAMPLE
721         {
722                 struct omap_overlay *ovl;
723                 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
724
725                 BUG_ON(ovl == NULL);
726
727                 ovl->name = "l4";
728                 ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
729
730                 ovl->set_manager = &omap_dss_set_manager;
731                 ovl->unset_manager = &omap_dss_unset_manager;
732                 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
733                 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
734
735                 omap_dss_add_overlay(ovl);
736
737                 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
738                                 &pdev->dev.kobj, "overlayl4");
739
740                 if (r)
741                         DSSERR("failed to create sysfs file\n");
742
743                 l4_overlays[0] = ovl;
744         }
745 #endif
746 }
747
748 /* connect overlays to the new device, if not already connected. if force
749  * selected, connect always. */
750 void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
751 {
752         int i;
753         struct omap_overlay_manager *lcd_mgr;
754         struct omap_overlay_manager *tv_mgr;
755         struct omap_overlay_manager *lcd2_mgr = NULL;
756         struct omap_overlay_manager *mgr = NULL;
757
758         lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
759         tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
760         if (dss_has_feature(FEAT_MGR_LCD2))
761                 lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2);
762
763         if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
764                 if (!lcd2_mgr->device || force) {
765                         if (lcd2_mgr->device)
766                                 lcd2_mgr->unset_device(lcd2_mgr);
767                         lcd2_mgr->set_device(lcd2_mgr, dssdev);
768                         mgr = lcd2_mgr;
769                 }
770         } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
771                         && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
772                 if (!lcd_mgr->device || force) {
773                         if (lcd_mgr->device)
774                                 lcd_mgr->unset_device(lcd_mgr);
775                         lcd_mgr->set_device(lcd_mgr, dssdev);
776                         mgr = lcd_mgr;
777                 }
778         }
779
780         if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
781                         || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
782                 if (!tv_mgr->device || force) {
783                         if (tv_mgr->device)
784                                 tv_mgr->unset_device(tv_mgr);
785                         tv_mgr->set_device(tv_mgr, dssdev);
786                         mgr = tv_mgr;
787                 }
788         }
789
790         if (mgr) {
791                 dispc_runtime_get();
792
793                 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
794                         struct omap_overlay *ovl;
795                         ovl = omap_dss_get_overlay(i);
796                         if (!ovl->manager || force) {
797                                 if (ovl->manager)
798                                         omap_dss_unset_manager(ovl);
799                                 omap_dss_set_manager(ovl, mgr);
800                         }
801                 }
802
803                 dispc_runtime_put();
804         }
805 }
806
807 void dss_uninit_overlays(struct platform_device *pdev)
808 {
809         struct omap_overlay *ovl;
810
811         while (!list_empty(&overlay_list)) {
812                 ovl = list_first_entry(&overlay_list,
813                                 struct omap_overlay, list);
814                 list_del(&ovl->list);
815                 kobject_del(&ovl->kobj);
816                 kobject_put(&ovl->kobj);
817                 kfree(ovl);
818         }
819
820         num_overlays = 0;
821 }
822