aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/platform/omap/omap_vout.c17
-rw-r--r--drivers/staging/omapdrm/omap_drv.c11
-rw-r--r--drivers/video/omap2/dss/Makefile7
-rw-r--r--drivers/video/omap2/dss/apply.c246
-rw-r--r--drivers/video/omap2/dss/core.c15
-rw-r--r--drivers/video/omap2/dss/dispc-compat.c667
-rw-r--r--drivers/video/omap2/dss/dispc-compat.h30
-rw-r--r--drivers/video/omap2/dss/dispc.c732
-rw-r--r--drivers/video/omap2/dss/display.c20
-rw-r--r--drivers/video/omap2/dss/dpi.c2
-rw-r--r--drivers/video/omap2/dss/dsi.c26
-rw-r--r--drivers/video/omap2/dss/dss.h70
-rw-r--r--drivers/video/omap2/dss/dss_features.c6
-rw-r--r--drivers/video/omap2/dss/dss_features.h5
-rw-r--r--drivers/video/omap2/dss/manager.c39
-rw-r--r--drivers/video/omap2/dss/output.c65
-rw-r--r--drivers/video/omap2/dss/overlay.c17
-rw-r--r--drivers/video/omap2/dss/rfbi.c12
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c6
19 files changed, 1124 insertions, 869 deletions
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index a2cc634eb42e..e8cac9e55bc9 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -2184,14 +2184,23 @@ static int __init omap_vout_probe(struct platform_device *pdev)
2184 struct omap_dss_device *def_display; 2184 struct omap_dss_device *def_display;
2185 struct omap2video_device *vid_dev = NULL; 2185 struct omap2video_device *vid_dev = NULL;
2186 2186
2187 ret = omapdss_compat_init();
2188 if (ret) {
2189 dev_err(&pdev->dev, "failed to init dss\n");
2190 return ret;
2191 }
2192
2187 if (pdev->num_resources == 0) { 2193 if (pdev->num_resources == 0) {
2188 dev_err(&pdev->dev, "probed for an unknown device\n"); 2194 dev_err(&pdev->dev, "probed for an unknown device\n");
2189 return -ENODEV; 2195 ret = -ENODEV;
2196 goto err_dss_init;
2190 } 2197 }
2191 2198
2192 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); 2199 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
2193 if (vid_dev == NULL) 2200 if (vid_dev == NULL) {
2194 return -ENOMEM; 2201 ret = -ENOMEM;
2202 goto err_dss_init;
2203 }
2195 2204
2196 vid_dev->num_displays = 0; 2205 vid_dev->num_displays = 0;
2197 for_each_dss_dev(dssdev) { 2206 for_each_dss_dev(dssdev) {
@@ -2286,6 +2295,8 @@ probe_err1:
2286 } 2295 }
2287probe_err0: 2296probe_err0:
2288 kfree(vid_dev); 2297 kfree(vid_dev);
2298err_dss_init:
2299 omapdss_compat_uninit();
2289 return ret; 2300 return ret;
2290} 2301}
2291 2302
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index ebdb0b676737..2bf72591817a 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -572,6 +572,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
572 572
573 dev->dev_private = priv; 573 dev->dev_private = priv;
574 574
575 ret = omapdss_compat_init();
576 if (ret) {
577 dev_err(dev->dev, "coult not init omapdss\n");
578 dev->dev_private = NULL;
579 kfree(priv);
580 return ret;
581 }
582
575 priv->wq = alloc_ordered_workqueue("omapdrm", 0); 583 priv->wq = alloc_ordered_workqueue("omapdrm", 0);
576 584
577 INIT_LIST_HEAD(&priv->obj_list); 585 INIT_LIST_HEAD(&priv->obj_list);
@@ -583,6 +591,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
583 dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); 591 dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
584 dev->dev_private = NULL; 592 dev->dev_private = NULL;
585 kfree(priv); 593 kfree(priv);
594 omapdss_compat_uninit();
586 return ret; 595 return ret;
587 } 596 }
588 597
@@ -618,6 +627,8 @@ static int dev_unload(struct drm_device *dev)
618 flush_workqueue(priv->wq); 627 flush_workqueue(priv->wq);
619 destroy_workqueue(priv->wq); 628 destroy_workqueue(priv->wq);
620 629
630 omapdss_compat_uninit();
631
621 kfree(dev->dev_private); 632 kfree(dev->dev_private);
622 dev->dev_private = NULL; 633 dev->dev_private = NULL;
623 634
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index af866d0b7942..61949ff7940c 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,7 +1,10 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2# Core DSS files
2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 3omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
3 manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o \ 4 output.o
4 display-sysfs.o 5# DSS compat layer files
6omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
7 dispc-compat.o display-sysfs.o
5omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 8omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
6omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 9omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
7omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o 10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 4a5cc5c64d4b..d446bdfc4c82 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -18,6 +18,7 @@
18#define DSS_SUBSYS_NAME "APPLY" 18#define DSS_SUBSYS_NAME "APPLY"
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23#include <linux/jiffies.h> 24#include <linux/jiffies.h>
@@ -26,6 +27,7 @@
26 27
27#include "dss.h" 28#include "dss.h"
28#include "dss_features.h" 29#include "dss_features.h"
30#include "dispc-compat.h"
29 31
30/* 32/*
31 * We have 4 levels of cache for the dispc settings. First two are in SW and 33 * We have 4 levels of cache for the dispc settings. First two are in SW and
@@ -104,6 +106,9 @@ struct mgr_priv_data {
104 106
105 struct omap_video_timings timings; 107 struct omap_video_timings timings;
106 struct dss_lcd_mgr_config lcd_config; 108 struct dss_lcd_mgr_config lcd_config;
109
110 void (*framedone_handler)(void *);
111 void *framedone_handler_data;
107}; 112};
108 113
109static struct { 114static struct {
@@ -131,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
131 return &dss_data.mgr_priv_data_array[mgr->id]; 136 return &dss_data.mgr_priv_data_array[mgr->id];
132} 137}
133 138
134void dss_apply_init(void) 139static void apply_init_priv(void)
135{ 140{
136 const int num_ovls = dss_feat_get_num_ovls(); 141 const int num_ovls = dss_feat_get_num_ovls();
137 struct mgr_priv_data *mp; 142 struct mgr_priv_data *mp;
@@ -415,7 +420,44 @@ static void wait_pending_extra_info_updates(void)
415 DSSWARN("timeout in wait_pending_extra_info_updates\n"); 420 DSSWARN("timeout in wait_pending_extra_info_updates\n");
416} 421}
417 422
418int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 423static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
424{
425 return ovl->manager ?
426 (ovl->manager->output ? ovl->manager->output->device : NULL) :
427 NULL;
428}
429
430static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
431{
432 return mgr->output ? mgr->output->device : NULL;
433}
434
435static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
436{
437 unsigned long timeout = msecs_to_jiffies(500);
438 struct omap_dss_device *dssdev = mgr->get_device(mgr);
439 u32 irq;
440 int r;
441
442 r = dispc_runtime_get();
443 if (r)
444 return r;
445
446 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
447 irq = DISPC_IRQ_EVSYNC_ODD;
448 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
449 irq = DISPC_IRQ_EVSYNC_EVEN;
450 else
451 irq = dispc_mgr_get_vsync_irq(mgr->id);
452
453 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
454
455 dispc_runtime_put();
456
457 return r;
458}
459
460static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
419{ 461{
420 unsigned long timeout = msecs_to_jiffies(500); 462 unsigned long timeout = msecs_to_jiffies(500);
421 struct mgr_priv_data *mp = get_mgr_priv(mgr); 463 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -485,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
485 return r; 527 return r;
486} 528}
487 529
488int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) 530static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
489{ 531{
490 unsigned long timeout = msecs_to_jiffies(500); 532 unsigned long timeout = msecs_to_jiffies(500);
491 struct ovl_priv_data *op; 533 struct ovl_priv_data *op;
@@ -743,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
743 } 785 }
744} 786}
745 787
746void dss_mgr_start_update(struct omap_overlay_manager *mgr) 788static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
747{ 789{
748 struct mgr_priv_data *mp = get_mgr_priv(mgr); 790 struct mgr_priv_data *mp = get_mgr_priv(mgr);
749 unsigned long flags; 791 unsigned long flags;
@@ -850,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
850 if (!extra_updating) 892 if (!extra_updating)
851 complete_all(&extra_updated_completion); 893 complete_all(&extra_updated_completion);
852 894
895 /* call framedone handlers for manual update displays */
896 for (i = 0; i < num_mgrs; i++) {
897 struct omap_overlay_manager *mgr;
898 struct mgr_priv_data *mp;
899
900 mgr = omap_dss_get_overlay_manager(i);
901 mp = get_mgr_priv(mgr);
902
903 if (!mgr_manual_update(mgr) || !mp->framedone_handler)
904 continue;
905
906 if (mask & dispc_mgr_get_framedone_irq(i))
907 mp->framedone_handler(mp->framedone_handler_data);
908 }
909
853 if (!need_isr()) 910 if (!need_isr())
854 dss_unregister_vsync_isr(); 911 dss_unregister_vsync_isr();
855 912
@@ -884,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
884 mp->info = mp->user_info; 941 mp->info = mp->user_info;
885} 942}
886 943
887int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) 944static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
888{ 945{
889 unsigned long flags; 946 unsigned long flags;
890 struct omap_overlay *ovl; 947 struct omap_overlay *ovl;
@@ -983,7 +1040,7 @@ static void dss_setup_fifos(void)
983 } 1040 }
984} 1041}
985 1042
986int dss_mgr_enable(struct omap_overlay_manager *mgr) 1043static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
987{ 1044{
988 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1045 struct mgr_priv_data *mp = get_mgr_priv(mgr);
989 unsigned long flags; 1046 unsigned long flags;
@@ -1033,7 +1090,7 @@ err:
1033 return r; 1090 return r;
1034} 1091}
1035 1092
1036void dss_mgr_disable(struct omap_overlay_manager *mgr) 1093static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
1037{ 1094{
1038 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1095 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1039 unsigned long flags; 1096 unsigned long flags;
@@ -1057,7 +1114,7 @@ out:
1057 mutex_unlock(&apply_lock); 1114 mutex_unlock(&apply_lock);
1058} 1115}
1059 1116
1060int dss_mgr_set_info(struct omap_overlay_manager *mgr, 1117static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1061 struct omap_overlay_manager_info *info) 1118 struct omap_overlay_manager_info *info)
1062{ 1119{
1063 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1120 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1078,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1078 return 0; 1135 return 0;
1079} 1136}
1080 1137
1081void dss_mgr_get_info(struct omap_overlay_manager *mgr, 1138static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1082 struct omap_overlay_manager_info *info) 1139 struct omap_overlay_manager_info *info)
1083{ 1140{
1084 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1141 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1091,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1091 spin_unlock_irqrestore(&data_lock, flags); 1148 spin_unlock_irqrestore(&data_lock, flags);
1092} 1149}
1093 1150
1094int dss_mgr_set_output(struct omap_overlay_manager *mgr, 1151static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1095 struct omap_dss_output *output) 1152 struct omap_dss_output *output)
1096{ 1153{
1097 int r; 1154 int r;
@@ -1123,7 +1180,7 @@ err:
1123 return r; 1180 return r;
1124} 1181}
1125 1182
1126int dss_mgr_unset_output(struct omap_overlay_manager *mgr) 1183static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1127{ 1184{
1128 int r; 1185 int r;
1129 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1186 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1170,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1170 mp->extra_info_dirty = true; 1227 mp->extra_info_dirty = true;
1171} 1228}
1172 1229
1173void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 1230static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
1174 const struct omap_video_timings *timings) 1231 const struct omap_video_timings *timings)
1175{ 1232{
1176 unsigned long flags; 1233 unsigned long flags;
@@ -1198,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1198 mp->extra_info_dirty = true; 1255 mp->extra_info_dirty = true;
1199} 1256}
1200 1257
1201void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, 1258static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
1202 const struct dss_lcd_mgr_config *config) 1259 const struct dss_lcd_mgr_config *config)
1203{ 1260{
1204 unsigned long flags; 1261 unsigned long flags;
@@ -1217,7 +1274,7 @@ out:
1217 spin_unlock_irqrestore(&data_lock, flags); 1274 spin_unlock_irqrestore(&data_lock, flags);
1218} 1275}
1219 1276
1220int dss_ovl_set_info(struct omap_overlay *ovl, 1277static int dss_ovl_set_info(struct omap_overlay *ovl,
1221 struct omap_overlay_info *info) 1278 struct omap_overlay_info *info)
1222{ 1279{
1223 struct ovl_priv_data *op = get_ovl_priv(ovl); 1280 struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1238,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
1238 return 0; 1295 return 0;
1239} 1296}
1240 1297
1241void dss_ovl_get_info(struct omap_overlay *ovl, 1298static void dss_ovl_get_info(struct omap_overlay *ovl,
1242 struct omap_overlay_info *info) 1299 struct omap_overlay_info *info)
1243{ 1300{
1244 struct ovl_priv_data *op = get_ovl_priv(ovl); 1301 struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1251,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
1251 spin_unlock_irqrestore(&data_lock, flags); 1308 spin_unlock_irqrestore(&data_lock, flags);
1252} 1309}
1253 1310
1254int dss_ovl_set_manager(struct omap_overlay *ovl, 1311static int dss_ovl_set_manager(struct omap_overlay *ovl,
1255 struct omap_overlay_manager *mgr) 1312 struct omap_overlay_manager *mgr)
1256{ 1313{
1257 struct ovl_priv_data *op = get_ovl_priv(ovl); 1314 struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1303,7 +1360,7 @@ err:
1303 return r; 1360 return r;
1304} 1361}
1305 1362
1306int dss_ovl_unset_manager(struct omap_overlay *ovl) 1363static int dss_ovl_unset_manager(struct omap_overlay *ovl)
1307{ 1364{
1308 struct ovl_priv_data *op = get_ovl_priv(ovl); 1365 struct ovl_priv_data *op = get_ovl_priv(ovl);
1309 unsigned long flags; 1366 unsigned long flags;
@@ -1363,7 +1420,7 @@ err:
1363 return r; 1420 return r;
1364} 1421}
1365 1422
1366bool dss_ovl_is_enabled(struct omap_overlay *ovl) 1423static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1367{ 1424{
1368 struct ovl_priv_data *op = get_ovl_priv(ovl); 1425 struct ovl_priv_data *op = get_ovl_priv(ovl);
1369 unsigned long flags; 1426 unsigned long flags;
@@ -1378,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1378 return e; 1435 return e;
1379} 1436}
1380 1437
1381int dss_ovl_enable(struct omap_overlay *ovl) 1438static int dss_ovl_enable(struct omap_overlay *ovl)
1382{ 1439{
1383 struct ovl_priv_data *op = get_ovl_priv(ovl); 1440 struct ovl_priv_data *op = get_ovl_priv(ovl);
1384 unsigned long flags; 1441 unsigned long flags;
@@ -1428,7 +1485,7 @@ err1:
1428 return r; 1485 return r;
1429} 1486}
1430 1487
1431int dss_ovl_disable(struct omap_overlay *ovl) 1488static int dss_ovl_disable(struct omap_overlay *ovl)
1432{ 1489{
1433 struct ovl_priv_data *op = get_ovl_priv(ovl); 1490 struct ovl_priv_data *op = get_ovl_priv(ovl);
1434 unsigned long flags; 1491 unsigned long flags;
@@ -1463,3 +1520,152 @@ err:
1463 return r; 1520 return r;
1464} 1521}
1465 1522
1523static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
1524 void (*handler)(void *), void *data)
1525{
1526 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1527
1528 if (mp->framedone_handler)
1529 return -EBUSY;
1530
1531 mp->framedone_handler = handler;
1532 mp->framedone_handler_data = data;
1533
1534 return 0;
1535}
1536
1537static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
1538 void (*handler)(void *), void *data)
1539{
1540 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1541
1542 WARN_ON(mp->framedone_handler != handler ||
1543 mp->framedone_handler_data != data);
1544
1545 mp->framedone_handler = NULL;
1546 mp->framedone_handler_data = NULL;
1547}
1548
1549static const struct dss_mgr_ops apply_mgr_ops = {
1550 .start_update = dss_mgr_start_update_compat,
1551 .enable = dss_mgr_enable_compat,
1552 .disable = dss_mgr_disable_compat,
1553 .set_timings = dss_mgr_set_timings_compat,
1554 .set_lcd_config = dss_mgr_set_lcd_config_compat,
1555 .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
1556 .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
1557};
1558
1559static int compat_refcnt;
1560static DEFINE_MUTEX(compat_init_lock);
1561
1562int omapdss_compat_init(void)
1563{
1564 struct platform_device *pdev = dss_get_core_pdev();
1565 struct omap_dss_device *dssdev = NULL;
1566 int i, r;
1567
1568 mutex_lock(&compat_init_lock);
1569
1570 if (compat_refcnt++ > 0)
1571 goto out;
1572
1573 apply_init_priv();
1574
1575 dss_init_overlay_managers(pdev);
1576 dss_init_overlays(pdev);
1577
1578 for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
1579 struct omap_overlay_manager *mgr;
1580
1581 mgr = omap_dss_get_overlay_manager(i);
1582
1583 mgr->set_output = &dss_mgr_set_output;
1584 mgr->unset_output = &dss_mgr_unset_output;
1585 mgr->apply = &omap_dss_mgr_apply;
1586 mgr->set_manager_info = &dss_mgr_set_info;
1587 mgr->get_manager_info = &dss_mgr_get_info;
1588 mgr->wait_for_go = &dss_mgr_wait_for_go;
1589 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1590 mgr->get_device = &dss_mgr_get_device;
1591 }
1592
1593 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
1594 struct omap_overlay *ovl = omap_dss_get_overlay(i);
1595
1596 ovl->is_enabled = &dss_ovl_is_enabled;
1597 ovl->enable = &dss_ovl_enable;
1598 ovl->disable = &dss_ovl_disable;
1599 ovl->set_manager = &dss_ovl_set_manager;
1600 ovl->unset_manager = &dss_ovl_unset_manager;
1601 ovl->set_overlay_info = &dss_ovl_set_info;
1602 ovl->get_overlay_info = &dss_ovl_get_info;
1603 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
1604 ovl->get_device = &dss_ovl_get_device;
1605 }
1606
1607 r = dss_install_mgr_ops(&apply_mgr_ops);
1608 if (r)
1609 goto err_mgr_ops;
1610
1611 for_each_dss_dev(dssdev) {
1612 r = display_init_sysfs(pdev, dssdev);
1613 /* XXX uninit sysfs files on error */
1614 if (r)
1615 goto err_disp_sysfs;
1616 }
1617
1618 dispc_runtime_get();
1619
1620 r = dss_dispc_initialize_irq();
1621 if (r)
1622 goto err_init_irq;
1623
1624 dispc_runtime_put();
1625
1626out:
1627 mutex_unlock(&compat_init_lock);
1628
1629 return 0;
1630
1631err_init_irq:
1632 dispc_runtime_put();
1633
1634err_disp_sysfs:
1635 dss_uninstall_mgr_ops();
1636
1637err_mgr_ops:
1638 dss_uninit_overlay_managers(pdev);
1639 dss_uninit_overlays(pdev);
1640
1641 compat_refcnt--;
1642
1643 mutex_unlock(&compat_init_lock);
1644
1645 return r;
1646}
1647EXPORT_SYMBOL(omapdss_compat_init);
1648
1649void omapdss_compat_uninit(void)
1650{
1651 struct platform_device *pdev = dss_get_core_pdev();
1652 struct omap_dss_device *dssdev = NULL;
1653
1654 mutex_lock(&compat_init_lock);
1655
1656 if (--compat_refcnt > 0)
1657 goto out;
1658
1659 dss_dispc_uninitialize_irq();
1660
1661 for_each_dss_dev(dssdev)
1662 display_uninit_sysfs(pdev, dssdev);
1663
1664 dss_uninstall_mgr_ops();
1665
1666 dss_uninit_overlay_managers(pdev);
1667 dss_uninit_overlays(pdev);
1668out:
1669 mutex_unlock(&compat_init_lock);
1670}
1671EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 5c5e59190586..f8779d4750ba 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -232,11 +232,6 @@ static int __init omap_dss_probe(struct platform_device *pdev)
232 232
233 dss_features_init(omapdss_get_version()); 233 dss_features_init(omapdss_get_version());
234 234
235 dss_apply_init();
236
237 dss_init_overlay_managers(pdev);
238 dss_init_overlays(pdev);
239
240 r = dss_initialize_debugfs(); 235 r = dss_initialize_debugfs();
241 if (r) 236 if (r)
242 goto err_debugfs; 237 goto err_debugfs;
@@ -261,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)
261 256
262 dss_uninitialize_debugfs(); 257 dss_uninitialize_debugfs();
263 258
264 dss_uninit_overlays(pdev);
265 dss_uninit_overlay_managers(pdev);
266
267 return 0; 259 return 0;
268} 260}
269 261
@@ -351,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
351 dev_name(dev), dssdev->driver_name, 343 dev_name(dev), dssdev->driver_name,
352 dssdrv->driver.name); 344 dssdrv->driver.name);
353 345
354 r = dss_init_device(core.pdev, dssdev);
355 if (r)
356 return r;
357
358 r = dssdrv->probe(dssdev); 346 r = dssdrv->probe(dssdev);
359 347
360 if (r) { 348 if (r) {
361 DSSERR("driver probe failed: %d\n", r); 349 DSSERR("driver probe failed: %d\n", r);
362 dss_uninit_device(core.pdev, dssdev);
363 return r; 350 return r;
364 } 351 }
365 352
@@ -380,8 +367,6 @@ static int dss_driver_remove(struct device *dev)
380 367
381 dssdrv->remove(dssdev); 368 dssdrv->remove(dssdev);
382 369
383 dss_uninit_device(core.pdev, dssdev);
384
385 dssdev->driver = NULL; 370 dssdev->driver = NULL;
386 371
387 return 0; 372 return 0;
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
new file mode 100644
index 000000000000..928884c9a0a9
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc-compat.c
@@ -0,0 +1,667 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
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/module.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/jiffies.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/seq_file.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33#include "dispc-compat.h"
34
35#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
36 DISPC_IRQ_OCP_ERR | \
37 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
38 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
39 DISPC_IRQ_SYNC_LOST | \
40 DISPC_IRQ_SYNC_LOST_DIGIT)
41
42#define DISPC_MAX_NR_ISRS 8
43
44struct omap_dispc_isr_data {
45 omap_dispc_isr_t isr;
46 void *arg;
47 u32 mask;
48};
49
50struct dispc_irq_stats {
51 unsigned long last_reset;
52 unsigned irq_count;
53 unsigned irqs[32];
54};
55
56static struct {
57 spinlock_t irq_lock;
58 u32 irq_error_mask;
59 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
60 u32 error_irqs;
61 struct work_struct error_work;
62
63#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
64 spinlock_t irq_stats_lock;
65 struct dispc_irq_stats irq_stats;
66#endif
67} dispc_compat;
68
69
70#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
71static void dispc_dump_irqs(struct seq_file *s)
72{
73 unsigned long flags;
74 struct dispc_irq_stats stats;
75
76 spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
77
78 stats = dispc_compat.irq_stats;
79 memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
80 dispc_compat.irq_stats.last_reset = jiffies;
81
82 spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
83
84 seq_printf(s, "period %u ms\n",
85 jiffies_to_msecs(jiffies - stats.last_reset));
86
87 seq_printf(s, "irqs %d\n", stats.irq_count);
88#define PIS(x) \
89 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
90
91 PIS(FRAMEDONE);
92 PIS(VSYNC);
93 PIS(EVSYNC_EVEN);
94 PIS(EVSYNC_ODD);
95 PIS(ACBIAS_COUNT_STAT);
96 PIS(PROG_LINE_NUM);
97 PIS(GFX_FIFO_UNDERFLOW);
98 PIS(GFX_END_WIN);
99 PIS(PAL_GAMMA_MASK);
100 PIS(OCP_ERR);
101 PIS(VID1_FIFO_UNDERFLOW);
102 PIS(VID1_END_WIN);
103 PIS(VID2_FIFO_UNDERFLOW);
104 PIS(VID2_END_WIN);
105 if (dss_feat_get_num_ovls() > 3) {
106 PIS(VID3_FIFO_UNDERFLOW);
107 PIS(VID3_END_WIN);
108 }
109 PIS(SYNC_LOST);
110 PIS(SYNC_LOST_DIGIT);
111 PIS(WAKEUP);
112 if (dss_has_feature(FEAT_MGR_LCD2)) {
113 PIS(FRAMEDONE2);
114 PIS(VSYNC2);
115 PIS(ACBIAS_COUNT_STAT2);
116 PIS(SYNC_LOST2);
117 }
118 if (dss_has_feature(FEAT_MGR_LCD3)) {
119 PIS(FRAMEDONE3);
120 PIS(VSYNC3);
121 PIS(ACBIAS_COUNT_STAT3);
122 PIS(SYNC_LOST3);
123 }
124#undef PIS
125}
126#endif
127
128/* dispc.irq_lock has to be locked by the caller */
129static void _omap_dispc_set_irqs(void)
130{
131 u32 mask;
132 int i;
133 struct omap_dispc_isr_data *isr_data;
134
135 mask = dispc_compat.irq_error_mask;
136
137 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
138 isr_data = &dispc_compat.registered_isr[i];
139
140 if (isr_data->isr == NULL)
141 continue;
142
143 mask |= isr_data->mask;
144 }
145
146 dispc_write_irqenable(mask);
147}
148
149int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
150{
151 int i;
152 int ret;
153 unsigned long flags;
154 struct omap_dispc_isr_data *isr_data;
155
156 if (isr == NULL)
157 return -EINVAL;
158
159 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
160
161 /* check for duplicate entry */
162 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
163 isr_data = &dispc_compat.registered_isr[i];
164 if (isr_data->isr == isr && isr_data->arg == arg &&
165 isr_data->mask == mask) {
166 ret = -EINVAL;
167 goto err;
168 }
169 }
170
171 isr_data = NULL;
172 ret = -EBUSY;
173
174 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
175 isr_data = &dispc_compat.registered_isr[i];
176
177 if (isr_data->isr != NULL)
178 continue;
179
180 isr_data->isr = isr;
181 isr_data->arg = arg;
182 isr_data->mask = mask;
183 ret = 0;
184
185 break;
186 }
187
188 if (ret)
189 goto err;
190
191 _omap_dispc_set_irqs();
192
193 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
194
195 return 0;
196err:
197 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
198
199 return ret;
200}
201EXPORT_SYMBOL(omap_dispc_register_isr);
202
203int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
204{
205 int i;
206 unsigned long flags;
207 int ret = -EINVAL;
208 struct omap_dispc_isr_data *isr_data;
209
210 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
211
212 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
213 isr_data = &dispc_compat.registered_isr[i];
214 if (isr_data->isr != isr || isr_data->arg != arg ||
215 isr_data->mask != mask)
216 continue;
217
218 /* found the correct isr */
219
220 isr_data->isr = NULL;
221 isr_data->arg = NULL;
222 isr_data->mask = 0;
223
224 ret = 0;
225 break;
226 }
227
228 if (ret == 0)
229 _omap_dispc_set_irqs();
230
231 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
232
233 return ret;
234}
235EXPORT_SYMBOL(omap_dispc_unregister_isr);
236
237static void print_irq_status(u32 status)
238{
239 if ((status & dispc_compat.irq_error_mask) == 0)
240 return;
241
242#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
243
244 pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
245 status,
246 PIS(OCP_ERR),
247 PIS(GFX_FIFO_UNDERFLOW),
248 PIS(VID1_FIFO_UNDERFLOW),
249 PIS(VID2_FIFO_UNDERFLOW),
250 dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
251 PIS(SYNC_LOST),
252 PIS(SYNC_LOST_DIGIT),
253 dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
254 dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
255#undef PIS
256}
257
258/* Called from dss.c. Note that we don't touch clocks here,
259 * but we presume they are on because we got an IRQ. However,
260 * an irq handler may turn the clocks off, so we may not have
261 * clock later in the function. */
262static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
263{
264 int i;
265 u32 irqstatus, irqenable;
266 u32 handledirqs = 0;
267 u32 unhandled_errors;
268 struct omap_dispc_isr_data *isr_data;
269 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
270
271 spin_lock(&dispc_compat.irq_lock);
272
273 irqstatus = dispc_read_irqstatus();
274 irqenable = dispc_read_irqenable();
275
276 /* IRQ is not for us */
277 if (!(irqstatus & irqenable)) {
278 spin_unlock(&dispc_compat.irq_lock);
279 return IRQ_NONE;
280 }
281
282#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
283 spin_lock(&dispc_compat.irq_stats_lock);
284 dispc_compat.irq_stats.irq_count++;
285 dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
286 spin_unlock(&dispc_compat.irq_stats_lock);
287#endif
288
289 print_irq_status(irqstatus);
290
291 /* Ack the interrupt. Do it here before clocks are possibly turned
292 * off */
293 dispc_clear_irqstatus(irqstatus);
294 /* flush posted write */
295 dispc_read_irqstatus();
296
297 /* make a copy and unlock, so that isrs can unregister
298 * themselves */
299 memcpy(registered_isr, dispc_compat.registered_isr,
300 sizeof(registered_isr));
301
302 spin_unlock(&dispc_compat.irq_lock);
303
304 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
305 isr_data = &registered_isr[i];
306
307 if (!isr_data->isr)
308 continue;
309
310 if (isr_data->mask & irqstatus) {
311 isr_data->isr(isr_data->arg, irqstatus);
312 handledirqs |= isr_data->mask;
313 }
314 }
315
316 spin_lock(&dispc_compat.irq_lock);
317
318 unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
319
320 if (unhandled_errors) {
321 dispc_compat.error_irqs |= unhandled_errors;
322
323 dispc_compat.irq_error_mask &= ~unhandled_errors;
324 _omap_dispc_set_irqs();
325
326 schedule_work(&dispc_compat.error_work);
327 }
328
329 spin_unlock(&dispc_compat.irq_lock);
330
331 return IRQ_HANDLED;
332}
333
334static void dispc_error_worker(struct work_struct *work)
335{
336 int i;
337 u32 errors;
338 unsigned long flags;
339 static const unsigned fifo_underflow_bits[] = {
340 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
341 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
342 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
343 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
344 };
345
346 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
347 errors = dispc_compat.error_irqs;
348 dispc_compat.error_irqs = 0;
349 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
350
351 dispc_runtime_get();
352
353 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
354 struct omap_overlay *ovl;
355 unsigned bit;
356
357 ovl = omap_dss_get_overlay(i);
358 bit = fifo_underflow_bits[i];
359
360 if (bit & errors) {
361 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
362 ovl->name);
363 dispc_ovl_enable(ovl->id, false);
364 dispc_mgr_go(ovl->manager->id);
365 msleep(50);
366 }
367 }
368
369 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
370 struct omap_overlay_manager *mgr;
371 unsigned bit;
372
373 mgr = omap_dss_get_overlay_manager(i);
374 bit = dispc_mgr_get_sync_lost_irq(i);
375
376 if (bit & errors) {
377 int j;
378
379 DSSERR("SYNC_LOST on channel %s, restarting the output "
380 "with video overlays disabled\n",
381 mgr->name);
382
383 dss_mgr_disable(mgr);
384
385 for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
386 struct omap_overlay *ovl;
387 ovl = omap_dss_get_overlay(j);
388
389 if (ovl->id != OMAP_DSS_GFX &&
390 ovl->manager == mgr)
391 ovl->disable(ovl);
392 }
393
394 dss_mgr_enable(mgr);
395 }
396 }
397
398 if (errors & DISPC_IRQ_OCP_ERR) {
399 DSSERR("OCP_ERR\n");
400 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
401 struct omap_overlay_manager *mgr;
402
403 mgr = omap_dss_get_overlay_manager(i);
404 dss_mgr_disable(mgr);
405 }
406 }
407
408 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
409 dispc_compat.irq_error_mask |= errors;
410 _omap_dispc_set_irqs();
411 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
412
413 dispc_runtime_put();
414}
415
416int dss_dispc_initialize_irq(void)
417{
418 int r;
419
420#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
421 spin_lock_init(&dispc_compat.irq_stats_lock);
422 dispc_compat.irq_stats.last_reset = jiffies;
423 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
424#endif
425
426 spin_lock_init(&dispc_compat.irq_lock);
427
428 memset(dispc_compat.registered_isr, 0,
429 sizeof(dispc_compat.registered_isr));
430
431 dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
432 if (dss_has_feature(FEAT_MGR_LCD2))
433 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
434 if (dss_has_feature(FEAT_MGR_LCD3))
435 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
436 if (dss_feat_get_num_ovls() > 3)
437 dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
438
439 /*
440 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
441 * so clear it
442 */
443 dispc_clear_irqstatus(dispc_read_irqstatus());
444
445 INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
446
447 _omap_dispc_set_irqs();
448
449 r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
450 if (r) {
451 DSSERR("dispc_request_irq failed\n");
452 return r;
453 }
454
455 return 0;
456}
457
458void dss_dispc_uninitialize_irq(void)
459{
460 dispc_free_irq(&dispc_compat);
461}
462
463static void dispc_mgr_disable_isr(void *data, u32 mask)
464{
465 struct completion *compl = data;
466 complete(compl);
467}
468
469static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
470{
471 dispc_mgr_enable(channel, true);
472}
473
474static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
475{
476 DECLARE_COMPLETION_ONSTACK(framedone_compl);
477 int r;
478 u32 irq;
479
480 if (dispc_mgr_is_enabled(channel) == false)
481 return;
482
483 /*
484 * When we disable LCD output, we need to wait for FRAMEDONE to know
485 * that DISPC has finished with the LCD output.
486 */
487
488 irq = dispc_mgr_get_framedone_irq(channel);
489
490 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
491 irq);
492 if (r)
493 DSSERR("failed to register FRAMEDONE isr\n");
494
495 dispc_mgr_enable(channel, false);
496
497 /* if we couldn't register for framedone, just sleep and exit */
498 if (r) {
499 msleep(100);
500 return;
501 }
502
503 if (!wait_for_completion_timeout(&framedone_compl,
504 msecs_to_jiffies(100)))
505 DSSERR("timeout waiting for FRAME DONE\n");
506
507 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
508 irq);
509 if (r)
510 DSSERR("failed to unregister FRAMEDONE isr\n");
511}
512
513static void dispc_digit_out_enable_isr(void *data, u32 mask)
514{
515 struct completion *compl = data;
516
517 /* ignore any sync lost interrupts */
518 if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
519 complete(compl);
520}
521
522static void dispc_mgr_enable_digit_out(void)
523{
524 DECLARE_COMPLETION_ONSTACK(vsync_compl);
525 int r;
526 u32 irq_mask;
527
528 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
529 return;
530
531 /*
532 * Digit output produces some sync lost interrupts during the first
533 * frame when enabling. Those need to be ignored, so we register for the
534 * sync lost irq to prevent the error handler from triggering.
535 */
536
537 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
538 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
539
540 r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
541 irq_mask);
542 if (r) {
543 DSSERR("failed to register %x isr\n", irq_mask);
544 return;
545 }
546
547 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
548
549 /* wait for the first evsync */
550 if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
551 DSSERR("timeout waiting for digit out to start\n");
552
553 r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
554 irq_mask);
555 if (r)
556 DSSERR("failed to unregister %x isr\n", irq_mask);
557}
558
559static void dispc_mgr_disable_digit_out(void)
560{
561 DECLARE_COMPLETION_ONSTACK(framedone_compl);
562 int r, i;
563 u32 irq_mask;
564 int num_irqs;
565
566 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
567 return;
568
569 /*
570 * When we disable the digit output, we need to wait for FRAMEDONE to
571 * know that DISPC has finished with the output.
572 */
573
574 irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
575 num_irqs = 1;
576
577 if (!irq_mask) {
578 /*
579 * omap 2/3 don't have framedone irq for TV, so we need to use
580 * vsyncs for this.
581 */
582
583 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
584 /*
585 * We need to wait for both even and odd vsyncs. Note that this
586 * is not totally reliable, as we could get a vsync interrupt
587 * before we disable the output, which leads to timeout in the
588 * wait_for_completion.
589 */
590 num_irqs = 2;
591 }
592
593 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
594 irq_mask);
595 if (r)
596 DSSERR("failed to register %x isr\n", irq_mask);
597
598 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
599
600 /* if we couldn't register the irq, just sleep and exit */
601 if (r) {
602 msleep(100);
603 return;
604 }
605
606 for (i = 0; i < num_irqs; ++i) {
607 if (!wait_for_completion_timeout(&framedone_compl,
608 msecs_to_jiffies(100)))
609 DSSERR("timeout waiting for digit out to stop\n");
610 }
611
612 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
613 irq_mask);
614 if (r)
615 DSSERR("failed to unregister %x isr\n", irq_mask);
616}
617
618void dispc_mgr_enable_sync(enum omap_channel channel)
619{
620 if (dss_mgr_is_lcd(channel))
621 dispc_mgr_enable_lcd_out(channel);
622 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
623 dispc_mgr_enable_digit_out();
624 else
625 WARN_ON(1);
626}
627
628void dispc_mgr_disable_sync(enum omap_channel channel)
629{
630 if (dss_mgr_is_lcd(channel))
631 dispc_mgr_disable_lcd_out(channel);
632 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
633 dispc_mgr_disable_digit_out();
634 else
635 WARN_ON(1);
636}
637
638int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
639 unsigned long timeout)
640{
641 void dispc_irq_wait_handler(void *data, u32 mask)
642 {
643 complete((struct completion *)data);
644 }
645
646 int r;
647 DECLARE_COMPLETION_ONSTACK(completion);
648
649 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
650 irqmask);
651
652 if (r)
653 return r;
654
655 timeout = wait_for_completion_interruptible_timeout(&completion,
656 timeout);
657
658 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
659
660 if (timeout == 0)
661 return -ETIMEDOUT;
662
663 if (timeout == -ERESTARTSYS)
664 return -ERESTARTSYS;
665
666 return 0;
667}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
new file mode 100644
index 000000000000..14a69b3d4fb0
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc-compat.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
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#ifndef __OMAP2_DSS_DISPC_COMPAT_H
19#define __OMAP2_DSS_DISPC_COMPAT_H
20
21void dispc_mgr_enable_sync(enum omap_channel channel);
22void dispc_mgr_disable_sync(enum omap_channel channel);
23
24int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
25 unsigned long timeout);
26
27int dss_dispc_initialize_irq(void);
28void dss_dispc_uninitialize_irq(void);
29
30#endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index f7df52306788..fedbd2c8e97a 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -33,7 +33,6 @@
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <linux/workqueue.h> 34#include <linux/workqueue.h>
35#include <linux/hardirq.h> 35#include <linux/hardirq.h>
36#include <linux/interrupt.h>
37#include <linux/platform_device.h> 36#include <linux/platform_device.h>
38#include <linux/pm_runtime.h> 37#include <linux/pm_runtime.h>
39#include <linux/sizes.h> 38#include <linux/sizes.h>
@@ -47,21 +46,6 @@
47/* DISPC */ 46/* DISPC */
48#define DISPC_SZ_REGS SZ_4K 47#define DISPC_SZ_REGS SZ_4K
49 48
50#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
51 DISPC_IRQ_OCP_ERR | \
52 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
53 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
54 DISPC_IRQ_SYNC_LOST | \
55 DISPC_IRQ_SYNC_LOST_DIGIT)
56
57#define DISPC_MAX_NR_ISRS 8
58
59struct omap_dispc_isr_data {
60 omap_dispc_isr_t isr;
61 void *arg;
62 u32 mask;
63};
64
65enum omap_burst_size { 49enum omap_burst_size {
66 BURST_SIZE_X2 = 0, 50 BURST_SIZE_X2 = 0,
67 BURST_SIZE_X4 = 1, 51 BURST_SIZE_X4 = 1,
@@ -74,12 +58,6 @@ enum omap_burst_size {
74#define REG_FLD_MOD(idx, val, start, end) \ 58#define REG_FLD_MOD(idx, val, start, end) \
75 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) 59 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
76 60
77struct dispc_irq_stats {
78 unsigned long last_reset;
79 unsigned irq_count;
80 unsigned irqs[32];
81};
82
83struct dispc_features { 61struct dispc_features {
84 u8 sw_start; 62 u8 sw_start;
85 u8 fp_start; 63 u8 fp_start;
@@ -124,21 +102,10 @@ static struct {
124 /* maps which plane is using a fifo. fifo-id -> plane-id */ 102 /* maps which plane is using a fifo. fifo-id -> plane-id */
125 int fifo_assignment[DISPC_MAX_NR_FIFOS]; 103 int fifo_assignment[DISPC_MAX_NR_FIFOS];
126 104
127 spinlock_t irq_lock;
128 u32 irq_error_mask;
129 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
130 u32 error_irqs;
131 struct work_struct error_work;
132
133 bool ctx_valid; 105 bool ctx_valid;
134 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 106 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
135 107
136 const struct dispc_features *feat; 108 const struct dispc_features *feat;
137
138#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
139 spinlock_t irq_stats_lock;
140 struct dispc_irq_stats irq_stats;
141#endif
142} dispc; 109} dispc;
143 110
144enum omap_color_component { 111enum omap_color_component {
@@ -249,7 +216,6 @@ struct color_conv_coef {
249 int full_range; 216 int full_range;
250}; 217};
251 218
252static void _omap_dispc_set_irqs(void);
253static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); 219static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
254static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); 220static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
255 221
@@ -528,6 +494,7 @@ int dispc_runtime_get(void)
528 WARN_ON(r < 0); 494 WARN_ON(r < 0);
529 return r < 0 ? r : 0; 495 return r < 0 ? r : 0;
530} 496}
497EXPORT_SYMBOL(dispc_runtime_get);
531 498
532void dispc_runtime_put(void) 499void dispc_runtime_put(void)
533{ 500{
@@ -538,11 +505,13 @@ void dispc_runtime_put(void)
538 r = pm_runtime_put_sync(&dispc.pdev->dev); 505 r = pm_runtime_put_sync(&dispc.pdev->dev);
539 WARN_ON(r < 0 && r != -ENOSYS); 506 WARN_ON(r < 0 && r != -ENOSYS);
540} 507}
508EXPORT_SYMBOL(dispc_runtime_put);
541 509
542u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) 510u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
543{ 511{
544 return mgr_desc[channel].vsync_irq; 512 return mgr_desc[channel].vsync_irq;
545} 513}
514EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
546 515
547u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) 516u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
548{ 517{
@@ -551,11 +520,13 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
551 520
552 return mgr_desc[channel].framedone_irq; 521 return mgr_desc[channel].framedone_irq;
553} 522}
523EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
554 524
555u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel) 525u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
556{ 526{
557 return mgr_desc[channel].sync_lost_irq; 527 return mgr_desc[channel].sync_lost_irq;
558} 528}
529EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
559 530
560u32 dispc_wb_get_framedone_irq(void) 531u32 dispc_wb_get_framedone_irq(void)
561{ 532{
@@ -566,6 +537,7 @@ bool dispc_mgr_go_busy(enum omap_channel channel)
566{ 537{
567 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 538 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
568} 539}
540EXPORT_SYMBOL(dispc_mgr_go_busy);
569 541
570void dispc_mgr_go(enum omap_channel channel) 542void dispc_mgr_go(enum omap_channel channel)
571{ 543{
@@ -576,6 +548,7 @@ void dispc_mgr_go(enum omap_channel channel)
576 548
577 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 549 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
578} 550}
551EXPORT_SYMBOL(dispc_mgr_go);
579 552
580bool dispc_wb_go_busy(void) 553bool dispc_wb_go_busy(void)
581{ 554{
@@ -979,6 +952,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
979 } 952 }
980 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 953 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
981} 954}
955EXPORT_SYMBOL(dispc_ovl_set_channel_out);
982 956
983static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) 957static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
984{ 958{
@@ -2354,6 +2328,47 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
2354 return 0; 2328 return 0;
2355} 2329}
2356 2330
2331int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
2332 const struct omap_overlay_info *oi,
2333 const struct omap_video_timings *timings,
2334 int *x_predecim, int *y_predecim)
2335{
2336 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2337 bool five_taps = true;
2338 bool fieldmode = 0;
2339 u16 in_height = oi->height;
2340 u16 in_width = oi->width;
2341 bool ilace = timings->interlace;
2342 u16 out_width, out_height;
2343 int pos_x = oi->pos_x;
2344 unsigned long pclk = dispc_mgr_pclk_rate(channel);
2345 unsigned long lclk = dispc_mgr_lclk_rate(channel);
2346
2347 out_width = oi->out_width == 0 ? oi->width : oi->out_width;
2348 out_height = oi->out_height == 0 ? oi->height : oi->out_height;
2349
2350 if (ilace && oi->height == out_height)
2351 fieldmode = 1;
2352
2353 if (ilace) {
2354 if (fieldmode)
2355 in_height /= 2;
2356 out_height /= 2;
2357
2358 DSSDBG("adjusting for ilace: height %d, out_height %d\n",
2359 in_height, out_height);
2360 }
2361
2362 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
2363 return -EINVAL;
2364
2365 return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
2366 in_height, out_width, out_height, oi->color_mode,
2367 &five_taps, x_predecim, y_predecim, pos_x,
2368 oi->rotation_type, false);
2369}
2370EXPORT_SYMBOL(dispc_ovl_check);
2371
2357static int dispc_ovl_setup_common(enum omap_plane plane, 2372static int dispc_ovl_setup_common(enum omap_plane plane,
2358 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, 2373 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2359 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height, 2374 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
@@ -2533,6 +2548,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2533 2548
2534 return r; 2549 return r;
2535} 2550}
2551EXPORT_SYMBOL(dispc_ovl_setup);
2536 2552
2537int dispc_wb_setup(const struct omap_dss_writeback_info *wi, 2553int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2538 bool mem_to_mem, const struct omap_video_timings *mgr_timings) 2554 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
@@ -2593,17 +2609,13 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
2593 2609
2594 return 0; 2610 return 0;
2595} 2611}
2612EXPORT_SYMBOL(dispc_ovl_enable);
2596 2613
2597bool dispc_ovl_enabled(enum omap_plane plane) 2614bool dispc_ovl_enabled(enum omap_plane plane)
2598{ 2615{
2599 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); 2616 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2600} 2617}
2601 2618EXPORT_SYMBOL(dispc_ovl_enabled);
2602static void dispc_mgr_disable_isr(void *data, u32 mask)
2603{
2604 struct completion *compl = data;
2605 complete(compl);
2606}
2607 2619
2608void dispc_mgr_enable(enum omap_channel channel, bool enable) 2620void dispc_mgr_enable(enum omap_channel channel, bool enable)
2609{ 2621{
@@ -2611,180 +2623,13 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
2611 /* flush posted write */ 2623 /* flush posted write */
2612 mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); 2624 mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2613} 2625}
2626EXPORT_SYMBOL(dispc_mgr_enable);
2614 2627
2615bool dispc_mgr_is_enabled(enum omap_channel channel) 2628bool dispc_mgr_is_enabled(enum omap_channel channel)
2616{ 2629{
2617 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); 2630 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2618} 2631}
2619 2632EXPORT_SYMBOL(dispc_mgr_is_enabled);
2620static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
2621{
2622 dispc_mgr_enable(channel, true);
2623}
2624
2625static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
2626{
2627 DECLARE_COMPLETION_ONSTACK(framedone_compl);
2628 int r;
2629 u32 irq;
2630
2631 if (dispc_mgr_is_enabled(channel) == false)
2632 return;
2633
2634 /*
2635 * When we disable LCD output, we need to wait for FRAMEDONE to know
2636 * that DISPC has finished with the LCD output.
2637 */
2638
2639 irq = dispc_mgr_get_framedone_irq(channel);
2640
2641 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
2642 irq);
2643 if (r)
2644 DSSERR("failed to register FRAMEDONE isr\n");
2645
2646 dispc_mgr_enable(channel, false);
2647
2648 /* if we couldn't register for framedone, just sleep and exit */
2649 if (r) {
2650 msleep(100);
2651 return;
2652 }
2653
2654 if (!wait_for_completion_timeout(&framedone_compl,
2655 msecs_to_jiffies(100)))
2656 DSSERR("timeout waiting for FRAME DONE\n");
2657
2658 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
2659 irq);
2660 if (r)
2661 DSSERR("failed to unregister FRAMEDONE isr\n");
2662}
2663
2664static void dispc_digit_out_enable_isr(void *data, u32 mask)
2665{
2666 struct completion *compl = data;
2667
2668 /* ignore any sync lost interrupts */
2669 if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
2670 complete(compl);
2671}
2672
2673static void dispc_mgr_enable_digit_out(void)
2674{
2675 DECLARE_COMPLETION_ONSTACK(vsync_compl);
2676 int r;
2677 u32 irq_mask;
2678
2679 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
2680 return;
2681
2682 /*
2683 * Digit output produces some sync lost interrupts during the first
2684 * frame when enabling. Those need to be ignored, so we register for the
2685 * sync lost irq to prevent the error handler from triggering.
2686 */
2687
2688 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
2689 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
2690
2691 r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
2692 irq_mask);
2693 if (r) {
2694 DSSERR("failed to register %x isr\n", irq_mask);
2695 return;
2696 }
2697
2698 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
2699
2700 /* wait for the first evsync */
2701 if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
2702 DSSERR("timeout waiting for digit out to start\n");
2703
2704 r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
2705 irq_mask);
2706 if (r)
2707 DSSERR("failed to unregister %x isr\n", irq_mask);
2708}
2709
2710static void dispc_mgr_disable_digit_out(void)
2711{
2712 DECLARE_COMPLETION_ONSTACK(framedone_compl);
2713 int r, i;
2714 u32 irq_mask;
2715 int num_irqs;
2716
2717 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
2718 return;
2719
2720 /*
2721 * When we disable the digit output, we need to wait for FRAMEDONE to
2722 * know that DISPC has finished with the output.
2723 */
2724
2725 irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
2726 num_irqs = 1;
2727
2728 if (!irq_mask) {
2729 /*
2730 * omap 2/3 don't have framedone irq for TV, so we need to use
2731 * vsyncs for this.
2732 */
2733
2734 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
2735 /*
2736 * We need to wait for both even and odd vsyncs. Note that this
2737 * is not totally reliable, as we could get a vsync interrupt
2738 * before we disable the output, which leads to timeout in the
2739 * wait_for_completion.
2740 */
2741 num_irqs = 2;
2742 }
2743
2744 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
2745 irq_mask);
2746 if (r)
2747 DSSERR("failed to register %x isr\n", irq_mask);
2748
2749 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
2750
2751 /* if we couldn't register the irq, just sleep and exit */
2752 if (r) {
2753 msleep(100);
2754 return;
2755 }
2756
2757 for (i = 0; i < num_irqs; ++i) {
2758 if (!wait_for_completion_timeout(&framedone_compl,
2759 msecs_to_jiffies(100)))
2760 DSSERR("timeout waiting for digit out to stop\n");
2761 }
2762
2763 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
2764 irq_mask);
2765 if (r)
2766 DSSERR("failed to unregister %x isr\n", irq_mask);
2767}
2768
2769void dispc_mgr_enable_sync(enum omap_channel channel)
2770{
2771 if (dss_mgr_is_lcd(channel))
2772 dispc_mgr_enable_lcd_out(channel);
2773 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2774 dispc_mgr_enable_digit_out();
2775 else
2776 WARN_ON(1);
2777}
2778
2779void dispc_mgr_disable_sync(enum omap_channel channel)
2780{
2781 if (dss_mgr_is_lcd(channel))
2782 dispc_mgr_disable_lcd_out(channel);
2783 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2784 dispc_mgr_disable_digit_out();
2785 else
2786 WARN_ON(1);
2787}
2788 2633
2789void dispc_wb_enable(bool enable) 2634void dispc_wb_enable(bool enable)
2790{ 2635{
@@ -2881,6 +2726,7 @@ void dispc_mgr_setup(enum omap_channel channel,
2881 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); 2726 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
2882 } 2727 }
2883} 2728}
2729EXPORT_SYMBOL(dispc_mgr_setup);
2884 2730
2885static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) 2731static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2886{ 2732{
@@ -2957,6 +2803,7 @@ void dispc_mgr_set_lcd_config(enum omap_channel channel,
2957 2803
2958 dispc_mgr_set_lcd_type_tft(channel); 2804 dispc_mgr_set_lcd_type_tft(channel);
2959} 2805}
2806EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
2960 2807
2961static bool _dispc_mgr_size_ok(u16 width, u16 height) 2808static bool _dispc_mgr_size_ok(u16 width, u16 height)
2962{ 2809{
@@ -3095,6 +2942,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
3095 2942
3096 dispc_mgr_set_size(channel, t.x_res, t.y_res); 2943 dispc_mgr_set_size(channel, t.x_res, t.y_res);
3097} 2944}
2945EXPORT_SYMBOL(dispc_mgr_set_timings);
3098 2946
3099static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, 2947static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
3100 u16 pck_div) 2948 u16 pck_div)
@@ -3301,64 +3149,6 @@ void dispc_dump_clocks(struct seq_file *s)
3301 dispc_runtime_put(); 3149 dispc_runtime_put();
3302} 3150}
3303 3151
3304#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3305static void dispc_dump_irqs(struct seq_file *s)
3306{
3307 unsigned long flags;
3308 struct dispc_irq_stats stats;
3309
3310 spin_lock_irqsave(&dispc.irq_stats_lock, flags);
3311
3312 stats = dispc.irq_stats;
3313 memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
3314 dispc.irq_stats.last_reset = jiffies;
3315
3316 spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
3317
3318 seq_printf(s, "period %u ms\n",
3319 jiffies_to_msecs(jiffies - stats.last_reset));
3320
3321 seq_printf(s, "irqs %d\n", stats.irq_count);
3322#define PIS(x) \
3323 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
3324
3325 PIS(FRAMEDONE);
3326 PIS(VSYNC);
3327 PIS(EVSYNC_EVEN);
3328 PIS(EVSYNC_ODD);
3329 PIS(ACBIAS_COUNT_STAT);
3330 PIS(PROG_LINE_NUM);
3331 PIS(GFX_FIFO_UNDERFLOW);
3332 PIS(GFX_END_WIN);
3333 PIS(PAL_GAMMA_MASK);
3334 PIS(OCP_ERR);
3335 PIS(VID1_FIFO_UNDERFLOW);
3336 PIS(VID1_END_WIN);
3337 PIS(VID2_FIFO_UNDERFLOW);
3338 PIS(VID2_END_WIN);
3339 if (dss_feat_get_num_ovls() > 3) {
3340 PIS(VID3_FIFO_UNDERFLOW);
3341 PIS(VID3_END_WIN);
3342 }
3343 PIS(SYNC_LOST);
3344 PIS(SYNC_LOST_DIGIT);
3345 PIS(WAKEUP);
3346 if (dss_has_feature(FEAT_MGR_LCD2)) {
3347 PIS(FRAMEDONE2);
3348 PIS(VSYNC2);
3349 PIS(ACBIAS_COUNT_STAT2);
3350 PIS(SYNC_LOST2);
3351 }
3352 if (dss_has_feature(FEAT_MGR_LCD3)) {
3353 PIS(FRAMEDONE3);
3354 PIS(VSYNC3);
3355 PIS(ACBIAS_COUNT_STAT3);
3356 PIS(SYNC_LOST3);
3357 }
3358#undef PIS
3359}
3360#endif
3361
3362static void dispc_dump_regs(struct seq_file *s) 3152static void dispc_dump_regs(struct seq_file *s)
3363{ 3153{
3364 int i, j; 3154 int i, j;
@@ -3616,16 +3406,19 @@ u32 dispc_read_irqstatus(void)
3616{ 3406{
3617 return dispc_read_reg(DISPC_IRQSTATUS); 3407 return dispc_read_reg(DISPC_IRQSTATUS);
3618} 3408}
3409EXPORT_SYMBOL(dispc_read_irqstatus);
3619 3410
3620void dispc_clear_irqstatus(u32 mask) 3411void dispc_clear_irqstatus(u32 mask)
3621{ 3412{
3622 dispc_write_reg(DISPC_IRQSTATUS, mask); 3413 dispc_write_reg(DISPC_IRQSTATUS, mask);
3623} 3414}
3415EXPORT_SYMBOL(dispc_clear_irqstatus);
3624 3416
3625u32 dispc_read_irqenable(void) 3417u32 dispc_read_irqenable(void)
3626{ 3418{
3627 return dispc_read_reg(DISPC_IRQENABLE); 3419 return dispc_read_reg(DISPC_IRQENABLE);
3628} 3420}
3421EXPORT_SYMBOL(dispc_read_irqenable);
3629 3422
3630void dispc_write_irqenable(u32 mask) 3423void dispc_write_irqenable(u32 mask)
3631{ 3424{
@@ -3636,376 +3429,7 @@ void dispc_write_irqenable(u32 mask)
3636 3429
3637 dispc_write_reg(DISPC_IRQENABLE, mask); 3430 dispc_write_reg(DISPC_IRQENABLE, mask);
3638} 3431}
3639 3432EXPORT_SYMBOL(dispc_write_irqenable);
3640/* dispc.irq_lock has to be locked by the caller */
3641static void _omap_dispc_set_irqs(void)
3642{
3643 u32 mask;
3644 int i;
3645 struct omap_dispc_isr_data *isr_data;
3646
3647 mask = dispc.irq_error_mask;
3648
3649 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3650 isr_data = &dispc.registered_isr[i];
3651
3652 if (isr_data->isr == NULL)
3653 continue;
3654
3655 mask |= isr_data->mask;
3656 }
3657
3658 dispc_write_irqenable(mask);
3659}
3660
3661int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
3662{
3663 int i;
3664 int ret;
3665 unsigned long flags;
3666 struct omap_dispc_isr_data *isr_data;
3667
3668 if (isr == NULL)
3669 return -EINVAL;
3670
3671 spin_lock_irqsave(&dispc.irq_lock, flags);
3672
3673 /* check for duplicate entry */
3674 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3675 isr_data = &dispc.registered_isr[i];
3676 if (isr_data->isr == isr && isr_data->arg == arg &&
3677 isr_data->mask == mask) {
3678 ret = -EINVAL;
3679 goto err;
3680 }
3681 }
3682
3683 isr_data = NULL;
3684 ret = -EBUSY;
3685
3686 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3687 isr_data = &dispc.registered_isr[i];
3688
3689 if (isr_data->isr != NULL)
3690 continue;
3691
3692 isr_data->isr = isr;
3693 isr_data->arg = arg;
3694 isr_data->mask = mask;
3695 ret = 0;
3696
3697 break;
3698 }
3699
3700 if (ret)
3701 goto err;
3702
3703 _omap_dispc_set_irqs();
3704
3705 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3706
3707 return 0;
3708err:
3709 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3710
3711 return ret;
3712}
3713EXPORT_SYMBOL(omap_dispc_register_isr);
3714
3715int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
3716{
3717 int i;
3718 unsigned long flags;
3719 int ret = -EINVAL;
3720 struct omap_dispc_isr_data *isr_data;
3721
3722 spin_lock_irqsave(&dispc.irq_lock, flags);
3723
3724 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3725 isr_data = &dispc.registered_isr[i];
3726 if (isr_data->isr != isr || isr_data->arg != arg ||
3727 isr_data->mask != mask)
3728 continue;
3729
3730 /* found the correct isr */
3731
3732 isr_data->isr = NULL;
3733 isr_data->arg = NULL;
3734 isr_data->mask = 0;
3735
3736 ret = 0;
3737 break;
3738 }
3739
3740 if (ret == 0)
3741 _omap_dispc_set_irqs();
3742
3743 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3744
3745 return ret;
3746}
3747EXPORT_SYMBOL(omap_dispc_unregister_isr);
3748
3749static void print_irq_status(u32 status)
3750{
3751 if ((status & dispc.irq_error_mask) == 0)
3752 return;
3753
3754#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
3755
3756 pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
3757 status,
3758 PIS(OCP_ERR),
3759 PIS(GFX_FIFO_UNDERFLOW),
3760 PIS(VID1_FIFO_UNDERFLOW),
3761 PIS(VID2_FIFO_UNDERFLOW),
3762 dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
3763 PIS(SYNC_LOST),
3764 PIS(SYNC_LOST_DIGIT),
3765 dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
3766 dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
3767#undef PIS
3768}
3769
3770/* Called from dss.c. Note that we don't touch clocks here,
3771 * but we presume they are on because we got an IRQ. However,
3772 * an irq handler may turn the clocks off, so we may not have
3773 * clock later in the function. */
3774static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
3775{
3776 int i;
3777 u32 irqstatus, irqenable;
3778 u32 handledirqs = 0;
3779 u32 unhandled_errors;
3780 struct omap_dispc_isr_data *isr_data;
3781 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
3782
3783 spin_lock(&dispc.irq_lock);
3784
3785 irqstatus = dispc_read_irqstatus();
3786 irqenable = dispc_read_irqenable();
3787
3788 /* IRQ is not for us */
3789 if (!(irqstatus & irqenable)) {
3790 spin_unlock(&dispc.irq_lock);
3791 return IRQ_NONE;
3792 }
3793
3794#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3795 spin_lock(&dispc.irq_stats_lock);
3796 dispc.irq_stats.irq_count++;
3797 dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
3798 spin_unlock(&dispc.irq_stats_lock);
3799#endif
3800
3801 print_irq_status(irqstatus);
3802
3803 /* Ack the interrupt. Do it here before clocks are possibly turned
3804 * off */
3805 dispc_clear_irqstatus(irqstatus);
3806 /* flush posted write */
3807 dispc_read_irqstatus();
3808
3809 /* make a copy and unlock, so that isrs can unregister
3810 * themselves */
3811 memcpy(registered_isr, dispc.registered_isr,
3812 sizeof(registered_isr));
3813
3814 spin_unlock(&dispc.irq_lock);
3815
3816 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3817 isr_data = &registered_isr[i];
3818
3819 if (!isr_data->isr)
3820 continue;
3821
3822 if (isr_data->mask & irqstatus) {
3823 isr_data->isr(isr_data->arg, irqstatus);
3824 handledirqs |= isr_data->mask;
3825 }
3826 }
3827
3828 spin_lock(&dispc.irq_lock);
3829
3830 unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
3831
3832 if (unhandled_errors) {
3833 dispc.error_irqs |= unhandled_errors;
3834
3835 dispc.irq_error_mask &= ~unhandled_errors;
3836 _omap_dispc_set_irqs();
3837
3838 schedule_work(&dispc.error_work);
3839 }
3840
3841 spin_unlock(&dispc.irq_lock);
3842
3843 return IRQ_HANDLED;
3844}
3845
3846static void dispc_error_worker(struct work_struct *work)
3847{
3848 int i;
3849 u32 errors;
3850 unsigned long flags;
3851 static const unsigned fifo_underflow_bits[] = {
3852 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
3853 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
3854 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
3855 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
3856 };
3857
3858 spin_lock_irqsave(&dispc.irq_lock, flags);
3859 errors = dispc.error_irqs;
3860 dispc.error_irqs = 0;
3861 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3862
3863 dispc_runtime_get();
3864
3865 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3866 struct omap_overlay *ovl;
3867 unsigned bit;
3868
3869 ovl = omap_dss_get_overlay(i);
3870 bit = fifo_underflow_bits[i];
3871
3872 if (bit & errors) {
3873 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
3874 ovl->name);
3875 dispc_ovl_enable(ovl->id, false);
3876 dispc_mgr_go(ovl->manager->id);
3877 msleep(50);
3878 }
3879 }
3880
3881 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3882 struct omap_overlay_manager *mgr;
3883 unsigned bit;
3884
3885 mgr = omap_dss_get_overlay_manager(i);
3886 bit = mgr_desc[i].sync_lost_irq;
3887
3888 if (bit & errors) {
3889 int j;
3890
3891 DSSERR("SYNC_LOST on channel %s, restarting the output "
3892 "with video overlays disabled\n",
3893 mgr->name);
3894
3895 dss_mgr_disable(mgr);
3896
3897 for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
3898 struct omap_overlay *ovl;
3899 ovl = omap_dss_get_overlay(j);
3900
3901 if (ovl->id != OMAP_DSS_GFX &&
3902 ovl->manager == mgr)
3903 ovl->disable(ovl);
3904 }
3905
3906 dss_mgr_enable(mgr);
3907 }
3908 }
3909
3910 if (errors & DISPC_IRQ_OCP_ERR) {
3911 DSSERR("OCP_ERR\n");
3912 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3913 struct omap_overlay_manager *mgr;
3914
3915 mgr = omap_dss_get_overlay_manager(i);
3916 dss_mgr_disable(mgr);
3917 }
3918 }
3919
3920 spin_lock_irqsave(&dispc.irq_lock, flags);
3921 dispc.irq_error_mask |= errors;
3922 _omap_dispc_set_irqs();
3923 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3924
3925 dispc_runtime_put();
3926}
3927
3928int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
3929{
3930 void dispc_irq_wait_handler(void *data, u32 mask)
3931 {
3932 complete((struct completion *)data);
3933 }
3934
3935 int r;
3936 DECLARE_COMPLETION_ONSTACK(completion);
3937
3938 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3939 irqmask);
3940
3941 if (r)
3942 return r;
3943
3944 timeout = wait_for_completion_timeout(&completion, timeout);
3945
3946 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3947
3948 if (timeout == 0)
3949 return -ETIMEDOUT;
3950
3951 return 0;
3952}
3953
3954int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
3955 unsigned long timeout)
3956{
3957 void dispc_irq_wait_handler(void *data, u32 mask)
3958 {
3959 complete((struct completion *)data);
3960 }
3961
3962 int r;
3963 DECLARE_COMPLETION_ONSTACK(completion);
3964
3965 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3966 irqmask);
3967
3968 if (r)
3969 return r;
3970
3971 timeout = wait_for_completion_interruptible_timeout(&completion,
3972 timeout);
3973
3974 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3975
3976 if (timeout == 0)
3977 return -ETIMEDOUT;
3978
3979 if (timeout == -ERESTARTSYS)
3980 return -ERESTARTSYS;
3981
3982 return 0;
3983}
3984
3985static void _omap_dispc_initialize_irq(void)
3986{
3987 unsigned long flags;
3988
3989 spin_lock_irqsave(&dispc.irq_lock, flags);
3990
3991 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
3992
3993 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3994 if (dss_has_feature(FEAT_MGR_LCD2))
3995 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
3996 if (dss_has_feature(FEAT_MGR_LCD3))
3997 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
3998 if (dss_feat_get_num_ovls() > 3)
3999 dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
4000
4001 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
4002 * so clear it */
4003 dispc_clear_irqstatus(dispc_read_irqstatus());
4004
4005 _omap_dispc_set_irqs();
4006
4007 spin_unlock_irqrestore(&dispc.irq_lock, flags);
4008}
4009 3433
4010void dispc_enable_sidle(void) 3434void dispc_enable_sidle(void)
4011{ 3435{
@@ -4176,6 +3600,19 @@ static int __init dispc_init_features(struct platform_device *pdev)
4176 return 0; 3600 return 0;
4177} 3601}
4178 3602
3603int dispc_request_irq(irq_handler_t handler, void *dev_id)
3604{
3605 return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
3606 IRQF_SHARED, "OMAP DISPC", dev_id);
3607}
3608EXPORT_SYMBOL(dispc_request_irq);
3609
3610void dispc_free_irq(void *dev_id)
3611{
3612 devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
3613}
3614EXPORT_SYMBOL(dispc_free_irq);
3615
4179/* DISPC HW IP initialisation */ 3616/* DISPC HW IP initialisation */
4180static int __init omap_dispchw_probe(struct platform_device *pdev) 3617static int __init omap_dispchw_probe(struct platform_device *pdev)
4181{ 3618{
@@ -4190,15 +3627,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4190 if (r) 3627 if (r)
4191 return r; 3628 return r;
4192 3629
4193 spin_lock_init(&dispc.irq_lock);
4194
4195#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
4196 spin_lock_init(&dispc.irq_stats_lock);
4197 dispc.irq_stats.last_reset = jiffies;
4198#endif
4199
4200 INIT_WORK(&dispc.error_work, dispc_error_worker);
4201
4202 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); 3630 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
4203 if (!dispc_mem) { 3631 if (!dispc_mem) {
4204 DSSERR("can't get IORESOURCE_MEM DISPC\n"); 3632 DSSERR("can't get IORESOURCE_MEM DISPC\n");
@@ -4218,13 +3646,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4218 return -ENODEV; 3646 return -ENODEV;
4219 } 3647 }
4220 3648
4221 r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
4222 IRQF_SHARED, "OMAP DISPC", dispc.pdev);
4223 if (r < 0) {
4224 DSSERR("request_irq failed\n");
4225 return r;
4226 }
4227
4228 clk = clk_get(&pdev->dev, "fck"); 3649 clk = clk_get(&pdev->dev, "fck");
4229 if (IS_ERR(clk)) { 3650 if (IS_ERR(clk)) {
4230 DSSERR("can't get fck\n"); 3651 DSSERR("can't get fck\n");
@@ -4242,8 +3663,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4242 3663
4243 _omap_dispc_initial_config(); 3664 _omap_dispc_initial_config();
4244 3665
4245 _omap_dispc_initialize_irq();
4246
4247 rev = dispc_read_reg(DISPC_REVISION); 3666 rev = dispc_read_reg(DISPC_REVISION);
4248 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", 3667 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
4249 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 3668 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -4252,9 +3671,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4252 3671
4253 dss_debugfs_create_file("dispc", dispc_dump_regs); 3672 dss_debugfs_create_file("dispc", dispc_dump_regs);
4254 3673
4255#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
4256 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
4257#endif
4258 return 0; 3674 return 0;
4259 3675
4260err_runtime_get: 3676err_runtime_get:
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 05f21b6231b7..0aa8ad8f9667 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -76,26 +76,6 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
76} 76}
77EXPORT_SYMBOL(omapdss_default_get_timings); 77EXPORT_SYMBOL(omapdss_default_get_timings);
78 78
79int dss_init_device(struct platform_device *pdev,
80 struct omap_dss_device *dssdev)
81{
82 int r;
83
84 r = display_init_sysfs(pdev, dssdev);
85 if (r) {
86 omapdss_output_unset_device(dssdev->output);
87 return r;
88 }
89
90 return 0;
91}
92
93void dss_uninit_device(struct platform_device *pdev,
94 struct omap_dss_device *dssdev)
95{
96 display_uninit_sysfs(pdev, dssdev);
97}
98
99static int dss_suspend_device(struct device *dev, void *data) 79static int dss_suspend_device(struct device *dev, void *data)
100{ 80{
101 struct omap_dss_device *dssdev = to_dss_device(dev); 81 struct omap_dss_device *dssdev = to_dss_device(dev);
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index d5bc47a4f3ee..6cbcc81991a1 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -315,7 +315,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
315 unsigned long pck; 315 unsigned long pck;
316 struct dispc_clock_info dispc_cinfo; 316 struct dispc_clock_info dispc_cinfo;
317 317
318 if (dss_mgr_check_timings(mgr, timings)) 318 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
319 return -EINVAL; 319 return -EINVAL;
320 320
321 if (timings->pixel_clock == 0) 321 if (timings->pixel_clock == 0)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index db9663dcfbd0..28d41d16b7be 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4535,7 +4535,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4535 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT); 4535 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
4536} 4536}
4537 4537
4538static void dsi_framedone_irq_callback(void *data, u32 mask) 4538static void dsi_framedone_irq_callback(void *data)
4539{ 4539{
4540 struct platform_device *dsidev = (struct platform_device *) data; 4540 struct platform_device *dsidev = (struct platform_device *) data;
4541 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4541 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4609,7 +4609,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4609 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4609 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4610 struct omap_overlay_manager *mgr = dssdev->output->manager; 4610 struct omap_overlay_manager *mgr = dssdev->output->manager;
4611 int r; 4611 int r;
4612 u32 irq = 0;
4613 4612
4614 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4613 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4615 dsi->timings.hsw = 1; 4614 dsi->timings.hsw = 1;
@@ -4619,12 +4618,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4619 dsi->timings.vfp = 0; 4618 dsi->timings.vfp = 0;
4620 dsi->timings.vbp = 0; 4619 dsi->timings.vbp = 0;
4621 4620
4622 irq = dispc_mgr_get_framedone_irq(mgr->id); 4621 r = dss_mgr_register_framedone_handler(mgr,
4623 4622 dsi_framedone_irq_callback, dsidev);
4624 r = omap_dispc_register_isr(dsi_framedone_irq_callback,
4625 (void *) dsidev, irq);
4626 if (r) { 4623 if (r) {
4627 DSSERR("can't get FRAMEDONE irq\n"); 4624 DSSERR("can't register FRAMEDONE handler\n");
4628 goto err; 4625 goto err;
4629 } 4626 }
4630 4627
@@ -4662,8 +4659,8 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4662 return 0; 4659 return 0;
4663err1: 4660err1:
4664 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) 4661 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4665 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4662 dss_mgr_unregister_framedone_handler(mgr,
4666 (void *) dsidev, irq); 4663 dsi_framedone_irq_callback, dsidev);
4667err: 4664err:
4668 return r; 4665 return r;
4669} 4666}
@@ -4674,14 +4671,9 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4674 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4675 struct omap_overlay_manager *mgr = dssdev->output->manager; 4672 struct omap_overlay_manager *mgr = dssdev->output->manager;
4676 4673
4677 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4678 u32 irq; 4675 dss_mgr_unregister_framedone_handler(mgr,
4679 4676 dsi_framedone_irq_callback, dsidev);
4680 irq = dispc_mgr_get_framedone_irq(mgr->id);
4681
4682 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4683 (void *) dsidev, irq);
4684 }
4685} 4677}
4686 4678
4687static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) 4679static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index bdf843135661..ebe9e08b2a91 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -23,6 +23,8 @@
23#ifndef __OMAP2_DSS_H 23#ifndef __OMAP2_DSS_H
24#define __OMAP2_DSS_H 24#define __OMAP2_DSS_H
25 25
26#include <linux/interrupt.h>
27
26#ifdef pr_fmt 28#ifdef pr_fmt
27#undef pr_fmt 29#undef pr_fmt
28#endif 30#endif
@@ -177,38 +179,6 @@ void dss_put_device(struct omap_dss_device *dssdev);
177void dss_copy_device_pdata(struct omap_dss_device *dst, 179void dss_copy_device_pdata(struct omap_dss_device *dst,
178 const struct omap_dss_device *src); 180 const struct omap_dss_device *src);
179 181
180/* apply */
181void dss_apply_init(void);
182int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
183int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
184void dss_mgr_start_update(struct omap_overlay_manager *mgr);
185int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
186
187int dss_mgr_enable(struct omap_overlay_manager *mgr);
188void dss_mgr_disable(struct omap_overlay_manager *mgr);
189int dss_mgr_set_info(struct omap_overlay_manager *mgr,
190 struct omap_overlay_manager_info *info);
191void dss_mgr_get_info(struct omap_overlay_manager *mgr,
192 struct omap_overlay_manager_info *info);
193int dss_mgr_set_output(struct omap_overlay_manager *mgr,
194 struct omap_dss_output *output);
195int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
196void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
197 const struct omap_video_timings *timings);
198void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
199 const struct dss_lcd_mgr_config *config);
200
201bool dss_ovl_is_enabled(struct omap_overlay *ovl);
202int dss_ovl_enable(struct omap_overlay *ovl);
203int dss_ovl_disable(struct omap_overlay *ovl);
204int dss_ovl_set_info(struct omap_overlay *ovl,
205 struct omap_overlay_info *info);
206void dss_ovl_get_info(struct omap_overlay *ovl,
207 struct omap_overlay_info *info);
208int dss_ovl_set_manager(struct omap_overlay *ovl,
209 struct omap_overlay_manager *mgr);
210int dss_ovl_unset_manager(struct omap_overlay *ovl);
211
212/* output */ 182/* output */
213void dss_register_output(struct omap_dss_output *out); 183void dss_register_output(struct omap_dss_output *out);
214void dss_unregister_output(struct omap_dss_output *out); 184void dss_unregister_output(struct omap_dss_output *out);
@@ -218,11 +188,6 @@ int dss_suspend_all_devices(void);
218int dss_resume_all_devices(void); 188int dss_resume_all_devices(void);
219void dss_disable_all_devices(void); 189void dss_disable_all_devices(void);
220 190
221int dss_init_device(struct platform_device *pdev,
222 struct omap_dss_device *dssdev);
223void dss_uninit_device(struct platform_device *pdev,
224 struct omap_dss_device *dssdev);
225
226int display_init_sysfs(struct platform_device *pdev, 191int display_init_sysfs(struct platform_device *pdev,
227 struct omap_dss_device *dssdev); 192 struct omap_dss_device *dssdev);
228void display_uninit_sysfs(struct platform_device *pdev, 193void display_uninit_sysfs(struct platform_device *pdev,
@@ -400,13 +365,6 @@ void dpi_uninit_platform_driver(void) __exit;
400int dispc_init_platform_driver(void) __init; 365int dispc_init_platform_driver(void) __init;
401void dispc_uninit_platform_driver(void) __exit; 366void dispc_uninit_platform_driver(void) __exit;
402void dispc_dump_clocks(struct seq_file *s); 367void dispc_dump_clocks(struct seq_file *s);
403u32 dispc_read_irqstatus(void);
404void dispc_clear_irqstatus(u32 mask);
405u32 dispc_read_irqenable(void);
406void dispc_write_irqenable(u32 mask);
407
408int dispc_runtime_get(void);
409void dispc_runtime_put(void);
410 368
411void dispc_enable_sidle(void); 369void dispc_enable_sidle(void);
412void dispc_disable_sidle(void); 370void dispc_disable_sidle(void);
@@ -430,27 +388,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
430void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 388void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
431 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, 389 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
432 bool manual_update); 390 bool manual_update);
433int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, 391
434 bool replication, const struct omap_video_timings *mgr_timings,
435 bool mem_to_mem);
436int dispc_ovl_enable(enum omap_plane plane, bool enable);
437bool dispc_ovl_enabled(enum omap_plane plane);
438void dispc_ovl_set_channel_out(enum omap_plane plane,
439 enum omap_channel channel);
440
441u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
442u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
443u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
444bool dispc_mgr_go_busy(enum omap_channel channel);
445void dispc_mgr_go(enum omap_channel channel);
446void dispc_mgr_enable(enum omap_channel channel, bool enable);
447bool dispc_mgr_is_enabled(enum omap_channel channel);
448void dispc_mgr_enable_sync(enum omap_channel channel);
449void dispc_mgr_disable_sync(enum omap_channel channel);
450void dispc_mgr_set_lcd_config(enum omap_channel channel,
451 const struct dss_lcd_mgr_config *config);
452void dispc_mgr_set_timings(enum omap_channel channel,
453 const struct omap_video_timings *timings);
454unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); 392unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
455unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); 393unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
456unsigned long dispc_core_clk_rate(void); 394unsigned long dispc_core_clk_rate(void);
@@ -458,8 +396,6 @@ void dispc_mgr_set_clock_div(enum omap_channel channel,
458 const struct dispc_clock_info *cinfo); 396 const struct dispc_clock_info *cinfo);
459int dispc_mgr_get_clock_div(enum omap_channel channel, 397int dispc_mgr_get_clock_div(enum omap_channel channel,
460 struct dispc_clock_info *cinfo); 398 struct dispc_clock_info *cinfo);
461void dispc_mgr_setup(enum omap_channel channel,
462 const struct omap_overlay_manager_info *info);
463 399
464u32 dispc_wb_get_framedone_irq(void); 400u32 dispc_wb_get_framedone_irq(void);
465bool dispc_wb_go_busy(void); 401bool dispc_wb_go_busy(void);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 1d125c6bfd19..18688c12e30d 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -18,6 +18,7 @@
18 */ 18 */
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h>
21#include <linux/types.h> 22#include <linux/types.h>
22#include <linux/err.h> 23#include <linux/err.h>
23#include <linux/slab.h> 24#include <linux/slab.h>
@@ -839,11 +840,13 @@ int dss_feat_get_num_mgrs(void)
839{ 840{
840 return omap_current_dss_features->num_mgrs; 841 return omap_current_dss_features->num_mgrs;
841} 842}
843EXPORT_SYMBOL(dss_feat_get_num_mgrs);
842 844
843int dss_feat_get_num_ovls(void) 845int dss_feat_get_num_ovls(void)
844{ 846{
845 return omap_current_dss_features->num_ovls; 847 return omap_current_dss_features->num_ovls;
846} 848}
849EXPORT_SYMBOL(dss_feat_get_num_ovls);
847 850
848int dss_feat_get_num_wbs(void) 851int dss_feat_get_num_wbs(void)
849{ 852{
@@ -864,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
864{ 867{
865 return omap_current_dss_features->supported_displays[channel]; 868 return omap_current_dss_features->supported_displays[channel];
866} 869}
870EXPORT_SYMBOL(dss_feat_get_supported_displays);
867 871
868enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) 872enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
869{ 873{
870 return omap_current_dss_features->supported_outputs[channel]; 874 return omap_current_dss_features->supported_outputs[channel];
871} 875}
876EXPORT_SYMBOL(dss_feat_get_supported_outputs);
872 877
873enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) 878enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
874{ 879{
875 return omap_current_dss_features->supported_color_modes[plane]; 880 return omap_current_dss_features->supported_color_modes[plane];
876} 881}
882EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
877 883
878enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) 884enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
879{ 885{
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 385b0afe63c2..489b9bec4a6d 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -101,14 +101,9 @@ enum dss_range_param {
101}; 101};
102 102
103/* DSS Feature Functions */ 103/* DSS Feature Functions */
104int dss_feat_get_num_mgrs(void);
105int dss_feat_get_num_ovls(void);
106int dss_feat_get_num_wbs(void); 104int dss_feat_get_num_wbs(void);
107unsigned long dss_feat_get_param_min(enum dss_range_param param); 105unsigned long dss_feat_get_param_min(enum dss_range_param param);
108unsigned long dss_feat_get_param_max(enum dss_range_param param); 106unsigned long dss_feat_get_param_max(enum dss_range_param param);
109enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
110enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
111enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
112enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 107enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
113bool dss_feat_color_mode_supported(enum omap_plane plane, 108bool dss_feat_color_mode_supported(enum omap_plane plane,
114 enum omap_color_mode color_mode); 109 enum omap_color_mode color_mode);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index c54d2f620ce3..2551eaa14c42 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -36,36 +36,6 @@
36static int num_managers; 36static int num_managers;
37static struct omap_overlay_manager *managers; 37static struct omap_overlay_manager *managers;
38 38
39static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
40{
41 return mgr->output ? mgr->output->device : NULL;
42}
43
44static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
45{
46 unsigned long timeout = msecs_to_jiffies(500);
47 struct omap_dss_device *dssdev = mgr->get_device(mgr);
48 u32 irq;
49 int r;
50
51 r = dispc_runtime_get();
52 if (r)
53 return r;
54
55 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
56 irq = DISPC_IRQ_EVSYNC_ODD;
57 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
58 irq = DISPC_IRQ_EVSYNC_EVEN;
59 else
60 irq = dispc_mgr_get_vsync_irq(mgr->id);
61
62 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
63
64 dispc_runtime_put();
65
66 return r;
67}
68
69int dss_init_overlay_managers(struct platform_device *pdev) 39int dss_init_overlay_managers(struct platform_device *pdev)
70{ 40{
71 int i, r; 41 int i, r;
@@ -99,15 +69,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
99 break; 69 break;
100 } 70 }
101 71
102 mgr->set_output = &dss_mgr_set_output;
103 mgr->unset_output = &dss_mgr_unset_output;
104 mgr->apply = &omap_dss_mgr_apply;
105 mgr->set_manager_info = &dss_mgr_set_info;
106 mgr->get_manager_info = &dss_mgr_get_info;
107 mgr->wait_for_go = &dss_mgr_wait_for_go;
108 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
109 mgr->get_device = &dss_mgr_get_device;
110
111 mgr->caps = 0; 72 mgr->caps = 0;
112 mgr->supported_displays = 73 mgr->supported_displays =
113 dss_feat_get_supported_displays(mgr->id); 74 dss_feat_get_supported_displays(mgr->id);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 1a84b79d5580..79dea1a1a732 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -113,3 +113,68 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
113 113
114 return NULL; 114 return NULL;
115} 115}
116
117static const struct dss_mgr_ops *dss_mgr_ops;
118
119int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
120{
121 if (dss_mgr_ops)
122 return -EBUSY;
123
124 dss_mgr_ops = mgr_ops;
125
126 return 0;
127}
128EXPORT_SYMBOL(dss_install_mgr_ops);
129
130void dss_uninstall_mgr_ops(void)
131{
132 dss_mgr_ops = NULL;
133}
134EXPORT_SYMBOL(dss_uninstall_mgr_ops);
135
136void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
137 const struct omap_video_timings *timings)
138{
139 dss_mgr_ops->set_timings(mgr, timings);
140}
141EXPORT_SYMBOL(dss_mgr_set_timings);
142
143void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
144 const struct dss_lcd_mgr_config *config)
145{
146 dss_mgr_ops->set_lcd_config(mgr, config);
147}
148EXPORT_SYMBOL(dss_mgr_set_lcd_config);
149
150int dss_mgr_enable(struct omap_overlay_manager *mgr)
151{
152 return dss_mgr_ops->enable(mgr);
153}
154EXPORT_SYMBOL(dss_mgr_enable);
155
156void dss_mgr_disable(struct omap_overlay_manager *mgr)
157{
158 dss_mgr_ops->disable(mgr);
159}
160EXPORT_SYMBOL(dss_mgr_disable);
161
162void dss_mgr_start_update(struct omap_overlay_manager *mgr)
163{
164 dss_mgr_ops->start_update(mgr);
165}
166EXPORT_SYMBOL(dss_mgr_start_update);
167
168int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
169 void (*handler)(void *), void *data)
170{
171 return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
172}
173EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
174
175void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
176 void (*handler)(void *), void *data)
177{
178 dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
179}
180EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 45f4994bc6b0..eccde322c28a 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -38,13 +38,6 @@
38static int num_overlays; 38static int num_overlays;
39static struct omap_overlay *overlays; 39static struct omap_overlay *overlays;
40 40
41static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
42{
43 return ovl->manager ?
44 (ovl->manager->output ? ovl->manager->output->device : NULL) :
45 NULL;
46}
47
48int omap_dss_get_num_overlays(void) 41int omap_dss_get_num_overlays(void)
49{ 42{
50 return num_overlays; 43 return num_overlays;
@@ -93,16 +86,6 @@ void dss_init_overlays(struct platform_device *pdev)
93 break; 86 break;
94 } 87 }
95 88
96 ovl->is_enabled = &dss_ovl_is_enabled;
97 ovl->enable = &dss_ovl_enable;
98 ovl->disable = &dss_ovl_disable;
99 ovl->set_manager = &dss_ovl_set_manager;
100 ovl->unset_manager = &dss_ovl_unset_manager;
101 ovl->set_overlay_info = &dss_ovl_set_info;
102 ovl->get_overlay_info = &dss_ovl_get_info;
103 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
104 ovl->get_device = &dss_ovl_get_device;
105
106 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 89 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
107 ovl->supported_modes = 90 ovl->supported_modes =
108 dss_feat_get_supported_color_modes(ovl->id); 91 dss_feat_get_supported_color_modes(ovl->id);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index ec9fde52716c..e903dd3f54d9 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -342,7 +342,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
342 return 0; 342 return 0;
343} 343}
344 344
345static void framedone_callback(void *data, u32 mask) 345static void framedone_callback(void *data)
346{ 346{
347 void (*callback)(void *data); 347 void (*callback)(void *data);
348 348
@@ -908,8 +908,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
908 goto err0; 908 goto err0;
909 } 909 }
910 910
911 r = omap_dispc_register_isr(framedone_callback, NULL, 911 r = dss_mgr_register_framedone_handler(out->manager,
912 DISPC_IRQ_FRAMEDONE); 912 framedone_callback, NULL);
913 if (r) { 913 if (r) {
914 DSSERR("can't get FRAMEDONE irq\n"); 914 DSSERR("can't get FRAMEDONE irq\n");
915 goto err1; 915 goto err1;
@@ -933,8 +933,10 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
933 933
934void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) 934void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
935{ 935{
936 omap_dispc_unregister_isr(framedone_callback, NULL, 936 struct omap_dss_output *out = dssdev->output;
937 DISPC_IRQ_FRAMEDONE); 937
938 dss_mgr_unregister_framedone_handler(out->manager,
939 framedone_callback, NULL);
938 omap_dss_stop_device(dssdev); 940 omap_dss_stop_device(dssdev);
939 941
940 rfbi_runtime_put(); 942 rfbi_runtime_put();
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 1f60741a7886..4fa9487a8720 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2425,6 +2425,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
2425 "ignoring the module parameter vrfb=y\n"); 2425 "ignoring the module parameter vrfb=y\n");
2426 } 2426 }
2427 2427
2428 r = omapdss_compat_init();
2429 if (r)
2430 goto err0;
2428 2431
2429 mutex_init(&fbdev->mtx); 2432 mutex_init(&fbdev->mtx);
2430 2433
@@ -2544,6 +2547,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
2544 2547
2545cleanup: 2548cleanup:
2546 omapfb_free_resources(fbdev); 2549 omapfb_free_resources(fbdev);
2550 omapdss_compat_uninit();
2547err0: 2551err0:
2548 dev_err(&pdev->dev, "failed to setup omapfb\n"); 2552 dev_err(&pdev->dev, "failed to setup omapfb\n");
2549 return r; 2553 return r;
@@ -2559,6 +2563,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
2559 2563
2560 omapfb_free_resources(fbdev); 2564 omapfb_free_resources(fbdev);
2561 2565
2566 omapdss_compat_uninit();
2567
2562 return 0; 2568 return 0;
2563} 2569}
2564 2570