aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-12-10 06:13:32 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-12-10 06:13:32 -0500
commitd10ecc5887a5671f2c71752b1624549a4a48b1fe (patch)
treedf88c096edcff99241371e5338439fd3faef59aa
parent6b6f1edfdb6c41e630e4a70d64a8e8817b3170c2 (diff)
parenta9ee9f08b615f746f31a41a6415712081c1a2865 (diff)
Merge omapdss compat layer work
We have two separate, exclusive, users of omapdss: 1) omapfb + omap_vout and 2) omapdrm. Because omapfb and omap_vout are independent drivers, we've built layers in omapdss to manage the two simultaneous callers. These layers are not needed for omapdrm, as omapdrm is the sole user of omapdss, and these layers in fact only create trouble for omapdrm. The simple option to improve omapdrm situation would be to copy the omapdss code for omapdrm. We are trying to avoid this, as omapdss and the panel drivers are quite a lot of code together, and most of the code would be used without change. Thus this series helps the situation by moving the omapdss code required by omapfb + omap_vout to separate files, creating a distinct layer used only by omapfb + omap_vout. We call this layer "compat layer". This compat layer then uses the core omapdss driver to operate the hardware. omapdrm will use the core omapdss directly, without any layers in between. After this series, omapfb, omap_vout and omapdrm can all be compiled at the same time. Obviously omapdrm and omapfb+omap_vout cannot be run at the same time (the first one to start will "win"), so compiling them at the same time is only sensible as modules for testing purposes. Normal users should only compile one of those. This series does not make omapdrm use the core omapdss API, that will happen in a separate series for omapdrm.
-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
-rw-r--r--include/video/omapdss.h81
20 files changed, 1202 insertions, 872 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
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index b1248c2d36e1..caefa093337d 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -21,6 +21,7 @@
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/kobject.h> 22#include <linux/kobject.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/interrupt.h>
24 25
25#define DISPC_IRQ_FRAMEDONE (1 << 0) 26#define DISPC_IRQ_FRAMEDONE (1 << 0)
26#define DISPC_IRQ_VSYNC (1 << 1) 27#define DISPC_IRQ_VSYNC (1 << 1)
@@ -55,6 +56,7 @@
55 56
56struct omap_dss_device; 57struct omap_dss_device;
57struct omap_overlay_manager; 58struct omap_overlay_manager;
59struct dss_lcd_mgr_config;
58struct snd_aes_iec958; 60struct snd_aes_iec958;
59struct snd_cea_861_aud_if; 61struct snd_cea_861_aud_if;
60 62
@@ -754,6 +756,14 @@ const char *omapdss_get_default_display_name(void);
754int omap_dss_start_device(struct omap_dss_device *dssdev); 756int omap_dss_start_device(struct omap_dss_device *dssdev);
755void omap_dss_stop_device(struct omap_dss_device *dssdev); 757void omap_dss_stop_device(struct omap_dss_device *dssdev);
756 758
759int dss_feat_get_num_mgrs(void);
760int dss_feat_get_num_ovls(void);
761enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
762enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
763enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
764
765
766
757int omap_dss_get_num_overlay_managers(void); 767int omap_dss_get_num_overlay_managers(void);
758struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); 768struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
759 769
@@ -775,9 +785,43 @@ typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
775int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); 785int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
776int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); 786int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
777 787
778int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); 788u32 dispc_read_irqstatus(void);
779int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, 789void dispc_clear_irqstatus(u32 mask);
780 unsigned long timeout); 790u32 dispc_read_irqenable(void);
791void dispc_write_irqenable(u32 mask);
792
793int dispc_request_irq(irq_handler_t handler, void *dev_id);
794void dispc_free_irq(void *dev_id);
795
796int dispc_runtime_get(void);
797void dispc_runtime_put(void);
798
799void dispc_mgr_enable(enum omap_channel channel, bool enable);
800bool dispc_mgr_is_enabled(enum omap_channel channel);
801u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
802u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
803u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
804bool dispc_mgr_go_busy(enum omap_channel channel);
805void dispc_mgr_go(enum omap_channel channel);
806void dispc_mgr_set_lcd_config(enum omap_channel channel,
807 const struct dss_lcd_mgr_config *config);
808void dispc_mgr_set_timings(enum omap_channel channel,
809 const struct omap_video_timings *timings);
810void dispc_mgr_setup(enum omap_channel channel,
811 const struct omap_overlay_manager_info *info);
812
813int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
814 const struct omap_overlay_info *oi,
815 const struct omap_video_timings *timings,
816 int *x_predecim, int *y_predecim);
817
818int dispc_ovl_enable(enum omap_plane plane, bool enable);
819bool dispc_ovl_enabled(enum omap_plane plane);
820void dispc_ovl_set_channel_out(enum omap_plane plane,
821 enum omap_channel channel);
822int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
823 bool replication, const struct omap_video_timings *mgr_timings,
824 bool mem_to_mem);
781 825
782#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) 826#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
783#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) 827#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
@@ -836,4 +880,35 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
836void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, 880void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
837 struct rfbi_timings *timings); 881 struct rfbi_timings *timings);
838 882
883int omapdss_compat_init(void);
884void omapdss_compat_uninit(void);
885
886struct dss_mgr_ops {
887 void (*start_update)(struct omap_overlay_manager *mgr);
888 int (*enable)(struct omap_overlay_manager *mgr);
889 void (*disable)(struct omap_overlay_manager *mgr);
890 void (*set_timings)(struct omap_overlay_manager *mgr,
891 const struct omap_video_timings *timings);
892 void (*set_lcd_config)(struct omap_overlay_manager *mgr,
893 const struct dss_lcd_mgr_config *config);
894 int (*register_framedone_handler)(struct omap_overlay_manager *mgr,
895 void (*handler)(void *), void *data);
896 void (*unregister_framedone_handler)(struct omap_overlay_manager *mgr,
897 void (*handler)(void *), void *data);
898};
899
900int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops);
901void dss_uninstall_mgr_ops(void);
902
903void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
904 const struct omap_video_timings *timings);
905void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
906 const struct dss_lcd_mgr_config *config);
907int dss_mgr_enable(struct omap_overlay_manager *mgr);
908void dss_mgr_disable(struct omap_overlay_manager *mgr);
909void dss_mgr_start_update(struct omap_overlay_manager *mgr);
910int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
911 void (*handler)(void *), void *data);
912void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
913 void (*handler)(void *), void *data);
839#endif 914#endif