aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r--drivers/video/omap2/dss/Kconfig2
-rw-r--r--drivers/video/omap2/dss/Makefile4
-rw-r--r--drivers/video/omap2/dss/apply.c330
-rw-r--r--drivers/video/omap2/dss/core.c91
-rw-r--r--drivers/video/omap2/dss/dispc.c1018
-rw-r--r--drivers/video/omap2/dss/dispc.h37
-rw-r--r--drivers/video/omap2/dss/display.c108
-rw-r--r--drivers/video/omap2/dss/dpi.c181
-rw-r--r--drivers/video/omap2/dss/dsi.c675
-rw-r--r--drivers/video/omap2/dss/dss.c257
-rw-r--r--drivers/video/omap2/dss/dss.h79
-rw-r--r--drivers/video/omap2/dss/dss_features.c278
-rw-r--r--drivers/video/omap2/dss/dss_features.h7
-rw-r--r--drivers/video/omap2/dss/hdmi.c247
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c31
-rw-r--r--drivers/video/omap2/dss/manager-sysfs.c512
-rw-r--r--drivers/video/omap2/dss/manager.c473
-rw-r--r--drivers/video/omap2/dss/output.c148
-rw-r--r--drivers/video/omap2/dss/overlay-sysfs.c456
-rw-r--r--drivers/video/omap2/dss/overlay.c492
-rw-r--r--drivers/video/omap2/dss/rfbi.c222
-rw-r--r--drivers/video/omap2/dss/sdi.c126
-rw-r--r--drivers/video/omap2/dss/venc.c337
-rw-r--r--drivers/video/omap2/dss/venc_panel.c251
24 files changed, 4129 insertions, 2233 deletions
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index b337a8469fd8..80f5390aa136 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -84,7 +84,7 @@ config OMAP2_DSS_SDI
84 84
85config OMAP2_DSS_DSI 85config OMAP2_DSS_DSI
86 bool "DSI support" 86 bool "DSI support"
87 depends on ARCH_OMAP3 || ARCH_OMAP4 87 depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
88 default n 88 default n
89 help 89 help
90 MIPI DSI (Display Serial Interface) support. 90 MIPI DSI (Display Serial Interface) support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 5c450b0f94d0..4549869bfe1a 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,9 +1,9 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
3 manager.o overlay.o apply.o 3 manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
7omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 7omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ 9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 0fefc68372b9..19d66f471b4b 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -111,9 +111,6 @@ static struct {
111 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; 111 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
112 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; 112 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
113 113
114 bool fifo_merge_dirty;
115 bool fifo_merge;
116
117 bool irq_enabled; 114 bool irq_enabled;
118} dss_data; 115} dss_data;
119 116
@@ -424,17 +421,25 @@ static void wait_pending_extra_info_updates(void)
424int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 421int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
425{ 422{
426 unsigned long timeout = msecs_to_jiffies(500); 423 unsigned long timeout = msecs_to_jiffies(500);
427 struct mgr_priv_data *mp; 424 struct mgr_priv_data *mp = get_mgr_priv(mgr);
428 u32 irq; 425 u32 irq;
426 unsigned long flags;
429 int r; 427 int r;
430 int i; 428 int i;
431 struct omap_dss_device *dssdev = mgr->device;
432 429
433 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 430 spin_lock_irqsave(&data_lock, flags);
431
432 if (mgr_manual_update(mgr)) {
433 spin_unlock_irqrestore(&data_lock, flags);
434 return 0; 434 return 0;
435 }
435 436
436 if (mgr_manual_update(mgr)) 437 if (!mp->enabled) {
438 spin_unlock_irqrestore(&data_lock, flags);
437 return 0; 439 return 0;
440 }
441
442 spin_unlock_irqrestore(&data_lock, flags);
438 443
439 r = dispc_runtime_get(); 444 r = dispc_runtime_get();
440 if (r) 445 if (r)
@@ -442,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
442 447
443 irq = dispc_mgr_get_vsync_irq(mgr->id); 448 irq = dispc_mgr_get_vsync_irq(mgr->id);
444 449
445 mp = get_mgr_priv(mgr);
446 i = 0; 450 i = 0;
447 while (1) { 451 while (1) {
448 unsigned long flags;
449 bool shadow_dirty, dirty; 452 bool shadow_dirty, dirty;
450 453
451 spin_lock_irqsave(&data_lock, flags); 454 spin_lock_irqsave(&data_lock, flags);
@@ -489,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
489{ 492{
490 unsigned long timeout = msecs_to_jiffies(500); 493 unsigned long timeout = msecs_to_jiffies(500);
491 struct ovl_priv_data *op; 494 struct ovl_priv_data *op;
492 struct omap_dss_device *dssdev; 495 struct mgr_priv_data *mp;
493 u32 irq; 496 u32 irq;
497 unsigned long flags;
494 int r; 498 int r;
495 int i; 499 int i;
496 500
497 if (!ovl->manager) 501 if (!ovl->manager)
498 return 0; 502 return 0;
499 503
500 dssdev = ovl->manager->device; 504 mp = get_mgr_priv(ovl->manager);
505
506 spin_lock_irqsave(&data_lock, flags);
501 507
502 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 508 if (ovl_manual_update(ovl)) {
509 spin_unlock_irqrestore(&data_lock, flags);
503 return 0; 510 return 0;
511 }
504 512
505 if (ovl_manual_update(ovl)) 513 if (!mp->enabled) {
514 spin_unlock_irqrestore(&data_lock, flags);
506 return 0; 515 return 0;
516 }
517
518 spin_unlock_irqrestore(&data_lock, flags);
507 519
508 r = dispc_runtime_get(); 520 r = dispc_runtime_get();
509 if (r) 521 if (r)
@@ -514,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
514 op = get_ovl_priv(ovl); 526 op = get_ovl_priv(ovl);
515 i = 0; 527 i = 0;
516 while (1) { 528 while (1) {
517 unsigned long flags;
518 bool shadow_dirty, dirty; 529 bool shadow_dirty, dirty;
519 530
520 spin_lock_irqsave(&data_lock, flags); 531 spin_lock_irqsave(&data_lock, flags);
@@ -573,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
573 584
574 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); 585 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
575 586
576 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); 587 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
577 if (r) { 588 if (r) {
578 /* 589 /*
579 * We can't do much here, as this function can be called from 590 * We can't do much here, as this function can be called from
@@ -677,40 +688,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
677 mp->shadow_extra_info_dirty = true; 688 mp->shadow_extra_info_dirty = true;
678} 689}
679 690
680static void dss_write_regs_common(void)
681{
682 const int num_mgrs = omap_dss_get_num_overlay_managers();
683 int i;
684
685 if (!dss_data.fifo_merge_dirty)
686 return;
687
688 for (i = 0; i < num_mgrs; ++i) {
689 struct omap_overlay_manager *mgr;
690 struct mgr_priv_data *mp;
691
692 mgr = omap_dss_get_overlay_manager(i);
693 mp = get_mgr_priv(mgr);
694
695 if (mp->enabled) {
696 if (dss_data.fifo_merge_dirty) {
697 dispc_enable_fifomerge(dss_data.fifo_merge);
698 dss_data.fifo_merge_dirty = false;
699 }
700
701 if (mp->updating)
702 mp->shadow_info_dirty = true;
703 }
704 }
705}
706
707static void dss_write_regs(void) 691static void dss_write_regs(void)
708{ 692{
709 const int num_mgrs = omap_dss_get_num_overlay_managers(); 693 const int num_mgrs = omap_dss_get_num_overlay_managers();
710 int i; 694 int i;
711 695
712 dss_write_regs_common();
713
714 for (i = 0; i < num_mgrs; ++i) { 696 for (i = 0; i < num_mgrs; ++i) {
715 struct omap_overlay_manager *mgr; 697 struct omap_overlay_manager *mgr;
716 struct mgr_priv_data *mp; 698 struct mgr_priv_data *mp;
@@ -799,8 +781,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
799 dss_mgr_write_regs(mgr); 781 dss_mgr_write_regs(mgr);
800 dss_mgr_write_regs_extra(mgr); 782 dss_mgr_write_regs_extra(mgr);
801 783
802 dss_write_regs_common();
803
804 mp->updating = true; 784 mp->updating = true;
805 785
806 if (!dss_data.irq_enabled && need_isr()) 786 if (!dss_data.irq_enabled && need_isr())
@@ -984,20 +964,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
984 op->extra_info_dirty = true; 964 op->extra_info_dirty = true;
985} 965}
986 966
987static void dss_apply_fifo_merge(bool use_fifo_merge) 967static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
988{
989 if (dss_data.fifo_merge == use_fifo_merge)
990 return;
991
992 dss_data.fifo_merge = use_fifo_merge;
993 dss_data.fifo_merge_dirty = true;
994}
995
996static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
997 bool use_fifo_merge)
998{ 968{
999 struct ovl_priv_data *op = get_ovl_priv(ovl); 969 struct ovl_priv_data *op = get_ovl_priv(ovl);
1000 u32 fifo_low, fifo_high; 970 u32 fifo_low, fifo_high;
971 bool use_fifo_merge = false;
1001 972
1002 if (!op->enabled && !op->enabling) 973 if (!op->enabled && !op->enabling)
1003 return; 974 return;
@@ -1008,8 +979,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
1008 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 979 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
1009} 980}
1010 981
1011static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, 982static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
1012 bool use_fifo_merge)
1013{ 983{
1014 struct omap_overlay *ovl; 984 struct omap_overlay *ovl;
1015 struct mgr_priv_data *mp; 985 struct mgr_priv_data *mp;
@@ -1020,94 +990,19 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
1020 return; 990 return;
1021 991
1022 list_for_each_entry(ovl, &mgr->overlays, list) 992 list_for_each_entry(ovl, &mgr->overlays, list)
1023 dss_ovl_setup_fifo(ovl, use_fifo_merge); 993 dss_ovl_setup_fifo(ovl);
1024}
1025
1026static void dss_setup_fifos(bool use_fifo_merge)
1027{
1028 const int num_mgrs = omap_dss_get_num_overlay_managers();
1029 struct omap_overlay_manager *mgr;
1030 int i;
1031
1032 for (i = 0; i < num_mgrs; ++i) {
1033 mgr = omap_dss_get_overlay_manager(i);
1034 dss_mgr_setup_fifos(mgr, use_fifo_merge);
1035 }
1036} 994}
1037 995
1038static int get_num_used_managers(void) 996static void dss_setup_fifos(void)
1039{ 997{
1040 const int num_mgrs = omap_dss_get_num_overlay_managers(); 998 const int num_mgrs = omap_dss_get_num_overlay_managers();
1041 struct omap_overlay_manager *mgr; 999 struct omap_overlay_manager *mgr;
1042 struct mgr_priv_data *mp;
1043 int i; 1000 int i;
1044 int enabled_mgrs;
1045
1046 enabled_mgrs = 0;
1047 1001
1048 for (i = 0; i < num_mgrs; ++i) { 1002 for (i = 0; i < num_mgrs; ++i) {
1049 mgr = omap_dss_get_overlay_manager(i); 1003 mgr = omap_dss_get_overlay_manager(i);
1050 mp = get_mgr_priv(mgr); 1004 dss_mgr_setup_fifos(mgr);
1051
1052 if (!mp->enabled)
1053 continue;
1054
1055 enabled_mgrs++;
1056 } 1005 }
1057
1058 return enabled_mgrs;
1059}
1060
1061static int get_num_used_overlays(void)
1062{
1063 const int num_ovls = omap_dss_get_num_overlays();
1064 struct omap_overlay *ovl;
1065 struct ovl_priv_data *op;
1066 struct mgr_priv_data *mp;
1067 int i;
1068 int enabled_ovls;
1069
1070 enabled_ovls = 0;
1071
1072 for (i = 0; i < num_ovls; ++i) {
1073 ovl = omap_dss_get_overlay(i);
1074 op = get_ovl_priv(ovl);
1075
1076 if (!op->enabled && !op->enabling)
1077 continue;
1078
1079 mp = get_mgr_priv(ovl->manager);
1080
1081 if (!mp->enabled)
1082 continue;
1083
1084 enabled_ovls++;
1085 }
1086
1087 return enabled_ovls;
1088}
1089
1090static bool get_use_fifo_merge(void)
1091{
1092 int enabled_mgrs = get_num_used_managers();
1093 int enabled_ovls = get_num_used_overlays();
1094
1095 if (!dss_has_feature(FEAT_FIFO_MERGE))
1096 return false;
1097
1098 /*
1099 * In theory the only requirement for fifomerge is enabled_ovls <= 1.
1100 * However, if we have two managers enabled and set/unset the fifomerge,
1101 * we need to set the GO bits in particular sequence for the managers,
1102 * and wait in between.
1103 *
1104 * This is rather difficult as new apply calls can happen at any time,
1105 * so we simplify the problem by requiring also that enabled_mgrs <= 1.
1106 * In practice this shouldn't matter, because when only one overlay is
1107 * enabled, most likely only one output is enabled.
1108 */
1109
1110 return enabled_mgrs <= 1 && enabled_ovls <= 1;
1111} 1006}
1112 1007
1113int dss_mgr_enable(struct omap_overlay_manager *mgr) 1008int dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -1115,7 +1010,6 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1115 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1010 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1116 unsigned long flags; 1011 unsigned long flags;
1117 int r; 1012 int r;
1118 bool fifo_merge;
1119 1013
1120 mutex_lock(&apply_lock); 1014 mutex_lock(&apply_lock);
1121 1015
@@ -1133,23 +1027,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1133 goto err; 1027 goto err;
1134 } 1028 }
1135 1029
1136 /* step 1: setup fifos/fifomerge before enabling the manager */ 1030 dss_setup_fifos();
1137
1138 fifo_merge = get_use_fifo_merge();
1139 dss_setup_fifos(fifo_merge);
1140 dss_apply_fifo_merge(fifo_merge);
1141 1031
1142 dss_write_regs(); 1032 dss_write_regs();
1143 dss_set_go_bits(); 1033 dss_set_go_bits();
1144 1034
1145 spin_unlock_irqrestore(&data_lock, flags);
1146
1147 /* wait until fifo config is in */
1148 wait_pending_extra_info_updates();
1149
1150 /* step 2: enable the manager */
1151 spin_lock_irqsave(&data_lock, flags);
1152
1153 if (!mgr_manual_update(mgr)) 1035 if (!mgr_manual_update(mgr))
1154 mp->updating = true; 1036 mp->updating = true;
1155 1037
@@ -1174,7 +1056,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1174{ 1056{
1175 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1057 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1176 unsigned long flags; 1058 unsigned long flags;
1177 bool fifo_merge;
1178 1059
1179 mutex_lock(&apply_lock); 1060 mutex_lock(&apply_lock);
1180 1061
@@ -1189,16 +1070,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1189 mp->updating = false; 1070 mp->updating = false;
1190 mp->enabled = false; 1071 mp->enabled = false;
1191 1072
1192 fifo_merge = get_use_fifo_merge();
1193 dss_setup_fifos(fifo_merge);
1194 dss_apply_fifo_merge(fifo_merge);
1195
1196 dss_write_regs();
1197 dss_set_go_bits();
1198
1199 spin_unlock_irqrestore(&data_lock, flags); 1073 spin_unlock_irqrestore(&data_lock, flags);
1200 1074
1201 wait_pending_extra_info_updates();
1202out: 1075out:
1203 mutex_unlock(&apply_lock); 1076 mutex_unlock(&apply_lock);
1204} 1077}
@@ -1237,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1237 spin_unlock_irqrestore(&data_lock, flags); 1110 spin_unlock_irqrestore(&data_lock, flags);
1238} 1111}
1239 1112
1240int dss_mgr_set_device(struct omap_overlay_manager *mgr, 1113int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1241 struct omap_dss_device *dssdev) 1114 struct omap_dss_output *output)
1242{ 1115{
1243 int r; 1116 int r;
1244 1117
1245 mutex_lock(&apply_lock); 1118 mutex_lock(&apply_lock);
1246 1119
1247 if (dssdev->manager) { 1120 if (mgr->output) {
1248 DSSERR("display '%s' already has a manager '%s'\n", 1121 DSSERR("manager %s is already connected to an output\n",
1249 dssdev->name, dssdev->manager->name); 1122 mgr->name);
1250 r = -EINVAL; 1123 r = -EINVAL;
1251 goto err; 1124 goto err;
1252 } 1125 }
1253 1126
1254 if ((mgr->supported_displays & dssdev->type) == 0) { 1127 if ((mgr->supported_outputs & output->id) == 0) {
1255 DSSERR("display '%s' does not support manager '%s'\n", 1128 DSSERR("output does not support manager %s\n",
1256 dssdev->name, mgr->name); 1129 mgr->name);
1257 r = -EINVAL; 1130 r = -EINVAL;
1258 goto err; 1131 goto err;
1259 } 1132 }
1260 1133
1261 dssdev->manager = mgr; 1134 output->manager = mgr;
1262 mgr->device = dssdev; 1135 mgr->output = output;
1263 1136
1264 mutex_unlock(&apply_lock); 1137 mutex_unlock(&apply_lock);
1265 1138
@@ -1269,40 +1142,46 @@ err:
1269 return r; 1142 return r;
1270} 1143}
1271 1144
1272int dss_mgr_unset_device(struct omap_overlay_manager *mgr) 1145int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1273{ 1146{
1274 int r; 1147 int r;
1148 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1149 unsigned long flags;
1275 1150
1276 mutex_lock(&apply_lock); 1151 mutex_lock(&apply_lock);
1277 1152
1278 if (!mgr->device) { 1153 if (!mgr->output) {
1279 DSSERR("failed to unset display, display not set.\n"); 1154 DSSERR("failed to unset output, output not set\n");
1280 r = -EINVAL; 1155 r = -EINVAL;
1281 goto err; 1156 goto err;
1282 } 1157 }
1283 1158
1284 /* 1159 spin_lock_irqsave(&data_lock, flags);
1285 * Don't allow currently enabled displays to have the overlay manager 1160
1286 * pulled out from underneath them 1161 if (mp->enabled) {
1287 */ 1162 DSSERR("output can't be unset when manager is enabled\n");
1288 if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
1289 r = -EINVAL; 1163 r = -EINVAL;
1290 goto err; 1164 goto err1;
1291 } 1165 }
1292 1166
1293 mgr->device->manager = NULL; 1167 spin_unlock_irqrestore(&data_lock, flags);
1294 mgr->device = NULL; 1168
1169 mgr->output->manager = NULL;
1170 mgr->output = NULL;
1295 1171
1296 mutex_unlock(&apply_lock); 1172 mutex_unlock(&apply_lock);
1297 1173
1298 return 0; 1174 return 0;
1175err1:
1176 spin_unlock_irqrestore(&data_lock, flags);
1299err: 1177err:
1300 mutex_unlock(&apply_lock); 1178 mutex_unlock(&apply_lock);
1179
1301 return r; 1180 return r;
1302} 1181}
1303 1182
1304static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, 1183static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1305 struct omap_video_timings *timings) 1184 const struct omap_video_timings *timings)
1306{ 1185{
1307 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1186 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1308 1187
@@ -1311,24 +1190,22 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1311} 1190}
1312 1191
1313void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 1192void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1314 struct omap_video_timings *timings) 1193 const struct omap_video_timings *timings)
1315{ 1194{
1316 unsigned long flags; 1195 unsigned long flags;
1317 1196 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1318 mutex_lock(&apply_lock);
1319 1197
1320 spin_lock_irqsave(&data_lock, flags); 1198 spin_lock_irqsave(&data_lock, flags);
1321 1199
1322 dss_apply_mgr_timings(mgr, timings); 1200 if (mp->updating) {
1323 1201 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1324 dss_write_regs(); 1202 mgr->name);
1325 dss_set_go_bits(); 1203 goto out;
1204 }
1326 1205
1206 dss_apply_mgr_timings(mgr, timings);
1207out:
1327 spin_unlock_irqrestore(&data_lock, flags); 1208 spin_unlock_irqrestore(&data_lock, flags);
1328
1329 wait_pending_extra_info_updates();
1330
1331 mutex_unlock(&apply_lock);
1332} 1209}
1333 1210
1334static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, 1211static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
@@ -1346,7 +1223,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1346 unsigned long flags; 1223 unsigned long flags;
1347 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1224 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1348 1225
1349 mutex_lock(&apply_lock); 1226 spin_lock_irqsave(&data_lock, flags);
1350 1227
1351 if (mp->enabled) { 1228 if (mp->enabled) {
1352 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n", 1229 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
@@ -1354,19 +1231,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1354 goto out; 1231 goto out;
1355 } 1232 }
1356 1233
1357 spin_lock_irqsave(&data_lock, flags);
1358
1359 dss_apply_mgr_lcd_config(mgr, config); 1234 dss_apply_mgr_lcd_config(mgr, config);
1360
1361 dss_write_regs();
1362 dss_set_go_bits();
1363
1364 spin_unlock_irqrestore(&data_lock, flags);
1365
1366 wait_pending_extra_info_updates();
1367
1368out: 1235out:
1369 mutex_unlock(&apply_lock); 1236 spin_unlock_irqrestore(&data_lock, flags);
1370} 1237}
1371 1238
1372int dss_ovl_set_info(struct omap_overlay *ovl, 1239int dss_ovl_set_info(struct omap_overlay *ovl,
@@ -1483,6 +1350,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
1483 goto err; 1350 goto err;
1484 } 1351 }
1485 1352
1353 spin_unlock_irqrestore(&data_lock, flags);
1354
1355 /* wait for pending extra_info updates to ensure the ovl is disabled */
1356 wait_pending_extra_info_updates();
1357
1358 spin_lock_irqsave(&data_lock, flags);
1359
1486 op->channel = -1; 1360 op->channel = -1;
1487 1361
1488 ovl->manager = NULL; 1362 ovl->manager = NULL;
@@ -1517,7 +1391,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1517{ 1391{
1518 struct ovl_priv_data *op = get_ovl_priv(ovl); 1392 struct ovl_priv_data *op = get_ovl_priv(ovl);
1519 unsigned long flags; 1393 unsigned long flags;
1520 bool fifo_merge;
1521 int r; 1394 int r;
1522 1395
1523 mutex_lock(&apply_lock); 1396 mutex_lock(&apply_lock);
@@ -1527,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1527 goto err1; 1400 goto err1;
1528 } 1401 }
1529 1402
1530 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1403 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1531 r = -EINVAL; 1404 r = -EINVAL;
1532 goto err1; 1405 goto err1;
1533 } 1406 }
@@ -1543,22 +1416,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1543 goto err2; 1416 goto err2;
1544 } 1417 }
1545 1418
1546 /* step 1: configure fifos/fifomerge for currently enabled ovls */ 1419 dss_setup_fifos();
1547
1548 fifo_merge = get_use_fifo_merge();
1549 dss_setup_fifos(fifo_merge);
1550 dss_apply_fifo_merge(fifo_merge);
1551
1552 dss_write_regs();
1553 dss_set_go_bits();
1554
1555 spin_unlock_irqrestore(&data_lock, flags);
1556
1557 /* wait for fifo configs to go in */
1558 wait_pending_extra_info_updates();
1559
1560 /* step 2: enable the overlay */
1561 spin_lock_irqsave(&data_lock, flags);
1562 1420
1563 op->enabling = false; 1421 op->enabling = false;
1564 dss_apply_ovl_enable(ovl, true); 1422 dss_apply_ovl_enable(ovl, true);
@@ -1568,9 +1426,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1568 1426
1569 spin_unlock_irqrestore(&data_lock, flags); 1427 spin_unlock_irqrestore(&data_lock, flags);
1570 1428
1571 /* wait for overlay to be enabled */
1572 wait_pending_extra_info_updates();
1573
1574 mutex_unlock(&apply_lock); 1429 mutex_unlock(&apply_lock);
1575 1430
1576 return 0; 1431 return 0;
@@ -1586,7 +1441,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1586{ 1441{
1587 struct ovl_priv_data *op = get_ovl_priv(ovl); 1442 struct ovl_priv_data *op = get_ovl_priv(ovl);
1588 unsigned long flags; 1443 unsigned long flags;
1589 bool fifo_merge;
1590 int r; 1444 int r;
1591 1445
1592 mutex_lock(&apply_lock); 1446 mutex_lock(&apply_lock);
@@ -1596,39 +1450,19 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1596 goto err; 1450 goto err;
1597 } 1451 }
1598 1452
1599 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1453 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1600 r = -EINVAL; 1454 r = -EINVAL;
1601 goto err; 1455 goto err;
1602 } 1456 }
1603 1457
1604 /* step 1: disable the overlay */
1605 spin_lock_irqsave(&data_lock, flags); 1458 spin_lock_irqsave(&data_lock, flags);
1606 1459
1607 dss_apply_ovl_enable(ovl, false); 1460 dss_apply_ovl_enable(ovl, false);
1608
1609 dss_write_regs(); 1461 dss_write_regs();
1610 dss_set_go_bits(); 1462 dss_set_go_bits();
1611 1463
1612 spin_unlock_irqrestore(&data_lock, flags); 1464 spin_unlock_irqrestore(&data_lock, flags);
1613 1465
1614 /* wait for the overlay to be disabled */
1615 wait_pending_extra_info_updates();
1616
1617 /* step 2: configure fifos/fifomerge */
1618 spin_lock_irqsave(&data_lock, flags);
1619
1620 fifo_merge = get_use_fifo_merge();
1621 dss_setup_fifos(fifo_merge);
1622 dss_apply_fifo_merge(fifo_merge);
1623
1624 dss_write_regs();
1625 dss_set_go_bits();
1626
1627 spin_unlock_irqrestore(&data_lock, flags);
1628
1629 /* wait for fifo config to go in */
1630 wait_pending_extra_info_updates();
1631
1632 mutex_unlock(&apply_lock); 1466 mutex_unlock(&apply_lock);
1633 1467
1634 return 0; 1468 return 0;
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 58bd9c27369d..b2af72dc20bd 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -33,6 +33,7 @@
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/suspend.h> 35#include <linux/suspend.h>
36#include <linux/slab.h>
36 37
37#include <video/omapdss.h> 38#include <video/omapdss.h>
38 39
@@ -57,6 +58,11 @@ bool dss_debug;
57module_param_named(debug, dss_debug, bool, 0644); 58module_param_named(debug, dss_debug, bool, 0644);
58#endif 59#endif
59 60
61const char *dss_get_default_display_name(void)
62{
63 return core.default_display_name;
64}
65
60/* REGULATORS */ 66/* REGULATORS */
61 67
62struct regulator *dss_get_vdds_dsi(void) 68struct regulator *dss_get_vdds_dsi(void)
@@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)
347 int r; 353 int r;
348 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 354 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
349 struct omap_dss_device *dssdev = to_dss_device(dev); 355 struct omap_dss_device *dssdev = to_dss_device(dev);
350 bool force;
351 356
352 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 357 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
353 dev_name(dev), dssdev->driver_name, 358 dev_name(dev), dssdev->driver_name,
354 dssdrv->driver.name); 359 dssdrv->driver.name);
355 360
356 dss_init_device(core.pdev, dssdev); 361 r = dss_init_device(core.pdev, dssdev);
357 362 if (r)
358 force = core.default_display_name && 363 return r;
359 strcmp(core.default_display_name, dssdev->name) == 0;
360 dss_recheck_connections(dssdev, force);
361 364
362 r = dssdrv->probe(dssdev); 365 r = dssdrv->probe(dssdev);
363 366
@@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
416EXPORT_SYMBOL(omap_dss_unregister_driver); 419EXPORT_SYMBOL(omap_dss_unregister_driver);
417 420
418/* DEVICE */ 421/* DEVICE */
419static void reset_device(struct device *dev, int check)
420{
421 u8 *dev_p = (u8 *)dev;
422 u8 *dev_end = dev_p + sizeof(*dev);
423 void *saved_pdata;
424
425 saved_pdata = dev->platform_data;
426 if (check) {
427 /*
428 * Check if there is any other setting than platform_data
429 * in struct device; warn that these will be reset by our
430 * init.
431 */
432 dev->platform_data = NULL;
433 while (dev_p < dev_end) {
434 if (*dev_p) {
435 WARN("%s: struct device fields will be "
436 "discarded\n",
437 __func__);
438 break;
439 }
440 dev_p++;
441 }
442 }
443 memset(dev, 0, sizeof(*dev));
444 dev->platform_data = saved_pdata;
445}
446
447 422
448static void omap_dss_dev_release(struct device *dev) 423static void omap_dss_dev_release(struct device *dev)
449{ 424{
450 reset_device(dev, 0); 425 struct omap_dss_device *dssdev = to_dss_device(dev);
426 kfree(dssdev);
451} 427}
452 428
453int omap_dss_register_device(struct omap_dss_device *dssdev, 429static int disp_num_counter;
454 struct device *parent, int disp_num) 430
431struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
455{ 432{
456 WARN_ON(!dssdev->driver_name); 433 struct omap_dss_device *dssdev;
434
435 dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
436 if (!dssdev)
437 return NULL;
457 438
458 reset_device(&dssdev->dev, 1);
459 dssdev->dev.bus = &dss_bus_type; 439 dssdev->dev.bus = &dss_bus_type;
460 dssdev->dev.parent = parent; 440 dssdev->dev.parent = parent;
461 dssdev->dev.release = omap_dss_dev_release; 441 dssdev->dev.release = omap_dss_dev_release;
462 dev_set_name(&dssdev->dev, "display%d", disp_num); 442 dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
463 return device_register(&dssdev->dev); 443
444 device_initialize(&dssdev->dev);
445
446 return dssdev;
447}
448
449int dss_add_device(struct omap_dss_device *dssdev)
450{
451 return device_add(&dssdev->dev);
452}
453
454void dss_put_device(struct omap_dss_device *dssdev)
455{
456 put_device(&dssdev->dev);
464} 457}
465 458
466void omap_dss_unregister_device(struct omap_dss_device *dssdev) 459void dss_unregister_device(struct omap_dss_device *dssdev)
467{ 460{
468 device_unregister(&dssdev->dev); 461 device_unregister(&dssdev->dev);
469} 462}
@@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)
471static int dss_unregister_dss_dev(struct device *dev, void *data) 464static int dss_unregister_dss_dev(struct device *dev, void *data)
472{ 465{
473 struct omap_dss_device *dssdev = to_dss_device(dev); 466 struct omap_dss_device *dssdev = to_dss_device(dev);
474 omap_dss_unregister_device(dssdev); 467 dss_unregister_device(dssdev);
475 return 0; 468 return 0;
476} 469}
477 470
478void omap_dss_unregister_child_devices(struct device *parent) 471void dss_unregister_child_devices(struct device *parent)
479{ 472{
480 device_for_each_child(parent, NULL, dss_unregister_dss_dev); 473 device_for_each_child(parent, NULL, dss_unregister_dss_dev);
481} 474}
482 475
476void dss_copy_device_pdata(struct omap_dss_device *dst,
477 const struct omap_dss_device *src)
478{
479 u8 *d = (u8 *)dst;
480 u8 *s = (u8 *)src;
481 size_t dsize = sizeof(struct device);
482
483 memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
484}
485
483/* BUS */ 486/* BUS */
484static int __init omap_dss_bus_register(void) 487static int __init omap_dss_bus_register(void)
485{ 488{
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ee9e29639dcc..b43477a5fae8 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -38,7 +38,6 @@
38#include <linux/pm_runtime.h> 38#include <linux/pm_runtime.h>
39 39
40#include <plat/cpu.h> 40#include <plat/cpu.h>
41#include <plat/clock.h>
42 41
43#include <video/omapdss.h> 42#include <video/omapdss.h>
44 43
@@ -82,6 +81,30 @@ struct dispc_irq_stats {
82 unsigned irqs[32]; 81 unsigned irqs[32];
83}; 82};
84 83
84struct dispc_features {
85 u8 sw_start;
86 u8 fp_start;
87 u8 bp_start;
88 u16 sw_max;
89 u16 vp_max;
90 u16 hp_max;
91 int (*calc_scaling) (enum omap_plane plane,
92 const struct omap_video_timings *mgr_timings,
93 u16 width, u16 height, u16 out_width, u16 out_height,
94 enum omap_color_mode color_mode, bool *five_taps,
95 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
96 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
97 unsigned long (*calc_core_clk) (enum omap_plane plane,
98 u16 width, u16 height, u16 out_width, u16 out_height,
99 bool mem_to_mem);
100 u8 num_fifos;
101
102 /* swap GFX & WB fifos */
103 bool gfx_fifo_workaround:1;
104};
105
106#define DISPC_MAX_NR_FIFOS 5
107
85static struct { 108static struct {
86 struct platform_device *pdev; 109 struct platform_device *pdev;
87 void __iomem *base; 110 void __iomem *base;
@@ -91,7 +114,9 @@ static struct {
91 int irq; 114 int irq;
92 struct clk *dss_clk; 115 struct clk *dss_clk;
93 116
94 u32 fifo_size[MAX_DSS_OVERLAYS]; 117 u32 fifo_size[DISPC_MAX_NR_FIFOS];
118 /* maps which plane is using a fifo. fifo-id -> plane-id */
119 int fifo_assignment[DISPC_MAX_NR_FIFOS];
95 120
96 spinlock_t irq_lock; 121 spinlock_t irq_lock;
97 u32 irq_error_mask; 122 u32 irq_error_mask;
@@ -102,6 +127,8 @@ static struct {
102 bool ctx_valid; 127 bool ctx_valid;
103 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 128 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
104 129
130 const struct dispc_features *feat;
131
105#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 132#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
106 spinlock_t irq_stats_lock; 133 spinlock_t irq_stats_lock;
107 struct dispc_irq_stats irq_stats; 134 struct dispc_irq_stats irq_stats;
@@ -211,7 +238,14 @@ static const struct {
211 }, 238 },
212}; 239};
213 240
241struct color_conv_coef {
242 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
243 int full_range;
244};
245
214static void _omap_dispc_set_irqs(void); 246static void _omap_dispc_set_irqs(void);
247static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
248static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
215 249
216static inline void dispc_write_reg(const u16 idx, u32 val) 250static inline void dispc_write_reg(const u16 idx, u32 val)
217{ 251{
@@ -509,6 +543,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
509 return mgr_desc[channel].framedone_irq; 543 return mgr_desc[channel].framedone_irq;
510} 544}
511 545
546u32 dispc_wb_get_framedone_irq(void)
547{
548 return DISPC_IRQ_FRAMEDONEWB;
549}
550
512bool dispc_mgr_go_busy(enum omap_channel channel) 551bool dispc_mgr_go_busy(enum omap_channel channel)
513{ 552{
514 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 553 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
@@ -536,6 +575,30 @@ void dispc_mgr_go(enum omap_channel channel)
536 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 575 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
537} 576}
538 577
578bool dispc_wb_go_busy(void)
579{
580 return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
581}
582
583void dispc_wb_go(void)
584{
585 enum omap_plane plane = OMAP_DSS_WB;
586 bool enable, go;
587
588 enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
589
590 if (!enable)
591 return;
592
593 go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
594 if (go) {
595 DSSERR("GO bit not down for WB\n");
596 return;
597 }
598
599 REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
600}
601
539static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) 602static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
540{ 603{
541 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); 604 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
@@ -618,41 +681,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
618 } 681 }
619} 682}
620 683
621static void _dispc_setup_color_conv_coef(void)
622{
623 int i;
624 const struct color_conv_coef {
625 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
626 int full_range;
627 } ctbl_bt601_5 = {
628 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
629 };
630
631 const struct color_conv_coef *ct;
632 684
685static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
686 const struct color_conv_coef *ct)
687{
633#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) 688#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
634 689
635 ct = &ctbl_bt601_5; 690 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
691 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
692 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
693 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
694 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
636 695
637 for (i = 1; i < dss_feat_get_num_ovls(); i++) { 696 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
638 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
639 CVAL(ct->rcr, ct->ry));
640 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
641 CVAL(ct->gy, ct->rcb));
642 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
643 CVAL(ct->gcb, ct->gcr));
644 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
645 CVAL(ct->bcr, ct->by));
646 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
647 CVAL(0, ct->bcb));
648
649 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
650 11, 11);
651 }
652 697
653#undef CVAL 698#undef CVAL
654} 699}
655 700
701static void dispc_setup_color_conv_coef(void)
702{
703 int i;
704 int num_ovl = dss_feat_get_num_ovls();
705 int num_wb = dss_feat_get_num_wbs();
706 const struct color_conv_coef ctbl_bt601_5_ovl = {
707 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
708 };
709 const struct color_conv_coef ctbl_bt601_5_wb = {
710 66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
711 };
712
713 for (i = 1; i < num_ovl; i++)
714 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
715
716 for (; i < num_wb; i++)
717 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
718}
656 719
657static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) 720static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
658{ 721{
@@ -674,24 +737,32 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
674 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); 737 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
675} 738}
676 739
677static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) 740static void dispc_ovl_set_pos(enum omap_plane plane,
741 enum omap_overlay_caps caps, int x, int y)
678{ 742{
679 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 743 u32 val;
744
745 if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
746 return;
747
748 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
680 749
681 dispc_write_reg(DISPC_OVL_POSITION(plane), val); 750 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
682} 751}
683 752
684static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) 753static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
754 int height)
685{ 755{
686 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 756 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
687 757
688 if (plane == OMAP_DSS_GFX) 758 if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
689 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 759 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
690 else 760 else
691 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); 761 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
692} 762}
693 763
694static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) 764static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
765 int height)
695{ 766{
696 u32 val; 767 u32 val;
697 768
@@ -699,14 +770,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
699 770
700 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 771 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
701 772
702 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 773 if (plane == OMAP_DSS_WB)
774 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
775 else
776 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
703} 777}
704 778
705static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) 779static void dispc_ovl_set_zorder(enum omap_plane plane,
780 enum omap_overlay_caps caps, u8 zorder)
706{ 781{
707 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 782 if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
708
709 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
710 return; 783 return;
711 784
712 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); 785 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
@@ -723,23 +796,22 @@ static void dispc_ovl_enable_zorder_planes(void)
723 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); 796 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
724} 797}
725 798
726static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) 799static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
800 enum omap_overlay_caps caps, bool enable)
727{ 801{
728 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 802 if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
729
730 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
731 return; 803 return;
732 804
733 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); 805 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
734} 806}
735 807
736static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 808static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
809 enum omap_overlay_caps caps, u8 global_alpha)
737{ 810{
738 static const unsigned shifts[] = { 0, 8, 16, 24, }; 811 static const unsigned shifts[] = { 0, 8, 16, 24, };
739 int shift; 812 int shift;
740 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
741 813
742 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) 814 if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
743 return; 815 return;
744 816
745 shift = shifts[plane]; 817 shift = shifts[plane];
@@ -947,10 +1019,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
947 return channel; 1019 return channel;
948} 1020}
949 1021
1022void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
1023{
1024 enum omap_plane plane = OMAP_DSS_WB;
1025
1026 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
1027}
1028
950static void dispc_ovl_set_burst_size(enum omap_plane plane, 1029static void dispc_ovl_set_burst_size(enum omap_plane plane,
951 enum omap_burst_size burst_size) 1030 enum omap_burst_size burst_size)
952{ 1031{
953 static const unsigned shifts[] = { 6, 14, 14, 14, }; 1032 static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
954 int shift; 1033 int shift;
955 1034
956 shift = shifts[plane]; 1035 shift = shifts[plane];
@@ -1027,11 +1106,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1027 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1106 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1028} 1107}
1029 1108
1030static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) 1109static void dispc_ovl_enable_replication(enum omap_plane plane,
1110 enum omap_overlay_caps caps, bool enable)
1031{ 1111{
1032 static const unsigned shifts[] = { 5, 10, 10, 10 }; 1112 static const unsigned shifts[] = { 5, 10, 10, 10 };
1033 int shift; 1113 int shift;
1034 1114
1115 if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
1116 return;
1117
1035 shift = shifts[plane]; 1118 shift = shifts[plane];
1036 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); 1119 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1037} 1120}
@@ -1045,10 +1128,10 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
1045 dispc_write_reg(DISPC_SIZE_MGR(channel), val); 1128 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1046} 1129}
1047 1130
1048static void dispc_read_plane_fifo_sizes(void) 1131static void dispc_init_fifos(void)
1049{ 1132{
1050 u32 size; 1133 u32 size;
1051 int plane; 1134 int fifo;
1052 u8 start, end; 1135 u8 start, end;
1053 u32 unit; 1136 u32 unit;
1054 1137
@@ -1056,16 +1139,53 @@ static void dispc_read_plane_fifo_sizes(void)
1056 1139
1057 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); 1140 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1058 1141
1059 for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) { 1142 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1060 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); 1143 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
1061 size *= unit; 1144 size *= unit;
1062 dispc.fifo_size[plane] = size; 1145 dispc.fifo_size[fifo] = size;
1146
1147 /*
1148 * By default fifos are mapped directly to overlays, fifo 0 to
1149 * ovl 0, fifo 1 to ovl 1, etc.
1150 */
1151 dispc.fifo_assignment[fifo] = fifo;
1152 }
1153
1154 /*
1155 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
1156 * causes problems with certain use cases, like using the tiler in 2D
1157 * mode. The below hack swaps the fifos of GFX and WB planes, thus
1158 * giving GFX plane a larger fifo. WB but should work fine with a
1159 * smaller fifo.
1160 */
1161 if (dispc.feat->gfx_fifo_workaround) {
1162 u32 v;
1163
1164 v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
1165
1166 v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
1167 v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
1168 v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
1169 v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
1170
1171 dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
1172
1173 dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1174 dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1063 } 1175 }
1064} 1176}
1065 1177
1066static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) 1178static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1067{ 1179{
1068 return dispc.fifo_size[plane]; 1180 int fifo;
1181 u32 size = 0;
1182
1183 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1184 if (dispc.fifo_assignment[fifo] == plane)
1185 size += dispc.fifo_size[fifo];
1186 }
1187
1188 return size;
1069} 1189}
1070 1190
1071void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) 1191void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
@@ -1141,6 +1261,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1141 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { 1261 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1142 *fifo_low = ovl_fifo_size - burst_size * 2; 1262 *fifo_low = ovl_fifo_size - burst_size * 2;
1143 *fifo_high = total_fifo_size - burst_size; 1263 *fifo_high = total_fifo_size - burst_size;
1264 } else if (plane == OMAP_DSS_WB) {
1265 /*
1266 * Most optimal configuration for writeback is to push out data
1267 * to the interconnect the moment writeback pushes enough pixels
1268 * in the FIFO to form a burst
1269 */
1270 *fifo_low = 0;
1271 *fifo_high = burst_size;
1144 } else { 1272 } else {
1145 *fifo_low = ovl_fifo_size - burst_size; 1273 *fifo_low = ovl_fifo_size - burst_size;
1146 *fifo_high = total_fifo_size - buf_unit; 1274 *fifo_high = total_fifo_size - buf_unit;
@@ -1383,6 +1511,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1383{ 1511{
1384 int scale_x = out_width != orig_width; 1512 int scale_x = out_width != orig_width;
1385 int scale_y = out_height != orig_height; 1513 int scale_y = out_height != orig_height;
1514 bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
1386 1515
1387 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) 1516 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1388 return; 1517 return;
@@ -1390,7 +1519,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1390 color_mode != OMAP_DSS_COLOR_UYVY && 1519 color_mode != OMAP_DSS_COLOR_UYVY &&
1391 color_mode != OMAP_DSS_COLOR_NV12)) { 1520 color_mode != OMAP_DSS_COLOR_NV12)) {
1392 /* reset chroma resampling for RGB formats */ 1521 /* reset chroma resampling for RGB formats */
1393 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); 1522 if (plane != OMAP_DSS_WB)
1523 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1394 return; 1524 return;
1395 } 1525 }
1396 1526
@@ -1399,23 +1529,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1399 1529
1400 switch (color_mode) { 1530 switch (color_mode) {
1401 case OMAP_DSS_COLOR_NV12: 1531 case OMAP_DSS_COLOR_NV12:
1402 /* UV is subsampled by 2 vertically*/ 1532 if (chroma_upscale) {
1403 orig_height >>= 1; 1533 /* UV is subsampled by 2 horizontally and vertically */
1404 /* UV is subsampled by 2 horz.*/ 1534 orig_height >>= 1;
1405 orig_width >>= 1; 1535 orig_width >>= 1;
1536 } else {
1537 /* UV is downsampled by 2 horizontally and vertically */
1538 orig_height <<= 1;
1539 orig_width <<= 1;
1540 }
1541
1406 break; 1542 break;
1407 case OMAP_DSS_COLOR_YUV2: 1543 case OMAP_DSS_COLOR_YUV2:
1408 case OMAP_DSS_COLOR_UYVY: 1544 case OMAP_DSS_COLOR_UYVY:
1409 /*For YUV422 with 90/270 rotation, 1545 /* For YUV422 with 90/270 rotation, we don't upsample chroma */
1410 *we don't upsample chroma
1411 */
1412 if (rotation == OMAP_DSS_ROT_0 || 1546 if (rotation == OMAP_DSS_ROT_0 ||
1413 rotation == OMAP_DSS_ROT_180) 1547 rotation == OMAP_DSS_ROT_180) {
1414 /* UV is subsampled by 2 hrz*/ 1548 if (chroma_upscale)
1415 orig_width >>= 1; 1549 /* UV is subsampled by 2 horizontally */
1550 orig_width >>= 1;
1551 else
1552 /* UV is downsampled by 2 horizontally */
1553 orig_width <<= 1;
1554 }
1555
1416 /* must use FIR for YUV422 if rotated */ 1556 /* must use FIR for YUV422 if rotated */
1417 if (rotation != OMAP_DSS_ROT_0) 1557 if (rotation != OMAP_DSS_ROT_0)
1418 scale_x = scale_y = true; 1558 scale_x = scale_y = true;
1559
1419 break; 1560 break;
1420 default: 1561 default:
1421 BUG(); 1562 BUG();
@@ -1431,8 +1572,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1431 out_width, out_height, five_taps, 1572 out_width, out_height, five_taps,
1432 rotation, DISPC_COLOR_COMPONENT_UV); 1573 rotation, DISPC_COLOR_COMPONENT_UV);
1433 1574
1434 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 1575 if (plane != OMAP_DSS_WB)
1435 (scale_x || scale_y) ? 1 : 0, 8, 8); 1576 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1577 (scale_x || scale_y) ? 1 : 0, 8, 8);
1578
1436 /* set H scaling */ 1579 /* set H scaling */
1437 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); 1580 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1438 /* set V scaling */ 1581 /* set V scaling */
@@ -1848,22 +1991,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1848 * This function is used to avoid synclosts in OMAP3, because of some 1991 * This function is used to avoid synclosts in OMAP3, because of some
1849 * undocumented horizontal position and timing related limitations. 1992 * undocumented horizontal position and timing related limitations.
1850 */ 1993 */
1851static int check_horiz_timing_omap3(enum omap_channel channel, 1994static int check_horiz_timing_omap3(enum omap_plane plane,
1852 const struct omap_video_timings *t, u16 pos_x, 1995 const struct omap_video_timings *t, u16 pos_x,
1853 u16 width, u16 height, u16 out_width, u16 out_height) 1996 u16 width, u16 height, u16 out_width, u16 out_height)
1854{ 1997{
1855 int DS = DIV_ROUND_UP(height, out_height); 1998 int DS = DIV_ROUND_UP(height, out_height);
1856 unsigned long nonactive, lclk, pclk; 1999 unsigned long nonactive;
1857 static const u8 limits[3] = { 8, 10, 20 }; 2000 static const u8 limits[3] = { 8, 10, 20 };
1858 u64 val, blank; 2001 u64 val, blank;
2002 unsigned long pclk = dispc_plane_pclk_rate(plane);
2003 unsigned long lclk = dispc_plane_lclk_rate(plane);
1859 int i; 2004 int i;
1860 2005
1861 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 2006 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1862 pclk = dispc_mgr_pclk_rate(channel);
1863 if (dss_mgr_is_lcd(channel))
1864 lclk = dispc_mgr_lclk_rate(channel);
1865 else
1866 lclk = dispc_fclk_rate();
1867 2007
1868 i = 0; 2008 i = 0;
1869 if (out_height < height) 2009 if (out_height < height)
@@ -1900,13 +2040,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1900 return 0; 2040 return 0;
1901} 2041}
1902 2042
1903static unsigned long calc_core_clk_five_taps(enum omap_channel channel, 2043static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
1904 const struct omap_video_timings *mgr_timings, u16 width, 2044 const struct omap_video_timings *mgr_timings, u16 width,
1905 u16 height, u16 out_width, u16 out_height, 2045 u16 height, u16 out_width, u16 out_height,
1906 enum omap_color_mode color_mode) 2046 enum omap_color_mode color_mode)
1907{ 2047{
1908 u32 core_clk = 0; 2048 u32 core_clk = 0;
1909 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 2049 u64 tmp;
2050 unsigned long pclk = dispc_plane_pclk_rate(plane);
1910 2051
1911 if (height <= out_height && width <= out_width) 2052 if (height <= out_height && width <= out_width)
1912 return (unsigned long) pclk; 2053 return (unsigned long) pclk;
@@ -1940,11 +2081,22 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
1940 return core_clk; 2081 return core_clk;
1941} 2082}
1942 2083
1943static unsigned long calc_core_clk(enum omap_channel channel, u16 width, 2084static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
1944 u16 height, u16 out_width, u16 out_height) 2085 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2086{
2087 unsigned long pclk = dispc_plane_pclk_rate(plane);
2088
2089 if (height > out_height && width > out_width)
2090 return pclk * 4;
2091 else
2092 return pclk * 2;
2093}
2094
2095static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2096 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
1945{ 2097{
1946 unsigned int hf, vf; 2098 unsigned int hf, vf;
1947 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2099 unsigned long pclk = dispc_plane_pclk_rate(plane);
1948 2100
1949 /* 2101 /*
1950 * FIXME how to determine the 'A' factor 2102 * FIXME how to determine the 'A' factor
@@ -1959,51 +2111,207 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
1959 hf = 2; 2111 hf = 2;
1960 else 2112 else
1961 hf = 1; 2113 hf = 1;
1962
1963 if (height > out_height) 2114 if (height > out_height)
1964 vf = 2; 2115 vf = 2;
1965 else 2116 else
1966 vf = 1; 2117 vf = 1;
1967 2118
1968 if (cpu_is_omap24xx()) { 2119 return pclk * vf * hf;
1969 if (vf > 1 && hf > 1) 2120}
1970 return pclk * 4; 2121
1971 else 2122static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
1972 return pclk * 2; 2123 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
1973 } else if (cpu_is_omap34xx()) { 2124{
1974 return pclk * vf * hf; 2125 unsigned long pclk;
1975 } else { 2126
1976 if (hf > 1) 2127 /*
1977 return DIV_ROUND_UP(pclk, out_width) * width; 2128 * If the overlay/writeback is in mem to mem mode, there are no
1978 else 2129 * downscaling limitations with respect to pixel clock, return 1 as
1979 return pclk; 2130 * required core clock to represent that we have sufficient enough
2131 * core clock to do maximum downscaling
2132 */
2133 if (mem_to_mem)
2134 return 1;
2135
2136 pclk = dispc_plane_pclk_rate(plane);
2137
2138 if (width > out_width)
2139 return DIV_ROUND_UP(pclk, out_width) * width;
2140 else
2141 return pclk;
2142}
2143
2144static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2145 const struct omap_video_timings *mgr_timings,
2146 u16 width, u16 height, u16 out_width, u16 out_height,
2147 enum omap_color_mode color_mode, bool *five_taps,
2148 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2149 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2150{
2151 int error;
2152 u16 in_width, in_height;
2153 int min_factor = min(*decim_x, *decim_y);
2154 const int maxsinglelinewidth =
2155 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2156
2157 *five_taps = false;
2158
2159 do {
2160 in_height = DIV_ROUND_UP(height, *decim_y);
2161 in_width = DIV_ROUND_UP(width, *decim_x);
2162 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2163 in_height, out_width, out_height, mem_to_mem);
2164 error = (in_width > maxsinglelinewidth || !*core_clk ||
2165 *core_clk > dispc_core_clk_rate());
2166 if (error) {
2167 if (*decim_x == *decim_y) {
2168 *decim_x = min_factor;
2169 ++*decim_y;
2170 } else {
2171 swap(*decim_x, *decim_y);
2172 if (*decim_x < *decim_y)
2173 ++*decim_x;
2174 }
2175 }
2176 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2177
2178 if (in_width > maxsinglelinewidth) {
2179 DSSERR("Cannot scale max input width exceeded");
2180 return -EINVAL;
1980 } 2181 }
2182 return 0;
1981} 2183}
1982 2184
1983static int dispc_ovl_calc_scaling(enum omap_plane plane, 2185static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
1984 enum omap_channel channel,
1985 const struct omap_video_timings *mgr_timings, 2186 const struct omap_video_timings *mgr_timings,
1986 u16 width, u16 height, u16 out_width, u16 out_height, 2187 u16 width, u16 height, u16 out_width, u16 out_height,
1987 enum omap_color_mode color_mode, bool *five_taps, 2188 enum omap_color_mode color_mode, bool *five_taps,
1988 int *x_predecim, int *y_predecim, u16 pos_x) 2189 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2190 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
1989{ 2191{
1990 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 2192 int error;
1991 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 2193 u16 in_width, in_height;
2194 int min_factor = min(*decim_x, *decim_y);
2195 const int maxsinglelinewidth =
2196 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2197
2198 do {
2199 in_height = DIV_ROUND_UP(height, *decim_y);
2200 in_width = DIV_ROUND_UP(width, *decim_x);
2201 *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
2202 in_width, in_height, out_width, out_height, color_mode);
2203
2204 error = check_horiz_timing_omap3(plane, mgr_timings,
2205 pos_x, in_width, in_height, out_width,
2206 out_height);
2207
2208 if (in_width > maxsinglelinewidth)
2209 if (in_height > out_height &&
2210 in_height < out_height * 2)
2211 *five_taps = false;
2212 if (!*five_taps)
2213 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2214 in_height, out_width, out_height,
2215 mem_to_mem);
2216
2217 error = (error || in_width > maxsinglelinewidth * 2 ||
2218 (in_width > maxsinglelinewidth && *five_taps) ||
2219 !*core_clk || *core_clk > dispc_core_clk_rate());
2220 if (error) {
2221 if (*decim_x == *decim_y) {
2222 *decim_x = min_factor;
2223 ++*decim_y;
2224 } else {
2225 swap(*decim_x, *decim_y);
2226 if (*decim_x < *decim_y)
2227 ++*decim_x;
2228 }
2229 }
2230 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2231
2232 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
2233 out_width, out_height)){
2234 DSSERR("horizontal timing too tight\n");
2235 return -EINVAL;
2236 }
2237
2238 if (in_width > (maxsinglelinewidth * 2)) {
2239 DSSERR("Cannot setup scaling");
2240 DSSERR("width exceeds maximum width possible");
2241 return -EINVAL;
2242 }
2243
2244 if (in_width > maxsinglelinewidth && *five_taps) {
2245 DSSERR("cannot setup scaling with five taps");
2246 return -EINVAL;
2247 }
2248 return 0;
2249}
2250
2251static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2252 const struct omap_video_timings *mgr_timings,
2253 u16 width, u16 height, u16 out_width, u16 out_height,
2254 enum omap_color_mode color_mode, bool *five_taps,
2255 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2256 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2257{
2258 u16 in_width, in_width_max;
2259 int decim_x_min = *decim_x;
2260 u16 in_height = DIV_ROUND_UP(height, *decim_y);
1992 const int maxsinglelinewidth = 2261 const int maxsinglelinewidth =
1993 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2262 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2263 unsigned long pclk = dispc_plane_pclk_rate(plane);
2264 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2265
2266 if (mem_to_mem)
2267 in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
2268 else
2269 in_width_max = dispc_core_clk_rate() /
2270 DIV_ROUND_UP(pclk, out_width);
2271
2272 *decim_x = DIV_ROUND_UP(width, in_width_max);
2273
2274 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
2275 if (*decim_x > *x_predecim)
2276 return -EINVAL;
2277
2278 do {
2279 in_width = DIV_ROUND_UP(width, *decim_x);
2280 } while (*decim_x <= *x_predecim &&
2281 in_width > maxsinglelinewidth && ++*decim_x);
2282
2283 if (in_width > maxsinglelinewidth) {
2284 DSSERR("Cannot scale width exceeds max line width");
2285 return -EINVAL;
2286 }
2287
2288 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
2289 out_width, out_height, mem_to_mem);
2290 return 0;
2291}
2292
2293static int dispc_ovl_calc_scaling(enum omap_plane plane,
2294 enum omap_overlay_caps caps,
2295 const struct omap_video_timings *mgr_timings,
2296 u16 width, u16 height, u16 out_width, u16 out_height,
2297 enum omap_color_mode color_mode, bool *five_taps,
2298 int *x_predecim, int *y_predecim, u16 pos_x,
2299 enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
2300{
2301 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1994 const int max_decim_limit = 16; 2302 const int max_decim_limit = 16;
1995 unsigned long core_clk = 0; 2303 unsigned long core_clk = 0;
1996 int decim_x, decim_y, error, min_factor; 2304 int decim_x, decim_y, ret;
1997 u16 in_width, in_height, in_width_max = 0;
1998 2305
1999 if (width == out_width && height == out_height) 2306 if (width == out_width && height == out_height)
2000 return 0; 2307 return 0;
2001 2308
2002 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 2309 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2003 return -EINVAL; 2310 return -EINVAL;
2004 2311
2005 *x_predecim = max_decim_limit; 2312 *x_predecim = max_decim_limit;
2006 *y_predecim = max_decim_limit; 2313 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
2314 dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
2007 2315
2008 if (color_mode == OMAP_DSS_COLOR_CLUT1 || 2316 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
2009 color_mode == OMAP_DSS_COLOR_CLUT2 || 2317 color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2018,118 +2326,18 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2018 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); 2326 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
2019 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); 2327 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
2020 2328
2021 min_factor = min(decim_x, decim_y);
2022
2023 if (decim_x > *x_predecim || out_width > width * 8) 2329 if (decim_x > *x_predecim || out_width > width * 8)
2024 return -EINVAL; 2330 return -EINVAL;
2025 2331
2026 if (decim_y > *y_predecim || out_height > height * 8) 2332 if (decim_y > *y_predecim || out_height > height * 8)
2027 return -EINVAL; 2333 return -EINVAL;
2028 2334
2029 if (cpu_is_omap24xx()) { 2335 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
2030 *five_taps = false; 2336 out_width, out_height, color_mode, five_taps,
2031 2337 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2032 do { 2338 mem_to_mem);
2033 in_height = DIV_ROUND_UP(height, decim_y); 2339 if (ret)
2034 in_width = DIV_ROUND_UP(width, decim_x); 2340 return ret;
2035 core_clk = calc_core_clk(channel, in_width, in_height,
2036 out_width, out_height);
2037 error = (in_width > maxsinglelinewidth || !core_clk ||
2038 core_clk > dispc_core_clk_rate());
2039 if (error) {
2040 if (decim_x == decim_y) {
2041 decim_x = min_factor;
2042 decim_y++;
2043 } else {
2044 swap(decim_x, decim_y);
2045 if (decim_x < decim_y)
2046 decim_x++;
2047 }
2048 }
2049 } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
2050 error);
2051
2052 if (in_width > maxsinglelinewidth) {
2053 DSSERR("Cannot scale max input width exceeded");
2054 return -EINVAL;
2055 }
2056 } else if (cpu_is_omap34xx()) {
2057
2058 do {
2059 in_height = DIV_ROUND_UP(height, decim_y);
2060 in_width = DIV_ROUND_UP(width, decim_x);
2061 core_clk = calc_core_clk_five_taps(channel, mgr_timings,
2062 in_width, in_height, out_width, out_height,
2063 color_mode);
2064
2065 error = check_horiz_timing_omap3(channel, mgr_timings,
2066 pos_x, in_width, in_height, out_width,
2067 out_height);
2068
2069 if (in_width > maxsinglelinewidth)
2070 if (in_height > out_height &&
2071 in_height < out_height * 2)
2072 *five_taps = false;
2073 if (!*five_taps)
2074 core_clk = calc_core_clk(channel, in_width,
2075 in_height, out_width, out_height);
2076 error = (error || in_width > maxsinglelinewidth * 2 ||
2077 (in_width > maxsinglelinewidth && *five_taps) ||
2078 !core_clk || core_clk > dispc_core_clk_rate());
2079 if (error) {
2080 if (decim_x == decim_y) {
2081 decim_x = min_factor;
2082 decim_y++;
2083 } else {
2084 swap(decim_x, decim_y);
2085 if (decim_x < decim_y)
2086 decim_x++;
2087 }
2088 }
2089 } while (decim_x <= *x_predecim && decim_y <= *y_predecim
2090 && error);
2091
2092 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
2093 height, out_width, out_height)){
2094 DSSERR("horizontal timing too tight\n");
2095 return -EINVAL;
2096 }
2097
2098 if (in_width > (maxsinglelinewidth * 2)) {
2099 DSSERR("Cannot setup scaling");
2100 DSSERR("width exceeds maximum width possible");
2101 return -EINVAL;
2102 }
2103
2104 if (in_width > maxsinglelinewidth && *five_taps) {
2105 DSSERR("cannot setup scaling with five taps");
2106 return -EINVAL;
2107 }
2108 } else {
2109 int decim_x_min = decim_x;
2110 in_height = DIV_ROUND_UP(height, decim_y);
2111 in_width_max = dispc_core_clk_rate() /
2112 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
2113 out_width);
2114 decim_x = DIV_ROUND_UP(width, in_width_max);
2115
2116 decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
2117 if (decim_x > *x_predecim)
2118 return -EINVAL;
2119
2120 do {
2121 in_width = DIV_ROUND_UP(width, decim_x);
2122 } while (decim_x <= *x_predecim &&
2123 in_width > maxsinglelinewidth && decim_x++);
2124
2125 if (in_width > maxsinglelinewidth) {
2126 DSSERR("Cannot scale width exceeds max line width");
2127 return -EINVAL;
2128 }
2129
2130 core_clk = calc_core_clk(channel, in_width, in_height,
2131 out_width, out_height);
2132 }
2133 2341
2134 DSSDBG("required core clk rate = %lu Hz\n", core_clk); 2342 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2135 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); 2343 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
@@ -2147,69 +2355,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2147 return 0; 2355 return 0;
2148} 2356}
2149 2357
2150int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 2358static int dispc_ovl_setup_common(enum omap_plane plane,
2151 bool replication, const struct omap_video_timings *mgr_timings) 2359 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2360 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2361 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2362 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2363 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2364 bool replication, const struct omap_video_timings *mgr_timings,
2365 bool mem_to_mem)
2152{ 2366{
2153 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2154 bool five_taps = true; 2367 bool five_taps = true;
2155 bool fieldmode = 0; 2368 bool fieldmode = 0;
2156 int r, cconv = 0; 2369 int r, cconv = 0;
2157 unsigned offset0, offset1; 2370 unsigned offset0, offset1;
2158 s32 row_inc; 2371 s32 row_inc;
2159 s32 pix_inc; 2372 s32 pix_inc;
2160 u16 frame_height = oi->height; 2373 u16 frame_height = height;
2161 unsigned int field_offset = 0; 2374 unsigned int field_offset = 0;
2162 u16 in_height = oi->height; 2375 u16 in_height = height;
2163 u16 in_width = oi->width; 2376 u16 in_width = width;
2164 u16 out_width, out_height;
2165 enum omap_channel channel;
2166 int x_predecim = 1, y_predecim = 1; 2377 int x_predecim = 1, y_predecim = 1;
2167 bool ilace = mgr_timings->interlace; 2378 bool ilace = mgr_timings->interlace;
2168 2379
2169 channel = dispc_ovl_get_channel_out(plane); 2380 if (paddr == 0)
2170
2171 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2172 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
2173 plane, oi->paddr, oi->p_uv_addr,
2174 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2175 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2176 oi->mirror, ilace, channel, replication);
2177
2178 if (oi->paddr == 0)
2179 return -EINVAL; 2381 return -EINVAL;
2180 2382
2181 out_width = oi->out_width == 0 ? oi->width : oi->out_width; 2383 out_width = out_width == 0 ? width : out_width;
2182 out_height = oi->out_height == 0 ? oi->height : oi->out_height; 2384 out_height = out_height == 0 ? height : out_height;
2183 2385
2184 if (ilace && oi->height == out_height) 2386 if (ilace && height == out_height)
2185 fieldmode = 1; 2387 fieldmode = 1;
2186 2388
2187 if (ilace) { 2389 if (ilace) {
2188 if (fieldmode) 2390 if (fieldmode)
2189 in_height /= 2; 2391 in_height /= 2;
2190 oi->pos_y /= 2; 2392 pos_y /= 2;
2191 out_height /= 2; 2393 out_height /= 2;
2192 2394
2193 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 2395 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
2194 "out_height %d\n", 2396 "out_height %d\n", in_height, pos_y,
2195 in_height, oi->pos_y, out_height); 2397 out_height);
2196 } 2398 }
2197 2399
2198 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 2400 if (!dss_feat_color_mode_supported(plane, color_mode))
2199 return -EINVAL; 2401 return -EINVAL;
2200 2402
2201 r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, 2403 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
2202 in_height, out_width, out_height, oi->color_mode, 2404 in_height, out_width, out_height, color_mode,
2203 &five_taps, &x_predecim, &y_predecim, oi->pos_x); 2405 &five_taps, &x_predecim, &y_predecim, pos_x,
2406 rotation_type, mem_to_mem);
2204 if (r) 2407 if (r)
2205 return r; 2408 return r;
2206 2409
2207 in_width = DIV_ROUND_UP(in_width, x_predecim); 2410 in_width = DIV_ROUND_UP(in_width, x_predecim);
2208 in_height = DIV_ROUND_UP(in_height, y_predecim); 2411 in_height = DIV_ROUND_UP(in_height, y_predecim);
2209 2412
2210 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 2413 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2211 oi->color_mode == OMAP_DSS_COLOR_UYVY || 2414 color_mode == OMAP_DSS_COLOR_UYVY ||
2212 oi->color_mode == OMAP_DSS_COLOR_NV12) 2415 color_mode == OMAP_DSS_COLOR_NV12)
2213 cconv = 1; 2416 cconv = 1;
2214 2417
2215 if (ilace && !fieldmode) { 2418 if (ilace && !fieldmode) {
@@ -2235,70 +2438,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
2235 row_inc = 0; 2438 row_inc = 0;
2236 pix_inc = 0; 2439 pix_inc = 0;
2237 2440
2238 if (oi->rotation_type == OMAP_DSS_ROT_TILER) 2441 if (rotation_type == OMAP_DSS_ROT_TILER)
2239 calc_tiler_rotation_offset(oi->screen_width, in_width, 2442 calc_tiler_rotation_offset(screen_width, in_width,
2240 oi->color_mode, fieldmode, field_offset, 2443 color_mode, fieldmode, field_offset,
2241 &offset0, &offset1, &row_inc, &pix_inc, 2444 &offset0, &offset1, &row_inc, &pix_inc,
2242 x_predecim, y_predecim); 2445 x_predecim, y_predecim);
2243 else if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2446 else if (rotation_type == OMAP_DSS_ROT_DMA)
2244 calc_dma_rotation_offset(oi->rotation, oi->mirror, 2447 calc_dma_rotation_offset(rotation, mirror,
2245 oi->screen_width, in_width, frame_height, 2448 screen_width, in_width, frame_height,
2246 oi->color_mode, fieldmode, field_offset, 2449 color_mode, fieldmode, field_offset,
2247 &offset0, &offset1, &row_inc, &pix_inc, 2450 &offset0, &offset1, &row_inc, &pix_inc,
2248 x_predecim, y_predecim); 2451 x_predecim, y_predecim);
2249 else 2452 else
2250 calc_vrfb_rotation_offset(oi->rotation, oi->mirror, 2453 calc_vrfb_rotation_offset(rotation, mirror,
2251 oi->screen_width, in_width, frame_height, 2454 screen_width, in_width, frame_height,
2252 oi->color_mode, fieldmode, field_offset, 2455 color_mode, fieldmode, field_offset,
2253 &offset0, &offset1, &row_inc, &pix_inc, 2456 &offset0, &offset1, &row_inc, &pix_inc,
2254 x_predecim, y_predecim); 2457 x_predecim, y_predecim);
2255 2458
2256 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 2459 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
2257 offset0, offset1, row_inc, pix_inc); 2460 offset0, offset1, row_inc, pix_inc);
2258 2461
2259 dispc_ovl_set_color_mode(plane, oi->color_mode); 2462 dispc_ovl_set_color_mode(plane, color_mode);
2260 2463
2261 dispc_ovl_configure_burst_type(plane, oi->rotation_type); 2464 dispc_ovl_configure_burst_type(plane, rotation_type);
2262 2465
2263 dispc_ovl_set_ba0(plane, oi->paddr + offset0); 2466 dispc_ovl_set_ba0(plane, paddr + offset0);
2264 dispc_ovl_set_ba1(plane, oi->paddr + offset1); 2467 dispc_ovl_set_ba1(plane, paddr + offset1);
2265 2468
2266 if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { 2469 if (OMAP_DSS_COLOR_NV12 == color_mode) {
2267 dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); 2470 dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
2268 dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); 2471 dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
2269 } 2472 }
2270 2473
2271
2272 dispc_ovl_set_row_inc(plane, row_inc); 2474 dispc_ovl_set_row_inc(plane, row_inc);
2273 dispc_ovl_set_pix_inc(plane, pix_inc); 2475 dispc_ovl_set_pix_inc(plane, pix_inc);
2274 2476
2275 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, 2477 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
2276 in_height, out_width, out_height); 2478 in_height, out_width, out_height);
2277 2479
2278 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 2480 dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
2279 2481
2280 dispc_ovl_set_pic_size(plane, in_width, in_height); 2482 dispc_ovl_set_input_size(plane, in_width, in_height);
2281 2483
2282 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 2484 if (caps & OMAP_DSS_OVL_CAP_SCALE) {
2283 dispc_ovl_set_scaling(plane, in_width, in_height, out_width, 2485 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
2284 out_height, ilace, five_taps, fieldmode, 2486 out_height, ilace, five_taps, fieldmode,
2285 oi->color_mode, oi->rotation); 2487 color_mode, rotation);
2286 dispc_ovl_set_vid_size(plane, out_width, out_height); 2488 dispc_ovl_set_output_size(plane, out_width, out_height);
2287 dispc_ovl_set_vid_color_conv(plane, cconv); 2489 dispc_ovl_set_vid_color_conv(plane, cconv);
2288 } 2490 }
2289 2491
2290 dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, 2492 dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
2291 oi->color_mode);
2292 2493
2293 dispc_ovl_set_zorder(plane, oi->zorder); 2494 dispc_ovl_set_zorder(plane, caps, zorder);
2294 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); 2495 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
2295 dispc_ovl_setup_global_alpha(plane, oi->global_alpha); 2496 dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
2296 2497
2297 dispc_ovl_enable_replication(plane, replication); 2498 dispc_ovl_enable_replication(plane, caps, replication);
2298 2499
2299 return 0; 2500 return 0;
2300} 2501}
2301 2502
2503int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2504 bool replication, const struct omap_video_timings *mgr_timings,
2505 bool mem_to_mem)
2506{
2507 int r;
2508 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2509 enum omap_channel channel;
2510
2511 channel = dispc_ovl_get_channel_out(plane);
2512
2513 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2514 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
2515 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
2516 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2517 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2518
2519 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
2520 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2521 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2522 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2523 oi->rotation_type, replication, mgr_timings, mem_to_mem);
2524
2525 return r;
2526}
2527
2528int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2529 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
2530{
2531 int r;
2532 u32 l;
2533 enum omap_plane plane = OMAP_DSS_WB;
2534 const int pos_x = 0, pos_y = 0;
2535 const u8 zorder = 0, global_alpha = 0;
2536 const bool replication = false;
2537 bool truncation;
2538 int in_width = mgr_timings->x_res;
2539 int in_height = mgr_timings->y_res;
2540 enum omap_overlay_caps caps =
2541 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
2542
2543 DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
2544 "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
2545 in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
2546 wi->mirror);
2547
2548 r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
2549 wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
2550 wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
2551 wi->pre_mult_alpha, global_alpha, wi->rotation_type,
2552 replication, mgr_timings, mem_to_mem);
2553
2554 switch (wi->color_mode) {
2555 case OMAP_DSS_COLOR_RGB16:
2556 case OMAP_DSS_COLOR_RGB24P:
2557 case OMAP_DSS_COLOR_ARGB16:
2558 case OMAP_DSS_COLOR_RGBA16:
2559 case OMAP_DSS_COLOR_RGB12U:
2560 case OMAP_DSS_COLOR_ARGB16_1555:
2561 case OMAP_DSS_COLOR_XRGB16_1555:
2562 case OMAP_DSS_COLOR_RGBX16:
2563 truncation = true;
2564 break;
2565 default:
2566 truncation = false;
2567 break;
2568 }
2569
2570 /* setup extra DISPC_WB_ATTRIBUTES */
2571 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
2572 l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */
2573 l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */
2574 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
2575
2576 return r;
2577}
2578
2302int dispc_ovl_enable(enum omap_plane plane, bool enable) 2579int dispc_ovl_enable(enum omap_plane plane, bool enable)
2303{ 2580{
2304 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 2581 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -2451,6 +2728,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
2451 BUG(); 2728 BUG();
2452} 2729}
2453 2730
2731void dispc_wb_enable(bool enable)
2732{
2733 enum omap_plane plane = OMAP_DSS_WB;
2734 struct completion frame_done_completion;
2735 bool is_on;
2736 int r;
2737 u32 irq;
2738
2739 is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2740 irq = DISPC_IRQ_FRAMEDONEWB;
2741
2742 if (!enable && is_on) {
2743 init_completion(&frame_done_completion);
2744
2745 r = omap_dispc_register_isr(dispc_disable_isr,
2746 &frame_done_completion, irq);
2747 if (r)
2748 DSSERR("failed to register FRAMEDONEWB isr\n");
2749 }
2750
2751 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2752
2753 if (!enable && is_on) {
2754 if (!wait_for_completion_timeout(&frame_done_completion,
2755 msecs_to_jiffies(100)))
2756 DSSERR("timeout waiting for FRAMEDONEWB\n");
2757
2758 r = omap_dispc_unregister_isr(dispc_disable_isr,
2759 &frame_done_completion, irq);
2760 if (r)
2761 DSSERR("failed to unregister FRAMEDONEWB isr\n");
2762 }
2763}
2764
2765bool dispc_wb_is_enabled(void)
2766{
2767 enum omap_plane plane = OMAP_DSS_WB;
2768
2769 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2770}
2771
2454void dispc_lcd_enable_signal_polarity(bool act_high) 2772void dispc_lcd_enable_signal_polarity(bool act_high)
2455{ 2773{
2456 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2774 if (!dss_has_feature(FEAT_LCDENABLEPOL))
@@ -2605,24 +2923,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
2605static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2923static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2606 int vsw, int vfp, int vbp) 2924 int vsw, int vfp, int vbp)
2607{ 2925{
2608 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2926 if (hsw < 1 || hsw > dispc.feat->sw_max ||
2609 if (hsw < 1 || hsw > 64 || 2927 hfp < 1 || hfp > dispc.feat->hp_max ||
2610 hfp < 1 || hfp > 256 || 2928 hbp < 1 || hbp > dispc.feat->hp_max ||
2611 hbp < 1 || hbp > 256 || 2929 vsw < 1 || vsw > dispc.feat->sw_max ||
2612 vsw < 1 || vsw > 64 || 2930 vfp < 0 || vfp > dispc.feat->vp_max ||
2613 vfp < 0 || vfp > 255 || 2931 vbp < 0 || vbp > dispc.feat->vp_max)
2614 vbp < 0 || vbp > 255) 2932 return false;
2615 return false;
2616 } else {
2617 if (hsw < 1 || hsw > 256 ||
2618 hfp < 1 || hfp > 4096 ||
2619 hbp < 1 || hbp > 4096 ||
2620 vsw < 1 || vsw > 256 ||
2621 vfp < 0 || vfp > 4095 ||
2622 vbp < 0 || vbp > 4095)
2623 return false;
2624 }
2625
2626 return true; 2933 return true;
2627} 2934}
2628 2935
@@ -2654,19 +2961,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2654 u32 timing_h, timing_v, l; 2961 u32 timing_h, timing_v, l;
2655 bool onoff, rf, ipc; 2962 bool onoff, rf, ipc;
2656 2963
2657 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2964 timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
2658 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | 2965 FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
2659 FLD_VAL(hbp-1, 27, 20); 2966 FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
2660 2967 timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
2661 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | 2968 FLD_VAL(vfp, dispc.feat->fp_start, 8) |
2662 FLD_VAL(vbp, 27, 20); 2969 FLD_VAL(vbp, dispc.feat->bp_start, 20);
2663 } else {
2664 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2665 FLD_VAL(hbp-1, 31, 20);
2666
2667 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2668 FLD_VAL(vbp, 31, 20);
2669 }
2670 2970
2671 dispc_write_reg(DISPC_TIMING_H(channel), timing_h); 2971 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2672 dispc_write_reg(DISPC_TIMING_V(channel), timing_v); 2972 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
@@ -2872,6 +3172,23 @@ unsigned long dispc_core_clk_rate(void)
2872 return fclk / lcd; 3172 return fclk / lcd;
2873} 3173}
2874 3174
3175static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3176{
3177 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3178
3179 return dispc_mgr_pclk_rate(channel);
3180}
3181
3182static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3183{
3184 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3185
3186 if (dss_mgr_is_lcd(channel))
3187 return dispc_mgr_lclk_rate(channel);
3188 else
3189 return dispc_fclk_rate();
3190
3191}
2875static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3192static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
2876{ 3193{
2877 int lcd, pcd; 3194 int lcd, pcd;
@@ -3492,7 +3809,7 @@ static void dispc_error_worker(struct work_struct *work)
3492 ovl->name); 3809 ovl->name);
3493 dispc_ovl_enable(ovl->id, false); 3810 dispc_ovl_enable(ovl->id, false);
3494 dispc_mgr_go(ovl->manager->id); 3811 dispc_mgr_go(ovl->manager->id);
3495 mdelay(50); 3812 msleep(50);
3496 } 3813 }
3497 } 3814 }
3498 3815
@@ -3504,7 +3821,7 @@ static void dispc_error_worker(struct work_struct *work)
3504 bit = mgr_desc[i].sync_lost_irq; 3821 bit = mgr_desc[i].sync_lost_irq;
3505 3822
3506 if (bit & errors) { 3823 if (bit & errors) {
3507 struct omap_dss_device *dssdev = mgr->device; 3824 struct omap_dss_device *dssdev = mgr->get_device(mgr);
3508 bool enable; 3825 bool enable;
3509 3826
3510 DSSERR("SYNC_LOST on channel %s, restarting the output " 3827 DSSERR("SYNC_LOST on channel %s, restarting the output "
@@ -3524,7 +3841,7 @@ static void dispc_error_worker(struct work_struct *work)
3524 } 3841 }
3525 3842
3526 dispc_mgr_go(mgr->id); 3843 dispc_mgr_go(mgr->id);
3527 mdelay(50); 3844 msleep(50);
3528 3845
3529 if (enable) 3846 if (enable)
3530 dssdev->driver->enable(dssdev); 3847 dssdev->driver->enable(dssdev);
@@ -3535,9 +3852,13 @@ static void dispc_error_worker(struct work_struct *work)
3535 DSSERR("OCP_ERR\n"); 3852 DSSERR("OCP_ERR\n");
3536 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3853 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3537 struct omap_overlay_manager *mgr; 3854 struct omap_overlay_manager *mgr;
3855 struct omap_dss_device *dssdev;
3856
3538 mgr = omap_dss_get_overlay_manager(i); 3857 mgr = omap_dss_get_overlay_manager(i);
3539 if (mgr->device && mgr->device->driver) 3858 dssdev = mgr->get_device(mgr);
3540 mgr->device->driver->disable(mgr->device); 3859
3860 if (dssdev && dssdev->driver)
3861 dssdev->driver->disable(dssdev);
3541 } 3862 }
3542 } 3863 }
3543 3864
@@ -3661,17 +3982,98 @@ static void _omap_dispc_initial_config(void)
3661 if (dss_has_feature(FEAT_FUNCGATED)) 3982 if (dss_has_feature(FEAT_FUNCGATED))
3662 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3983 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3663 3984
3664 _dispc_setup_color_conv_coef(); 3985 dispc_setup_color_conv_coef();
3665 3986
3666 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); 3987 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3667 3988
3668 dispc_read_plane_fifo_sizes(); 3989 dispc_init_fifos();
3669 3990
3670 dispc_configure_burst_sizes(); 3991 dispc_configure_burst_sizes();
3671 3992
3672 dispc_ovl_enable_zorder_planes(); 3993 dispc_ovl_enable_zorder_planes();
3673} 3994}
3674 3995
3996static const struct dispc_features omap24xx_dispc_feats __initconst = {
3997 .sw_start = 5,
3998 .fp_start = 15,
3999 .bp_start = 27,
4000 .sw_max = 64,
4001 .vp_max = 255,
4002 .hp_max = 256,
4003 .calc_scaling = dispc_ovl_calc_scaling_24xx,
4004 .calc_core_clk = calc_core_clk_24xx,
4005 .num_fifos = 3,
4006};
4007
4008static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
4009 .sw_start = 5,
4010 .fp_start = 15,
4011 .bp_start = 27,
4012 .sw_max = 64,
4013 .vp_max = 255,
4014 .hp_max = 256,
4015 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4016 .calc_core_clk = calc_core_clk_34xx,
4017 .num_fifos = 3,
4018};
4019
4020static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
4021 .sw_start = 7,
4022 .fp_start = 19,
4023 .bp_start = 31,
4024 .sw_max = 256,
4025 .vp_max = 4095,
4026 .hp_max = 4096,
4027 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4028 .calc_core_clk = calc_core_clk_34xx,
4029 .num_fifos = 3,
4030};
4031
4032static const struct dispc_features omap44xx_dispc_feats __initconst = {
4033 .sw_start = 7,
4034 .fp_start = 19,
4035 .bp_start = 31,
4036 .sw_max = 256,
4037 .vp_max = 4095,
4038 .hp_max = 4096,
4039 .calc_scaling = dispc_ovl_calc_scaling_44xx,
4040 .calc_core_clk = calc_core_clk_44xx,
4041 .num_fifos = 5,
4042 .gfx_fifo_workaround = true,
4043};
4044
4045static int __init dispc_init_features(struct device *dev)
4046{
4047 const struct dispc_features *src;
4048 struct dispc_features *dst;
4049
4050 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
4051 if (!dst) {
4052 dev_err(dev, "Failed to allocate DISPC Features\n");
4053 return -ENOMEM;
4054 }
4055
4056 if (cpu_is_omap24xx()) {
4057 src = &omap24xx_dispc_feats;
4058 } else if (cpu_is_omap34xx()) {
4059 if (omap_rev() < OMAP3430_REV_ES3_0)
4060 src = &omap34xx_rev1_0_dispc_feats;
4061 else
4062 src = &omap34xx_rev3_0_dispc_feats;
4063 } else if (cpu_is_omap44xx()) {
4064 src = &omap44xx_dispc_feats;
4065 } else if (soc_is_omap54xx()) {
4066 src = &omap44xx_dispc_feats;
4067 } else {
4068 return -ENODEV;
4069 }
4070
4071 memcpy(dst, src, sizeof(*dst));
4072 dispc.feat = dst;
4073
4074 return 0;
4075}
4076
3675/* DISPC HW IP initialisation */ 4077/* DISPC HW IP initialisation */
3676static int __init omap_dispchw_probe(struct platform_device *pdev) 4078static int __init omap_dispchw_probe(struct platform_device *pdev)
3677{ 4079{
@@ -3682,6 +4084,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3682 4084
3683 dispc.pdev = pdev; 4085 dispc.pdev = pdev;
3684 4086
4087 r = dispc_init_features(&dispc.pdev->dev);
4088 if (r)
4089 return r;
4090
3685 spin_lock_init(&dispc.irq_lock); 4091 spin_lock_init(&dispc.irq_lock);
3686 4092
3687#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 4093#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 92d8a9be86fc..222363c6e623 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -36,6 +36,7 @@
36#define DISPC_CONTROL2 0x0238 36#define DISPC_CONTROL2 0x0238
37#define DISPC_CONFIG2 0x0620 37#define DISPC_CONFIG2 0x0620
38#define DISPC_DIVISOR 0x0804 38#define DISPC_DIVISOR 0x0804
39#define DISPC_GLOBAL_BUFFER 0x0800
39#define DISPC_CONTROL3 0x0848 40#define DISPC_CONTROL3 0x0848
40#define DISPC_CONFIG3 0x084C 41#define DISPC_CONFIG3 0x084C
41 42
@@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
355 return 0x014C; 356 return 0x014C;
356 case OMAP_DSS_VIDEO3: 357 case OMAP_DSS_VIDEO3:
357 return 0x0300; 358 return 0x0300;
359 case OMAP_DSS_WB:
360 return 0x0500;
358 default: 361 default:
359 BUG(); 362 BUG();
360 return 0; 363 return 0;
@@ -370,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
370 case OMAP_DSS_VIDEO2: 373 case OMAP_DSS_VIDEO2:
371 return 0x0000; 374 return 0x0000;
372 case OMAP_DSS_VIDEO3: 375 case OMAP_DSS_VIDEO3:
376 case OMAP_DSS_WB:
373 return 0x0008; 377 return 0x0008;
374 default: 378 default:
375 BUG(); 379 BUG();
@@ -385,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
385 case OMAP_DSS_VIDEO2: 389 case OMAP_DSS_VIDEO2:
386 return 0x0004; 390 return 0x0004;
387 case OMAP_DSS_VIDEO3: 391 case OMAP_DSS_VIDEO3:
392 case OMAP_DSS_WB:
388 return 0x000C; 393 return 0x000C;
389 default: 394 default:
390 BUG(); 395 BUG();
@@ -404,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
404 return 0x04BC; 409 return 0x04BC;
405 case OMAP_DSS_VIDEO3: 410 case OMAP_DSS_VIDEO3:
406 return 0x0310; 411 return 0x0310;
412 case OMAP_DSS_WB:
413 return 0x0118;
407 default: 414 default:
408 BUG(); 415 BUG();
409 return 0; 416 return 0;
@@ -422,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
422 return 0x04C0; 429 return 0x04C0;
423 case OMAP_DSS_VIDEO3: 430 case OMAP_DSS_VIDEO3:
424 return 0x0314; 431 return 0x0314;
432 case OMAP_DSS_WB:
433 return 0x011C;
425 default: 434 default:
426 BUG(); 435 BUG();
427 return 0; 436 return 0;
@@ -451,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
451 case OMAP_DSS_VIDEO2: 460 case OMAP_DSS_VIDEO2:
452 return 0x000C; 461 return 0x000C;
453 case OMAP_DSS_VIDEO3: 462 case OMAP_DSS_VIDEO3:
463 case OMAP_DSS_WB:
454 return 0x00A8; 464 return 0x00A8;
455 default: 465 default:
456 BUG(); 466 BUG();
@@ -467,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
467 case OMAP_DSS_VIDEO2: 477 case OMAP_DSS_VIDEO2:
468 return 0x0010; 478 return 0x0010;
469 case OMAP_DSS_VIDEO3: 479 case OMAP_DSS_VIDEO3:
480 case OMAP_DSS_WB:
470 return 0x0070; 481 return 0x0070;
471 default: 482 default:
472 BUG(); 483 BUG();
@@ -486,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
486 return 0x04DC; 497 return 0x04DC;
487 case OMAP_DSS_VIDEO3: 498 case OMAP_DSS_VIDEO3:
488 return 0x032C; 499 return 0x032C;
500 case OMAP_DSS_WB:
501 return 0x0310;
489 default: 502 default:
490 BUG(); 503 BUG();
491 return 0; 504 return 0;
@@ -501,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
501 case OMAP_DSS_VIDEO2: 514 case OMAP_DSS_VIDEO2:
502 return 0x0014; 515 return 0x0014;
503 case OMAP_DSS_VIDEO3: 516 case OMAP_DSS_VIDEO3:
517 case OMAP_DSS_WB:
504 return 0x008C; 518 return 0x008C;
505 default: 519 default:
506 BUG(); 520 BUG();
@@ -517,6 +531,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
517 case OMAP_DSS_VIDEO2: 531 case OMAP_DSS_VIDEO2:
518 return 0x0018; 532 return 0x0018;
519 case OMAP_DSS_VIDEO3: 533 case OMAP_DSS_VIDEO3:
534 case OMAP_DSS_WB:
520 return 0x0088; 535 return 0x0088;
521 default: 536 default:
522 BUG(); 537 BUG();
@@ -533,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
533 case OMAP_DSS_VIDEO2: 548 case OMAP_DSS_VIDEO2:
534 return 0x001C; 549 return 0x001C;
535 case OMAP_DSS_VIDEO3: 550 case OMAP_DSS_VIDEO3:
551 case OMAP_DSS_WB:
536 return 0x00A4; 552 return 0x00A4;
537 default: 553 default:
538 BUG(); 554 BUG();
@@ -549,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
549 case OMAP_DSS_VIDEO2: 565 case OMAP_DSS_VIDEO2:
550 return 0x0020; 566 return 0x0020;
551 case OMAP_DSS_VIDEO3: 567 case OMAP_DSS_VIDEO3:
568 case OMAP_DSS_WB:
552 return 0x0098; 569 return 0x0098;
553 default: 570 default:
554 BUG(); 571 BUG();
@@ -598,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
598 case OMAP_DSS_VIDEO2: 615 case OMAP_DSS_VIDEO2:
599 return 0x0024; 616 return 0x0024;
600 case OMAP_DSS_VIDEO3: 617 case OMAP_DSS_VIDEO3:
618 case OMAP_DSS_WB:
601 return 0x0090; 619 return 0x0090;
602 default: 620 default:
603 BUG(); 621 BUG();
@@ -617,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
617 return 0x055C; 635 return 0x055C;
618 case OMAP_DSS_VIDEO3: 636 case OMAP_DSS_VIDEO3:
619 return 0x0424; 637 return 0x0424;
638 case OMAP_DSS_WB:
639 return 0x290;
620 default: 640 default:
621 BUG(); 641 BUG();
622 return 0; 642 return 0;
@@ -633,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
633 case OMAP_DSS_VIDEO2: 653 case OMAP_DSS_VIDEO2:
634 return 0x0028; 654 return 0x0028;
635 case OMAP_DSS_VIDEO3: 655 case OMAP_DSS_VIDEO3:
656 case OMAP_DSS_WB:
636 return 0x0094; 657 return 0x0094;
637 default: 658 default:
638 BUG(); 659 BUG();
@@ -651,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
651 case OMAP_DSS_VIDEO2: 672 case OMAP_DSS_VIDEO2:
652 return 0x002C; 673 return 0x002C;
653 case OMAP_DSS_VIDEO3: 674 case OMAP_DSS_VIDEO3:
675 case OMAP_DSS_WB:
654 return 0x0000; 676 return 0x0000;
655 default: 677 default:
656 BUG(); 678 BUG();
@@ -670,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
670 return 0x0560; 692 return 0x0560;
671 case OMAP_DSS_VIDEO3: 693 case OMAP_DSS_VIDEO3:
672 return 0x0428; 694 return 0x0428;
695 case OMAP_DSS_WB:
696 return 0x0294;
673 default: 697 default:
674 BUG(); 698 BUG();
675 return 0; 699 return 0;
@@ -686,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
686 case OMAP_DSS_VIDEO2: 710 case OMAP_DSS_VIDEO2:
687 return 0x0030; 711 return 0x0030;
688 case OMAP_DSS_VIDEO3: 712 case OMAP_DSS_VIDEO3:
713 case OMAP_DSS_WB:
689 return 0x0004; 714 return 0x0004;
690 default: 715 default:
691 BUG(); 716 BUG();
@@ -705,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
705 return 0x0564; 730 return 0x0564;
706 case OMAP_DSS_VIDEO3: 731 case OMAP_DSS_VIDEO3:
707 return 0x042C; 732 return 0x042C;
733 case OMAP_DSS_WB:
734 return 0x0298;
708 default: 735 default:
709 BUG(); 736 BUG();
710 return 0; 737 return 0;
@@ -722,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
722 case OMAP_DSS_VIDEO2: 749 case OMAP_DSS_VIDEO2:
723 return 0x0034 + i * 0x8; 750 return 0x0034 + i * 0x8;
724 case OMAP_DSS_VIDEO3: 751 case OMAP_DSS_VIDEO3:
752 case OMAP_DSS_WB:
725 return 0x0010 + i * 0x8; 753 return 0x0010 + i * 0x8;
726 default: 754 default:
727 BUG(); 755 BUG();
@@ -742,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
742 return 0x0568 + i * 0x8; 770 return 0x0568 + i * 0x8;
743 case OMAP_DSS_VIDEO3: 771 case OMAP_DSS_VIDEO3:
744 return 0x0430 + i * 0x8; 772 return 0x0430 + i * 0x8;
773 case OMAP_DSS_WB:
774 return 0x02A0 + i * 0x8;
745 default: 775 default:
746 BUG(); 776 BUG();
747 return 0; 777 return 0;
@@ -759,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
759 case OMAP_DSS_VIDEO2: 789 case OMAP_DSS_VIDEO2:
760 return 0x0038 + i * 0x8; 790 return 0x0038 + i * 0x8;
761 case OMAP_DSS_VIDEO3: 791 case OMAP_DSS_VIDEO3:
792 case OMAP_DSS_WB:
762 return 0x0014 + i * 0x8; 793 return 0x0014 + i * 0x8;
763 default: 794 default:
764 BUG(); 795 BUG();
@@ -779,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
779 return 0x056C + i * 0x8; 810 return 0x056C + i * 0x8;
780 case OMAP_DSS_VIDEO3: 811 case OMAP_DSS_VIDEO3:
781 return 0x0434 + i * 0x8; 812 return 0x0434 + i * 0x8;
813 case OMAP_DSS_WB:
814 return 0x02A4 + i * 0x8;
782 default: 815 default:
783 BUG(); 816 BUG();
784 return 0; 817 return 0;
@@ -795,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
795 case OMAP_DSS_VIDEO1: 828 case OMAP_DSS_VIDEO1:
796 case OMAP_DSS_VIDEO2: 829 case OMAP_DSS_VIDEO2:
797 case OMAP_DSS_VIDEO3: 830 case OMAP_DSS_VIDEO3:
831 case OMAP_DSS_WB:
798 return 0x0074 + i * 0x4; 832 return 0x0074 + i * 0x4;
799 default: 833 default:
800 BUG(); 834 BUG();
@@ -814,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
814 case OMAP_DSS_VIDEO2: 848 case OMAP_DSS_VIDEO2:
815 return 0x00B4 + i * 0x4; 849 return 0x00B4 + i * 0x4;
816 case OMAP_DSS_VIDEO3: 850 case OMAP_DSS_VIDEO3:
851 case OMAP_DSS_WB:
817 return 0x0050 + i * 0x4; 852 return 0x0050 + i * 0x4;
818 default: 853 default:
819 BUG(); 854 BUG();
@@ -834,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
834 return 0x05A8 + i * 0x4; 869 return 0x05A8 + i * 0x4;
835 case OMAP_DSS_VIDEO3: 870 case OMAP_DSS_VIDEO3:
836 return 0x0470 + i * 0x4; 871 return 0x0470 + i * 0x4;
872 case OMAP_DSS_WB:
873 return 0x02E0 + i * 0x4;
837 default: 874 default:
838 BUG(); 875 BUG();
839 return 0; 876 return 0;
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 5bd957e85505..ccf8550fafde 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,
142 if (r) 142 if (r)
143 return r; 143 return r;
144 144
145 dssdev->driver->disable(dssdev);
145 dssdev->driver->set_timings(dssdev, &t); 146 dssdev->driver->set_timings(dssdev, &t);
147 r = dssdev->driver->enable(dssdev);
148 if (r)
149 return r;
146 150
147 return size; 151 return size;
148} 152}
@@ -316,26 +320,117 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
316} 320}
317EXPORT_SYMBOL(omapdss_default_get_timings); 321EXPORT_SYMBOL(omapdss_default_get_timings);
318 322
319void dss_init_device(struct platform_device *pdev, 323/*
324 * Connect dssdev to a manager if the manager is free or if force is specified.
325 * Connect all overlays to that manager if they are free or if force is
326 * specified.
327 */
328static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
329{
330 struct omap_dss_output *out;
331 struct omap_overlay_manager *mgr;
332 int i, r;
333
334 out = omapdss_get_output_from_dssdev(dssdev);
335
336 WARN_ON(dssdev->output);
337 WARN_ON(out->device);
338
339 r = omapdss_output_set_device(out, dssdev);
340 if (r) {
341 DSSERR("failed to connect output to new device\n");
342 return r;
343 }
344
345 mgr = omap_dss_get_overlay_manager(dssdev->channel);
346
347 if (mgr->output && !force)
348 return 0;
349
350 if (mgr->output)
351 mgr->unset_output(mgr);
352
353 r = mgr->set_output(mgr, out);
354 if (r) {
355 DSSERR("failed to connect manager to output of new device\n");
356
357 /* remove the output-device connection we just made */
358 omapdss_output_unset_device(out);
359 return r;
360 }
361
362 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
363 struct omap_overlay *ovl = omap_dss_get_overlay(i);
364
365 if (!ovl->manager || force) {
366 if (ovl->manager)
367 ovl->unset_manager(ovl);
368
369 r = ovl->set_manager(ovl, mgr);
370 if (r) {
371 DSSERR("failed to set initial overlay\n");
372 return r;
373 }
374 }
375 }
376
377 return 0;
378}
379
380static void dss_uninit_connections(struct omap_dss_device *dssdev)
381{
382 if (dssdev->output) {
383 struct omap_overlay_manager *mgr = dssdev->output->manager;
384
385 if (mgr)
386 mgr->unset_output(mgr);
387
388 omapdss_output_unset_device(dssdev->output);
389 }
390}
391
392int dss_init_device(struct platform_device *pdev,
320 struct omap_dss_device *dssdev) 393 struct omap_dss_device *dssdev)
321{ 394{
322 struct device_attribute *attr; 395 struct device_attribute *attr;
323 int i; 396 int i, r;
324 int r; 397 const char *def_disp_name = dss_get_default_display_name();
398 bool force;
399
400 force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
401 dss_init_connections(dssdev, force);
325 402
326 /* create device sysfs files */ 403 /* create device sysfs files */
327 i = 0; 404 i = 0;
328 while ((attr = display_sysfs_attrs[i++]) != NULL) { 405 while ((attr = display_sysfs_attrs[i++]) != NULL) {
329 r = device_create_file(&dssdev->dev, attr); 406 r = device_create_file(&dssdev->dev, attr);
330 if (r) 407 if (r) {
408 for (i = i - 2; i >= 0; i--) {
409 attr = display_sysfs_attrs[i];
410 device_remove_file(&dssdev->dev, attr);
411 }
412
413 dss_uninit_connections(dssdev);
414
331 DSSERR("failed to create sysfs file\n"); 415 DSSERR("failed to create sysfs file\n");
416 return r;
417 }
332 } 418 }
333 419
334 /* create display? sysfs links */ 420 /* create display? sysfs links */
335 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, 421 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
336 dev_name(&dssdev->dev)); 422 dev_name(&dssdev->dev));
337 if (r) 423 if (r) {
424 while ((attr = display_sysfs_attrs[i++]) != NULL)
425 device_remove_file(&dssdev->dev, attr);
426
427 dss_uninit_connections(dssdev);
428
338 DSSERR("failed to create sysfs display link\n"); 429 DSSERR("failed to create sysfs display link\n");
430 return r;
431 }
432
433 return 0;
339} 434}
340 435
341void dss_uninit_device(struct platform_device *pdev, 436void dss_uninit_device(struct platform_device *pdev,
@@ -349,8 +444,7 @@ void dss_uninit_device(struct platform_device *pdev,
349 while ((attr = display_sysfs_attrs[i++]) != NULL) 444 while ((attr = display_sysfs_attrs[i++]) != NULL)
350 device_remove_file(&dssdev->dev, attr); 445 device_remove_file(&dssdev->dev, attr);
351 446
352 if (dssdev->manager) 447 dss_uninit_connections(dssdev);
353 dssdev->manager->unset_device(dssdev->manager);
354} 448}
355 449
356static int dss_suspend_device(struct device *dev, void *data) 450static int dss_suspend_device(struct device *dev, void *data)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 3266be23fc0d..56748cf8760e 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -29,17 +29,24 @@
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32#include <linux/string.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
34#include <plat/cpu.h>
35 35
36#include "dss.h" 36#include "dss.h"
37#include "dss_features.h"
37 38
38static struct { 39static struct {
39 struct regulator *vdds_dsi_reg; 40 struct regulator *vdds_dsi_reg;
40 struct platform_device *dsidev; 41 struct platform_device *dsidev;
41 42
43 struct mutex lock;
44
45 struct omap_video_timings timings;
42 struct dss_lcd_mgr_config mgr_config; 46 struct dss_lcd_mgr_config mgr_config;
47 int data_lines;
48
49 struct omap_dss_output output;
43} dpi; 50} dpi;
44 51
45static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 52static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
121 128
122static int dpi_set_mode(struct omap_dss_device *dssdev) 129static int dpi_set_mode(struct omap_dss_device *dssdev)
123{ 130{
124 struct omap_video_timings *t = &dssdev->panel.timings; 131 struct omap_video_timings *t = &dpi.timings;
132 struct omap_overlay_manager *mgr = dssdev->output->manager;
125 int lck_div = 0, pck_div = 0; 133 int lck_div = 0, pck_div = 0;
126 unsigned long fck = 0; 134 unsigned long fck = 0;
127 unsigned long pck; 135 unsigned long pck;
@@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
146 t->pixel_clock = pck; 154 t->pixel_clock = pck;
147 } 155 }
148 156
149 dss_mgr_set_timings(dssdev->manager, t); 157 dss_mgr_set_timings(mgr, t);
150 158
151 return 0; 159 return 0;
152} 160}
153 161
154static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) 162static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
155{ 163{
164 struct omap_overlay_manager *mgr = dssdev->output->manager;
165
156 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 166 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
157 167
158 dpi.mgr_config.stallmode = false; 168 dpi.mgr_config.stallmode = false;
159 dpi.mgr_config.fifohandcheck = false; 169 dpi.mgr_config.fifohandcheck = false;
160 170
161 dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines; 171 dpi.mgr_config.video_port_width = dpi.data_lines;
162 172
163 dpi.mgr_config.lcden_sig_polarity = 0; 173 dpi.mgr_config.lcden_sig_polarity = 0;
164 174
165 dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config); 175 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
166} 176}
167 177
168int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 178int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
169{ 179{
180 struct omap_dss_output *out = dssdev->output;
170 int r; 181 int r;
171 182
172 if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { 183 mutex_lock(&dpi.lock);
184
185 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
173 DSSERR("no VDSS_DSI regulator\n"); 186 DSSERR("no VDSS_DSI regulator\n");
174 return -ENODEV; 187 r = -ENODEV;
188 goto err_no_reg;
175 } 189 }
176 190
177 if (dssdev->manager == NULL) { 191 if (out == NULL || out->manager == NULL) {
178 DSSERR("failed to enable display: no manager\n"); 192 DSSERR("failed to enable display: no output/manager\n");
179 return -ENODEV; 193 r = -ENODEV;
194 goto err_no_out_mgr;
180 } 195 }
181 196
182 r = omap_dss_start_device(dssdev); 197 r = omap_dss_start_device(dssdev);
@@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
185 goto err_start_dev; 200 goto err_start_dev;
186 } 201 }
187 202
188 if (cpu_is_omap34xx()) { 203 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
189 r = regulator_enable(dpi.vdds_dsi_reg); 204 r = regulator_enable(dpi.vdds_dsi_reg);
190 if (r) 205 if (r)
191 goto err_reg_enable; 206 goto err_reg_enable;
@@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
195 if (r) 210 if (r)
196 goto err_get_dispc; 211 goto err_get_dispc;
197 212
213 r = dss_dpi_select_source(dssdev->channel);
214 if (r)
215 goto err_src_sel;
216
198 if (dpi_use_dsi_pll(dssdev)) { 217 if (dpi_use_dsi_pll(dssdev)) {
199 r = dsi_runtime_get(dpi.dsidev); 218 r = dsi_runtime_get(dpi.dsidev);
200 if (r) 219 if (r)
@@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
213 232
214 mdelay(2); 233 mdelay(2);
215 234
216 r = dss_mgr_enable(dssdev->manager); 235 r = dss_mgr_enable(out->manager);
217 if (r) 236 if (r)
218 goto err_mgr_enable; 237 goto err_mgr_enable;
219 238
239 mutex_unlock(&dpi.lock);
240
220 return 0; 241 return 0;
221 242
222err_mgr_enable: 243err_mgr_enable:
@@ -227,20 +248,28 @@ err_dsi_pll_init:
227 if (dpi_use_dsi_pll(dssdev)) 248 if (dpi_use_dsi_pll(dssdev))
228 dsi_runtime_put(dpi.dsidev); 249 dsi_runtime_put(dpi.dsidev);
229err_get_dsi: 250err_get_dsi:
251err_src_sel:
230 dispc_runtime_put(); 252 dispc_runtime_put();
231err_get_dispc: 253err_get_dispc:
232 if (cpu_is_omap34xx()) 254 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
233 regulator_disable(dpi.vdds_dsi_reg); 255 regulator_disable(dpi.vdds_dsi_reg);
234err_reg_enable: 256err_reg_enable:
235 omap_dss_stop_device(dssdev); 257 omap_dss_stop_device(dssdev);
236err_start_dev: 258err_start_dev:
259err_no_out_mgr:
260err_no_reg:
261 mutex_unlock(&dpi.lock);
237 return r; 262 return r;
238} 263}
239EXPORT_SYMBOL(omapdss_dpi_display_enable); 264EXPORT_SYMBOL(omapdss_dpi_display_enable);
240 265
241void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 266void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
242{ 267{
243 dss_mgr_disable(dssdev->manager); 268 struct omap_overlay_manager *mgr = dssdev->output->manager;
269
270 mutex_lock(&dpi.lock);
271
272 dss_mgr_disable(mgr);
244 273
245 if (dpi_use_dsi_pll(dssdev)) { 274 if (dpi_use_dsi_pll(dssdev)) {
246 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 275 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
@@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
250 279
251 dispc_runtime_put(); 280 dispc_runtime_put();
252 281
253 if (cpu_is_omap34xx()) 282 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
254 regulator_disable(dpi.vdds_dsi_reg); 283 regulator_disable(dpi.vdds_dsi_reg);
255 284
256 omap_dss_stop_device(dssdev); 285 omap_dss_stop_device(dssdev);
286
287 mutex_unlock(&dpi.lock);
257} 288}
258EXPORT_SYMBOL(omapdss_dpi_display_disable); 289EXPORT_SYMBOL(omapdss_dpi_display_disable);
259 290
260void dpi_set_timings(struct omap_dss_device *dssdev, 291void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
261 struct omap_video_timings *timings) 292 struct omap_video_timings *timings)
262{ 293{
263 int r;
264
265 DSSDBG("dpi_set_timings\n"); 294 DSSDBG("dpi_set_timings\n");
266 dssdev->panel.timings = *timings;
267 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
268 r = dispc_runtime_get();
269 if (r)
270 return;
271 295
272 dpi_set_mode(dssdev); 296 mutex_lock(&dpi.lock);
273 297
274 dispc_runtime_put(); 298 dpi.timings = *timings;
275 } else { 299
276 dss_mgr_set_timings(dssdev->manager, timings); 300 mutex_unlock(&dpi.lock);
277 }
278} 301}
279EXPORT_SYMBOL(dpi_set_timings); 302EXPORT_SYMBOL(omapdss_dpi_set_timings);
280 303
281int dpi_check_timings(struct omap_dss_device *dssdev, 304int dpi_check_timings(struct omap_dss_device *dssdev,
282 struct omap_video_timings *timings) 305 struct omap_video_timings *timings)
283{ 306{
284 int r; 307 int r;
308 struct omap_overlay_manager *mgr = dssdev->output->manager;
285 int lck_div, pck_div; 309 int lck_div, pck_div;
286 unsigned long fck; 310 unsigned long fck;
287 unsigned long pck; 311 unsigned long pck;
288 struct dispc_clock_info dispc_cinfo; 312 struct dispc_clock_info dispc_cinfo;
289 313
290 if (dss_mgr_check_timings(dssdev->manager, timings)) 314 if (dss_mgr_check_timings(mgr, timings))
291 return -EINVAL; 315 return -EINVAL;
292 316
293 if (timings->pixel_clock == 0) 317 if (timings->pixel_clock == 0)
@@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
325} 349}
326EXPORT_SYMBOL(dpi_check_timings); 350EXPORT_SYMBOL(dpi_check_timings);
327 351
352void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
353{
354 mutex_lock(&dpi.lock);
355
356 dpi.data_lines = data_lines;
357
358 mutex_unlock(&dpi.lock);
359}
360EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
361
328static int __init dpi_init_display(struct omap_dss_device *dssdev) 362static int __init dpi_init_display(struct omap_dss_device *dssdev)
329{ 363{
330 DSSDBG("init_display\n"); 364 DSSDBG("init_display\n");
331 365
332 if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { 366 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
367 dpi.vdds_dsi_reg == NULL) {
333 struct regulator *vdds_dsi; 368 struct regulator *vdds_dsi;
334 369
335 vdds_dsi = dss_get_vdds_dsi(); 370 vdds_dsi = dss_get_vdds_dsi();
@@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
351 return 0; 386 return 0;
352} 387}
353 388
354static void __init dpi_probe_pdata(struct platform_device *pdev) 389static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
355{ 390{
356 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 391 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
357 int i, r; 392 const char *def_disp_name = dss_get_default_display_name();
393 struct omap_dss_device *def_dssdev;
394 int i;
395
396 def_dssdev = NULL;
358 397
359 for (i = 0; i < pdata->num_devices; ++i) { 398 for (i = 0; i < pdata->num_devices; ++i) {
360 struct omap_dss_device *dssdev = pdata->devices[i]; 399 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
362 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) 401 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
363 continue; 402 continue;
364 403
365 r = dpi_init_display(dssdev); 404 if (def_dssdev == NULL)
366 if (r) { 405 def_dssdev = dssdev;
367 DSSERR("device %s init failed: %d\n", dssdev->name, r); 406
368 continue; 407 if (def_disp_name != NULL &&
408 strcmp(dssdev->name, def_disp_name) == 0) {
409 def_dssdev = dssdev;
410 break;
369 } 411 }
412 }
370 413
371 r = omap_dss_register_device(dssdev, &pdev->dev, i); 414 return def_dssdev;
372 if (r) 415}
373 DSSERR("device %s register failed: %d\n", 416
374 dssdev->name, r); 417static void __init dpi_probe_pdata(struct platform_device *dpidev)
418{
419 struct omap_dss_device *plat_dssdev;
420 struct omap_dss_device *dssdev;
421 int r;
422
423 plat_dssdev = dpi_find_dssdev(dpidev);
424
425 if (!plat_dssdev)
426 return;
427
428 dssdev = dss_alloc_and_init_device(&dpidev->dev);
429 if (!dssdev)
430 return;
431
432 dss_copy_device_pdata(dssdev, plat_dssdev);
433
434 r = dpi_init_display(dssdev);
435 if (r) {
436 DSSERR("device %s init failed: %d\n", dssdev->name, r);
437 dss_put_device(dssdev);
438 return;
439 }
440
441 r = dss_add_device(dssdev);
442 if (r) {
443 DSSERR("device %s register failed: %d\n", dssdev->name, r);
444 dss_put_device(dssdev);
445 return;
375 } 446 }
376} 447}
377 448
449static void __init dpi_init_output(struct platform_device *pdev)
450{
451 struct omap_dss_output *out = &dpi.output;
452
453 out->pdev = pdev;
454 out->id = OMAP_DSS_OUTPUT_DPI;
455 out->type = OMAP_DISPLAY_TYPE_DPI;
456
457 dss_register_output(out);
458}
459
460static void __exit dpi_uninit_output(struct platform_device *pdev)
461{
462 struct omap_dss_output *out = &dpi.output;
463
464 dss_unregister_output(out);
465}
466
378static int __init omap_dpi_probe(struct platform_device *pdev) 467static int __init omap_dpi_probe(struct platform_device *pdev)
379{ 468{
469 mutex_init(&dpi.lock);
470
471 dpi_init_output(pdev);
472
380 dpi_probe_pdata(pdev); 473 dpi_probe_pdata(pdev);
381 474
382 return 0; 475 return 0;
@@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
384 477
385static int __exit omap_dpi_remove(struct platform_device *pdev) 478static int __exit omap_dpi_remove(struct platform_device *pdev)
386{ 479{
387 omap_dss_unregister_child_devices(&pdev->dev); 480 dss_unregister_child_devices(&pdev->dev);
481
482 dpi_uninit_output(pdev);
388 483
389 return 0; 484 return 0;
390} 485}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 05ee04667af1..d64ac3842884 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -41,7 +41,6 @@
41 41
42#include <video/omapdss.h> 42#include <video/omapdss.h>
43#include <video/mipi_display.h> 43#include <video/mipi_display.h>
44#include <plat/clock.h>
45 44
46#include "dss.h" 45#include "dss.h"
47#include "dss_features.h" 46#include "dss_features.h"
@@ -333,6 +332,12 @@ struct dsi_data {
333 unsigned scp_clk_refcount; 332 unsigned scp_clk_refcount;
334 333
335 struct dss_lcd_mgr_config mgr_config; 334 struct dss_lcd_mgr_config mgr_config;
335 struct omap_video_timings timings;
336 enum omap_dss_dsi_pixel_format pix_fmt;
337 enum omap_dss_dsi_mode mode;
338 struct omap_dss_dsi_videomode_timings vm_timings;
339
340 struct omap_dss_output output;
336}; 341};
337 342
338struct dsi_packet_sent_handler_data { 343struct dsi_packet_sent_handler_data {
@@ -340,8 +345,6 @@ struct dsi_packet_sent_handler_data {
340 struct completion *completion; 345 struct completion *completion;
341}; 346};
342 347
343static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
344
345#ifdef DEBUG 348#ifdef DEBUG
346static bool dsi_perf; 349static bool dsi_perf;
347module_param(dsi_perf, bool, 0644); 350module_param(dsi_perf, bool, 0644);
@@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
354 357
355static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) 358static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
356{ 359{
357 return dsi_pdev_map[dssdev->phy.dsi.module]; 360 return dssdev->output->pdev;
358} 361}
359 362
360struct platform_device *dsi_get_dsidev_from_id(int module) 363struct platform_device *dsi_get_dsidev_from_id(int module)
361{ 364{
362 return dsi_pdev_map[module]; 365 struct omap_dss_output *out;
366 enum omap_dss_output_id id;
367
368 id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
369
370 out = omap_dss_get_output(id);
371
372 return out->pdev;
363} 373}
364 374
365static inline void dsi_write_reg(struct platform_device *dsidev, 375static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -1450,6 +1460,148 @@ found:
1450 return 0; 1460 return 0;
1451} 1461}
1452 1462
1463static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1464 unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
1465{
1466 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1467 struct dsi_clock_info cur, best;
1468
1469 DSSDBG("dsi_pll_calc_ddrfreq\n");
1470
1471 memset(&best, 0, sizeof(best));
1472 memset(&cur, 0, sizeof(cur));
1473
1474 cur.clkin = clk_get_rate(dsi->sys_clk);
1475
1476 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1477 cur.fint = cur.clkin / cur.regn;
1478
1479 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1480 continue;
1481
1482 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1483 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1484 unsigned long a, b;
1485
1486 a = 2 * cur.regm * (cur.clkin/1000);
1487 b = cur.regn;
1488 cur.clkin4ddr = a / b * 1000;
1489
1490 if (cur.clkin4ddr > 1800 * 1000 * 1000)
1491 break;
1492
1493 if (abs(cur.clkin4ddr - req_clkin4ddr) <
1494 abs(best.clkin4ddr - req_clkin4ddr)) {
1495 best = cur;
1496 DSSDBG("best %ld\n", best.clkin4ddr);
1497 }
1498
1499 if (cur.clkin4ddr == req_clkin4ddr)
1500 goto found;
1501 }
1502 }
1503found:
1504 if (cinfo)
1505 *cinfo = best;
1506
1507 return 0;
1508}
1509
1510static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1511 struct dsi_clock_info *cinfo)
1512{
1513 unsigned long max_dsi_fck;
1514
1515 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1516
1517 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
1518 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1519}
1520
1521static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
1522 unsigned long req_pck, struct dsi_clock_info *cinfo,
1523 struct dispc_clock_info *dispc_cinfo)
1524{
1525 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1526 unsigned regm_dispc, best_regm_dispc;
1527 unsigned long dispc_clk, best_dispc_clk;
1528 int min_fck_per_pck;
1529 unsigned long max_dss_fck;
1530 struct dispc_clock_info best_dispc;
1531 bool match;
1532
1533 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1534
1535 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1536
1537 if (min_fck_per_pck &&
1538 req_pck * min_fck_per_pck > max_dss_fck) {
1539 DSSERR("Requested pixel clock not possible with the current "
1540 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1541 "the constraint off.\n");
1542 min_fck_per_pck = 0;
1543 }
1544
1545retry:
1546 best_regm_dispc = 0;
1547 best_dispc_clk = 0;
1548 memset(&best_dispc, 0, sizeof(best_dispc));
1549 match = false;
1550
1551 for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
1552 struct dispc_clock_info cur_dispc;
1553
1554 dispc_clk = cinfo->clkin4ddr / regm_dispc;
1555
1556 /* this will narrow down the search a bit,
1557 * but still give pixclocks below what was
1558 * requested */
1559 if (dispc_clk < req_pck)
1560 break;
1561
1562 if (dispc_clk > max_dss_fck)
1563 continue;
1564
1565 if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
1566 continue;
1567
1568 match = true;
1569
1570 dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
1571
1572 if (abs(cur_dispc.pck - req_pck) <
1573 abs(best_dispc.pck - req_pck)) {
1574 best_regm_dispc = regm_dispc;
1575 best_dispc_clk = dispc_clk;
1576 best_dispc = cur_dispc;
1577
1578 if (cur_dispc.pck == req_pck)
1579 goto found;
1580 }
1581 }
1582
1583 if (!match) {
1584 if (min_fck_per_pck) {
1585 DSSERR("Could not find suitable clock settings.\n"
1586 "Turning FCK/PCK constraint off and"
1587 "trying again.\n");
1588 min_fck_per_pck = 0;
1589 goto retry;
1590 }
1591
1592 DSSERR("Could not find suitable clock settings.\n");
1593
1594 return -EINVAL;
1595 }
1596found:
1597 cinfo->regm_dispc = best_regm_dispc;
1598 cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
1599
1600 *dispc_cinfo = best_dispc;
1601
1602 return 0;
1603}
1604
1453int dsi_pll_set_clock_div(struct platform_device *dsidev, 1605int dsi_pll_set_clock_div(struct platform_device *dsidev,
1454 struct dsi_clock_info *cinfo) 1606 struct dsi_clock_info *cinfo)
1455{ 1607{
@@ -1526,21 +1678,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1526 1678
1527 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); 1679 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1528 1680
1681 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1682
1529 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { 1683 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1530 f = cinfo->fint < 1000000 ? 0x3 : 1684 f = cinfo->fint < 1000000 ? 0x3 :
1531 cinfo->fint < 1250000 ? 0x4 : 1685 cinfo->fint < 1250000 ? 0x4 :
1532 cinfo->fint < 1500000 ? 0x5 : 1686 cinfo->fint < 1500000 ? 0x5 :
1533 cinfo->fint < 1750000 ? 0x6 : 1687 cinfo->fint < 1750000 ? 0x6 :
1534 0x7; 1688 0x7;
1535 }
1536 1689
1537 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1538
1539 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1540 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ 1690 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1691 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1692 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1693
1694 l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
1695 }
1696
1541 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1697 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1542 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1698 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1543 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1699 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1700 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1701 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1544 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); 1702 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1545 1703
1546 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ 1704 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
@@ -2004,15 +2162,16 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2004 return 1194 * 3; /* 1194x24 bits */ 2162 return 1194 * 3; /* 1194x24 bits */
2005 case 6: 2163 case 6:
2006 return 1365 * 3; /* 1365x24 bits */ 2164 return 1365 * 3; /* 1365x24 bits */
2165 case 7:
2166 return 1920 * 3; /* 1920x24 bits */
2007 default: 2167 default:
2008 BUG(); 2168 BUG();
2009 return 0; 2169 return 0;
2010 } 2170 }
2011} 2171}
2012 2172
2013static int dsi_set_lane_config(struct omap_dss_device *dssdev) 2173static int dsi_set_lane_config(struct platform_device *dsidev)
2014{ 2174{
2015 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2016 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2175 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2017 static const u8 offsets[] = { 0, 4, 8, 12, 16 }; 2176 static const u8 offsets[] = { 0, 4, 8, 12, 16 };
2018 static const enum dsi_lane_function functions[] = { 2177 static const enum dsi_lane_function functions[] = {
@@ -2136,9 +2295,16 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2136 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r); 2295 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
2137 2296
2138 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 2297 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
2139 r = FLD_MOD(r, tlpx_half, 22, 16); 2298 r = FLD_MOD(r, tlpx_half, 20, 16);
2140 r = FLD_MOD(r, tclk_trail, 15, 8); 2299 r = FLD_MOD(r, tclk_trail, 15, 8);
2141 r = FLD_MOD(r, tclk_zero, 7, 0); 2300 r = FLD_MOD(r, tclk_zero, 7, 0);
2301
2302 if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
2303 r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
2304 r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
2305 r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
2306 }
2307
2142 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); 2308 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
2143 2309
2144 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); 2310 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
@@ -2147,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2147} 2313}
2148 2314
2149/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ 2315/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
2150static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, 2316static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
2151 unsigned mask_p, unsigned mask_n) 2317 unsigned mask_p, unsigned mask_n)
2152{ 2318{
2153 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2154 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2319 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2155 int i; 2320 int i;
2156 u32 l; 2321 u32 l;
@@ -2197,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2197 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); 2362 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
2198} 2363}
2199 2364
2200static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) 2365static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
2201{ 2366{
2202 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2203 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2367 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2204 int t, i; 2368 int t, i;
2205 bool in_use[DSI_MAX_NR_LANES]; 2369 bool in_use[DSI_MAX_NR_LANES];
@@ -2247,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2247} 2411}
2248 2412
2249/* return bitmask of enabled lanes, lane0 being the lsb */ 2413/* return bitmask of enabled lanes, lane0 being the lsb */
2250static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) 2414static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
2251{ 2415{
2252 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2253 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2416 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2254 unsigned mask = 0; 2417 unsigned mask = 0;
2255 int i; 2418 int i;
@@ -2262,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
2262 return mask; 2425 return mask;
2263} 2426}
2264 2427
2265static int dsi_cio_init(struct omap_dss_device *dssdev) 2428static int dsi_cio_init(struct platform_device *dsidev)
2266{ 2429{
2267 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2268 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2430 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2269 int r; 2431 int r;
2270 u32 l; 2432 u32 l;
2271 2433
2272 DSSDBGF(); 2434 DSSDBGF();
2273 2435
2274 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2436 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2275 if (r) 2437 if (r)
2276 return r; 2438 return r;
2277 2439
@@ -2288,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2288 goto err_scp_clk_dom; 2450 goto err_scp_clk_dom;
2289 } 2451 }
2290 2452
2291 r = dsi_set_lane_config(dssdev); 2453 r = dsi_set_lane_config(dsidev);
2292 if (r) 2454 if (r)
2293 goto err_scp_clk_dom; 2455 goto err_scp_clk_dom;
2294 2456
@@ -2323,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2323 mask_p |= 1 << i; 2485 mask_p |= 1 << i;
2324 } 2486 }
2325 2487
2326 dsi_cio_enable_lane_override(dssdev, mask_p, 0); 2488 dsi_cio_enable_lane_override(dsidev, mask_p, 0);
2327 } 2489 }
2328 2490
2329 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); 2491 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2340,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2340 dsi_if_enable(dsidev, false); 2502 dsi_if_enable(dsidev, false);
2341 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ 2503 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
2342 2504
2343 r = dsi_cio_wait_tx_clk_esc_reset(dssdev); 2505 r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
2344 if (r) 2506 if (r)
2345 goto err_tx_clk_esc_rst; 2507 goto err_tx_clk_esc_rst;
2346 2508
@@ -2360,10 +2522,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2360 2522
2361 dsi_cio_timings(dsidev); 2523 dsi_cio_timings(dsidev);
2362 2524
2363 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 2525 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
2364 /* DDR_CLK_ALWAYS_ON */ 2526 /* DDR_CLK_ALWAYS_ON */
2365 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 2527 REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
2366 dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); 2528 dsi->vm_timings.ddr_clk_always_on, 13, 13);
2367 } 2529 }
2368 2530
2369 dsi->ulps_enabled = false; 2531 dsi->ulps_enabled = false;
@@ -2381,13 +2543,12 @@ err_cio_pwr:
2381 dsi_cio_disable_lane_override(dsidev); 2543 dsi_cio_disable_lane_override(dsidev);
2382err_scp_clk_dom: 2544err_scp_clk_dom:
2383 dsi_disable_scp_clk(dsidev); 2545 dsi_disable_scp_clk(dsidev);
2384 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2546 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2385 return r; 2547 return r;
2386} 2548}
2387 2549
2388static void dsi_cio_uninit(struct omap_dss_device *dssdev) 2550static void dsi_cio_uninit(struct platform_device *dsidev)
2389{ 2551{
2390 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2391 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2552 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2392 2553
2393 /* DDR_CLK_ALWAYS_ON */ 2554 /* DDR_CLK_ALWAYS_ON */
@@ -2395,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)
2395 2556
2396 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); 2557 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2397 dsi_disable_scp_clk(dsidev); 2558 dsi_disable_scp_clk(dsidev);
2398 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2559 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2399} 2560}
2400 2561
2401static void dsi_config_tx_fifo(struct platform_device *dsidev, 2562static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2685,6 +2846,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2685 bool enable) 2846 bool enable)
2686{ 2847{
2687 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2848 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2849 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2688 2850
2689 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); 2851 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
2690 2852
@@ -2701,7 +2863,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2701 dsi_force_tx_stop_mode_io(dsidev); 2863 dsi_force_tx_stop_mode_io(dsidev);
2702 2864
2703 /* start the DDR clock by sending a NULL packet */ 2865 /* start the DDR clock by sending a NULL packet */
2704 if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) 2866 if (dsi->vm_timings.ddr_clk_always_on && enable)
2705 dsi_vc_send_null(dssdev, channel); 2867 dsi_vc_send_null(dssdev, channel);
2706} 2868}
2707EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); 2869EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
@@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
2987} 3149}
2988EXPORT_SYMBOL(dsi_vc_send_null); 3150EXPORT_SYMBOL(dsi_vc_send_null);
2989 3151
2990static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, 3152static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
2991 int channel, u8 *data, int len, enum dss_dsi_content_type type) 3153 int channel, u8 *data, int len, enum dss_dsi_content_type type)
2992{ 3154{
2993 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2994 int r; 3155 int r;
2995 3156
2996 if (len == 0) { 3157 if (len == 0) {
@@ -3021,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
3021int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, 3182int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3022 u8 *data, int len) 3183 u8 *data, int len)
3023{ 3184{
3024 return dsi_vc_write_nosync_common(dssdev, channel, data, len, 3185 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3186
3187 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3025 DSS_DSI_CONTENT_DCS); 3188 DSS_DSI_CONTENT_DCS);
3026} 3189}
3027EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); 3190EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
@@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
3029int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, 3192int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
3030 u8 *data, int len) 3193 u8 *data, int len)
3031{ 3194{
3032 return dsi_vc_write_nosync_common(dssdev, channel, data, len, 3195 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3196
3197 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3033 DSS_DSI_CONTENT_GENERIC); 3198 DSS_DSI_CONTENT_GENERIC);
3034} 3199}
3035EXPORT_SYMBOL(dsi_vc_generic_write_nosync); 3200EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
@@ -3040,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3040 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3205 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3041 int r; 3206 int r;
3042 3207
3043 r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); 3208 r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
3044 if (r) 3209 if (r)
3045 goto err; 3210 goto err;
3046 3211
@@ -3118,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
3118} 3283}
3119EXPORT_SYMBOL(dsi_vc_generic_write_2); 3284EXPORT_SYMBOL(dsi_vc_generic_write_2);
3120 3285
3121static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, 3286static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
3122 int channel, u8 dcs_cmd) 3287 int channel, u8 dcs_cmd)
3123{ 3288{
3124 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3125 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3289 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3126 int r; 3290 int r;
3127 3291
@@ -3139,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
3139 return 0; 3303 return 0;
3140} 3304}
3141 3305
3142static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, 3306static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
3143 int channel, u8 *reqdata, int reqlen) 3307 int channel, u8 *reqdata, int reqlen)
3144{ 3308{
3145 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3146 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3309 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3147 u16 data; 3310 u16 data;
3148 u8 data_type; 3311 u8 data_type;
@@ -3291,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3291 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3454 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3292 int r; 3455 int r;
3293 3456
3294 r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); 3457 r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
3295 if (r) 3458 if (r)
3296 goto err; 3459 goto err;
3297 3460
@@ -3322,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
3322 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3485 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3323 int r; 3486 int r;
3324 3487
3325 r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); 3488 r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
3326 if (r) 3489 if (r)
3327 return r; 3490 return r;
3328 3491
@@ -3604,15 +3767,15 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3604 (total_ticks * 1000) / (fck / 1000 / 1000)); 3767 (total_ticks * 1000) / (fck / 1000 / 1000));
3605} 3768}
3606 3769
3607static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) 3770static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3608{ 3771{
3609 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3772 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3610 int num_line_buffers; 3773 int num_line_buffers;
3611 3774
3612 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3775 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3613 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3776 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3614 unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 3777 unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
3615 struct omap_video_timings *timings = &dssdev->panel.timings; 3778 struct omap_video_timings *timings = &dsi->timings;
3616 /* 3779 /*
3617 * Don't use line buffers if width is greater than the video 3780 * Don't use line buffers if width is greater than the video
3618 * port's line buffer size 3781 * port's line buffer size
@@ -3630,11 +3793,11 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
3630 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); 3793 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
3631} 3794}
3632 3795
3633static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) 3796static void dsi_config_vp_sync_events(struct platform_device *dsidev)
3634{ 3797{
3635 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3798 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3636 bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; 3799 bool vsync_end = dsi->vm_timings.vp_vsync_end;
3637 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; 3800 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3638 u32 r; 3801 u32 r;
3639 3802
3640 r = dsi_read_reg(dsidev, DSI_CTRL); 3803 r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -3648,13 +3811,13 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
3648 dsi_write_reg(dsidev, DSI_CTRL, r); 3811 dsi_write_reg(dsidev, DSI_CTRL, r);
3649} 3812}
3650 3813
3651static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) 3814static void dsi_config_blanking_modes(struct platform_device *dsidev)
3652{ 3815{
3653 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3816 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3654 int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; 3817 int blanking_mode = dsi->vm_timings.blanking_mode;
3655 int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; 3818 int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
3656 int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; 3819 int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
3657 int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; 3820 int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
3658 u32 r; 3821 u32 r;
3659 3822
3660 /* 3823 /*
@@ -3741,8 +3904,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3741 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; 3904 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3742 int tclk_trail, ths_exit, exiths_clk; 3905 int tclk_trail, ths_exit, exiths_clk;
3743 bool ddr_alwon; 3906 bool ddr_alwon;
3744 struct omap_video_timings *timings = &dssdev->panel.timings; 3907 struct omap_video_timings *timings = &dsi->timings;
3745 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3908 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3746 int ndl = dsi->num_lanes_used - 1; 3909 int ndl = dsi->num_lanes_used - 1;
3747 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; 3910 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
3748 int hsa_interleave_hs = 0, hsa_interleave_lp = 0; 3911 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
@@ -3852,6 +4015,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3852static int dsi_proto_config(struct omap_dss_device *dssdev) 4015static int dsi_proto_config(struct omap_dss_device *dssdev)
3853{ 4016{
3854 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4017 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4018 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3855 u32 r; 4019 u32 r;
3856 int buswidth = 0; 4020 int buswidth = 0;
3857 4021
@@ -3871,7 +4035,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3871 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); 4035 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
3872 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); 4036 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
3873 4037
3874 switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { 4038 switch (dsi_get_pixel_size(dsi->pix_fmt)) {
3875 case 16: 4039 case 16:
3876 buswidth = 0; 4040 buswidth = 0;
3877 break; 4041 break;
@@ -3903,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3903 4067
3904 dsi_write_reg(dsidev, DSI_CTRL, r); 4068 dsi_write_reg(dsidev, DSI_CTRL, r);
3905 4069
3906 dsi_config_vp_num_line_buffers(dssdev); 4070 dsi_config_vp_num_line_buffers(dsidev);
3907 4071
3908 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4072 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3909 dsi_config_vp_sync_events(dssdev); 4073 dsi_config_vp_sync_events(dsidev);
3910 dsi_config_blanking_modes(dssdev); 4074 dsi_config_blanking_modes(dsidev);
3911 dsi_config_cmd_mode_interleaving(dssdev); 4075 dsi_config_cmd_mode_interleaving(dssdev);
3912 } 4076 }
3913 4077
@@ -3919,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3919 return 0; 4083 return 0;
3920} 4084}
3921 4085
3922static void dsi_proto_timings(struct omap_dss_device *dssdev) 4086static void dsi_proto_timings(struct platform_device *dsidev)
3923{ 4087{
3924 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3925 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4088 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3926 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 4089 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
3927 unsigned tclk_pre, tclk_post; 4090 unsigned tclk_pre, tclk_post;
@@ -3941,7 +4104,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3941 ths_exit = FLD_GET(r, 7, 0); 4104 ths_exit = FLD_GET(r, 7, 0);
3942 4105
3943 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 4106 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3944 tlpx = FLD_GET(r, 22, 16) * 2; 4107 tlpx = FLD_GET(r, 20, 16) * 2;
3945 tclk_trail = FLD_GET(r, 15, 8); 4108 tclk_trail = FLD_GET(r, 15, 8);
3946 tclk_zero = FLD_GET(r, 7, 0); 4109 tclk_zero = FLD_GET(r, 7, 0);
3947 4110
@@ -3984,18 +4147,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3984 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", 4147 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
3985 enter_hs_mode_lat, exit_hs_mode_lat); 4148 enter_hs_mode_lat, exit_hs_mode_lat);
3986 4149
3987 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4150 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3988 /* TODO: Implement a video mode check_timings function */ 4151 /* TODO: Implement a video mode check_timings function */
3989 int hsa = dssdev->panel.dsi_vm_data.hsa; 4152 int hsa = dsi->vm_timings.hsa;
3990 int hfp = dssdev->panel.dsi_vm_data.hfp; 4153 int hfp = dsi->vm_timings.hfp;
3991 int hbp = dssdev->panel.dsi_vm_data.hbp; 4154 int hbp = dsi->vm_timings.hbp;
3992 int vsa = dssdev->panel.dsi_vm_data.vsa; 4155 int vsa = dsi->vm_timings.vsa;
3993 int vfp = dssdev->panel.dsi_vm_data.vfp; 4156 int vfp = dsi->vm_timings.vfp;
3994 int vbp = dssdev->panel.dsi_vm_data.vbp; 4157 int vbp = dsi->vm_timings.vbp;
3995 int window_sync = dssdev->panel.dsi_vm_data.window_sync; 4158 int window_sync = dsi->vm_timings.window_sync;
3996 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; 4159 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3997 struct omap_video_timings *timings = &dssdev->panel.timings; 4160 struct omap_video_timings *timings = &dsi->timings;
3998 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4161 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3999 int tl, t_he, width_bytes; 4162 int tl, t_he, width_bytes;
4000 4163
4001 t_he = hsync_end ? 4164 t_he = hsync_end ?
@@ -4100,16 +4263,84 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
4100} 4263}
4101EXPORT_SYMBOL(omapdss_dsi_configure_pins); 4264EXPORT_SYMBOL(omapdss_dsi_configure_pins);
4102 4265
4103int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 4266int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
4267 unsigned long ddr_clk, unsigned long lp_clk)
4104{ 4268{
4105 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4269 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4270 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4271 struct dsi_clock_info cinfo;
4272 struct dispc_clock_info dispc_cinfo;
4273 unsigned lp_clk_div;
4274 unsigned long dsi_fclk;
4106 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4275 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
4276 unsigned long pck;
4277 int r;
4278
4279 DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
4280
4281 mutex_lock(&dsi->lock);
4282
4283 /* Calculate PLL output clock */
4284 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
4285 if (r)
4286 goto err;
4287
4288 /* Calculate PLL's DSI clock */
4289 dsi_pll_calc_dsi_fck(dsidev, &cinfo);
4290
4291 /* Calculate PLL's DISPC clock and pck & lck divs */
4292 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
4293 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4294 r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
4295 if (r)
4296 goto err;
4297
4298 /* Calculate LP clock */
4299 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
4300 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
4301
4302 dssdev->clocks.dsi.regn = cinfo.regn;
4303 dssdev->clocks.dsi.regm = cinfo.regm;
4304 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4305 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4306
4307 dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
4308
4309 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
4310 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
4311
4312 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
4313
4314 dssdev->clocks.dispc.channel.lcd_clk_src =
4315 dsi->module_id == 0 ?
4316 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4317 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
4318
4319 dssdev->clocks.dsi.dsi_fclk_src =
4320 dsi->module_id == 0 ?
4321 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4322 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
4323
4324 mutex_unlock(&dsi->lock);
4325 return 0;
4326err:
4327 mutex_unlock(&dsi->lock);
4328 return r;
4329}
4330EXPORT_SYMBOL(omapdss_dsi_set_clocks);
4331
4332int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4333{
4334 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4335 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4336 struct omap_overlay_manager *mgr = dssdev->output->manager;
4337 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4107 u8 data_type; 4338 u8 data_type;
4108 u16 word_count; 4339 u16 word_count;
4109 int r; 4340 int r;
4110 4341
4111 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4342 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4112 switch (dssdev->panel.dsi_pix_fmt) { 4343 switch (dsi->pix_fmt) {
4113 case OMAP_DSS_DSI_FMT_RGB888: 4344 case OMAP_DSS_DSI_FMT_RGB888:
4114 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 4345 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
4115 break; 4346 break;
@@ -4133,7 +4364,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4133 /* MODE, 1 = video mode */ 4364 /* MODE, 1 = video mode */
4134 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 4365 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
4135 4366
4136 word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); 4367 word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
4137 4368
4138 dsi_vc_write_long_header(dsidev, channel, data_type, 4369 dsi_vc_write_long_header(dsidev, channel, data_type,
4139 word_count, 0); 4370 word_count, 0);
@@ -4142,9 +4373,9 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4142 dsi_if_enable(dsidev, true); 4373 dsi_if_enable(dsidev, true);
4143 } 4374 }
4144 4375
4145 r = dss_mgr_enable(dssdev->manager); 4376 r = dss_mgr_enable(mgr);
4146 if (r) { 4377 if (r) {
4147 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4378 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4148 dsi_if_enable(dsidev, false); 4379 dsi_if_enable(dsidev, false);
4149 dsi_vc_enable(dsidev, channel, false); 4380 dsi_vc_enable(dsidev, channel, false);
4150 } 4381 }
@@ -4159,8 +4390,10 @@ EXPORT_SYMBOL(dsi_enable_video_output);
4159void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) 4390void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4160{ 4391{
4161 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4392 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4393 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4394 struct omap_overlay_manager *mgr = dssdev->output->manager;
4162 4395
4163 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4396 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4164 dsi_if_enable(dsidev, false); 4397 dsi_if_enable(dsidev, false);
4165 dsi_vc_enable(dsidev, channel, false); 4398 dsi_vc_enable(dsidev, channel, false);
4166 4399
@@ -4171,15 +4404,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4171 dsi_if_enable(dsidev, true); 4404 dsi_if_enable(dsidev, true);
4172 } 4405 }
4173 4406
4174 dss_mgr_disable(dssdev->manager); 4407 dss_mgr_disable(mgr);
4175} 4408}
4176EXPORT_SYMBOL(dsi_disable_video_output); 4409EXPORT_SYMBOL(dsi_disable_video_output);
4177 4410
4178static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 4411static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4179 u16 w, u16 h)
4180{ 4412{
4181 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4413 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4182 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4414 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4415 struct omap_overlay_manager *mgr = dssdev->output->manager;
4183 unsigned bytespp; 4416 unsigned bytespp;
4184 unsigned bytespl; 4417 unsigned bytespl;
4185 unsigned bytespf; 4418 unsigned bytespf;
@@ -4190,12 +4423,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4190 int r; 4423 int r;
4191 const unsigned channel = dsi->update_channel; 4424 const unsigned channel = dsi->update_channel;
4192 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 4425 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
4426 u16 w = dsi->timings.x_res;
4427 u16 h = dsi->timings.y_res;
4193 4428
4194 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); 4429 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
4195 4430
4196 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); 4431 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
4197 4432
4198 bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4433 bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
4199 bytespl = w * bytespp; 4434 bytespl = w * bytespp;
4200 bytespf = bytespl * h; 4435 bytespf = bytespl * h;
4201 4436
@@ -4239,7 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4239 msecs_to_jiffies(250)); 4474 msecs_to_jiffies(250));
4240 BUG_ON(r == 0); 4475 BUG_ON(r == 0);
4241 4476
4242 dss_mgr_start_update(dssdev->manager); 4477 dss_mgr_set_timings(mgr, &dsi->timings);
4478
4479 dss_mgr_start_update(mgr);
4243 4480
4244 if (dsi->te_enabled) { 4481 if (dsi->te_enabled) {
4245 /* disable LP_RX_TO, so that we can receive TE. Time to wait 4482 /* disable LP_RX_TO, so that we can receive TE. Time to wait
@@ -4297,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4297 4534
4298static void dsi_framedone_irq_callback(void *data, u32 mask) 4535static void dsi_framedone_irq_callback(void *data, u32 mask)
4299{ 4536{
4300 struct omap_dss_device *dssdev = (struct omap_dss_device *) data; 4537 struct platform_device *dsidev = (struct platform_device *) data;
4301 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4302 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4538 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4303 4539
4304 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 4540 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
@@ -4325,13 +4561,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
4325 dsi->framedone_callback = callback; 4561 dsi->framedone_callback = callback;
4326 dsi->framedone_data = data; 4562 dsi->framedone_data = data;
4327 4563
4328 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4564 dw = dsi->timings.x_res;
4565 dh = dsi->timings.y_res;
4329 4566
4330#ifdef DEBUG 4567#ifdef DEBUG
4331 dsi->update_bytes = dw * dh * 4568 dsi->update_bytes = dw * dh *
4332 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4569 dsi_get_pixel_size(dsi->pix_fmt) / 8;
4333#endif 4570#endif
4334 dsi_update_screen_dispc(dssdev, dw, dh); 4571 dsi_update_screen_dispc(dssdev);
4335 4572
4336 return 0; 4573 return 0;
4337} 4574}
@@ -4367,28 +4604,22 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4367{ 4604{
4368 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4605 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4369 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4606 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4370 struct omap_video_timings timings; 4607 struct omap_overlay_manager *mgr = dssdev->output->manager;
4371 int r; 4608 int r;
4372 u32 irq = 0; 4609 u32 irq = 0;
4373 4610
4374 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4611 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4375 u16 dw, dh; 4612 dsi->timings.hsw = 1;
4376 4613 dsi->timings.hfp = 1;
4377 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4614 dsi->timings.hbp = 1;
4378 4615 dsi->timings.vsw = 1;
4379 timings.x_res = dw; 4616 dsi->timings.vfp = 0;
4380 timings.y_res = dh; 4617 dsi->timings.vbp = 0;
4381 timings.hsw = 1;
4382 timings.hfp = 1;
4383 timings.hbp = 1;
4384 timings.vsw = 1;
4385 timings.vfp = 0;
4386 timings.vbp = 0;
4387 4618
4388 irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); 4619 irq = dispc_mgr_get_framedone_irq(mgr->id);
4389 4620
4390 r = omap_dispc_register_isr(dsi_framedone_irq_callback, 4621 r = omap_dispc_register_isr(dsi_framedone_irq_callback,
4391 (void *) dssdev, irq); 4622 (void *) dsidev, irq);
4392 if (r) { 4623 if (r) {
4393 DSSERR("can't get FRAMEDONE irq\n"); 4624 DSSERR("can't get FRAMEDONE irq\n");
4394 goto err; 4625 goto err;
@@ -4397,8 +4628,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4397 dsi->mgr_config.stallmode = true; 4628 dsi->mgr_config.stallmode = true;
4398 dsi->mgr_config.fifohandcheck = true; 4629 dsi->mgr_config.fifohandcheck = true;
4399 } else { 4630 } else {
4400 timings = dssdev->panel.timings;
4401
4402 dsi->mgr_config.stallmode = false; 4631 dsi->mgr_config.stallmode = false;
4403 dsi->mgr_config.fifohandcheck = false; 4632 dsi->mgr_config.fifohandcheck = false;
4404 } 4633 }
@@ -4407,14 +4636,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4407 * override interlace, logic level and edge related parameters in 4636 * override interlace, logic level and edge related parameters in
4408 * omap_video_timings with default values 4637 * omap_video_timings with default values
4409 */ 4638 */
4410 timings.interlace = false; 4639 dsi->timings.interlace = false;
4411 timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; 4640 dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4412 timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; 4641 dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4413 timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 4642 dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
4414 timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; 4643 dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
4415 timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; 4644 dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
4416 4645
4417 dss_mgr_set_timings(dssdev->manager, &timings); 4646 dss_mgr_set_timings(mgr, &dsi->timings);
4418 4647
4419 r = dsi_configure_dispc_clocks(dssdev); 4648 r = dsi_configure_dispc_clocks(dssdev);
4420 if (r) 4649 if (r)
@@ -4422,29 +4651,33 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4422 4651
4423 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 4652 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
4424 dsi->mgr_config.video_port_width = 4653 dsi->mgr_config.video_port_width =
4425 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4654 dsi_get_pixel_size(dsi->pix_fmt);
4426 dsi->mgr_config.lcden_sig_polarity = 0; 4655 dsi->mgr_config.lcden_sig_polarity = 0;
4427 4656
4428 dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config); 4657 dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
4429 4658
4430 return 0; 4659 return 0;
4431err1: 4660err1:
4432 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) 4661 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4433 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4662 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4434 (void *) dssdev, irq); 4663 (void *) dsidev, irq);
4435err: 4664err:
4436 return r; 4665 return r;
4437} 4666}
4438 4667
4439static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4668static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4440{ 4669{
4441 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4670 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4672 struct omap_overlay_manager *mgr = dssdev->output->manager;
4673
4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4442 u32 irq; 4675 u32 irq;
4443 4676
4444 irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); 4677 irq = dispc_mgr_get_framedone_irq(mgr->id);
4445 4678
4446 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4679 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4447 (void *) dssdev, irq); 4680 (void *) dsidev, irq);
4448 } 4681 }
4449} 4682}
4450 4683
@@ -4477,6 +4710,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4477{ 4710{
4478 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4711 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4479 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4712 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4713 struct omap_overlay_manager *mgr = dssdev->output->manager;
4480 int r; 4714 int r;
4481 4715
4482 r = dsi_pll_init(dsidev, true, true); 4716 r = dsi_pll_init(dsidev, true, true);
@@ -4489,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4489 4723
4490 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 4724 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
4491 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); 4725 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
4492 dss_select_lcd_clk_source(dssdev->manager->id, 4726 dss_select_lcd_clk_source(mgr->id,
4493 dssdev->clocks.dispc.channel.lcd_clk_src); 4727 dssdev->clocks.dispc.channel.lcd_clk_src);
4494 4728
4495 DSSDBG("PLL OK\n"); 4729 DSSDBG("PLL OK\n");
4496 4730
4497 r = dsi_cio_init(dssdev); 4731 r = dsi_cio_init(dsidev);
4498 if (r) 4732 if (r)
4499 goto err2; 4733 goto err2;
4500 4734
4501 _dsi_print_reset_status(dsidev); 4735 _dsi_print_reset_status(dsidev);
4502 4736
4503 dsi_proto_timings(dssdev); 4737 dsi_proto_timings(dsidev);
4504 dsi_set_lp_clk_divisor(dssdev); 4738 dsi_set_lp_clk_divisor(dssdev);
4505 4739
4506 if (1) 4740 if (1)
@@ -4520,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4520 4754
4521 return 0; 4755 return 0;
4522err3: 4756err3:
4523 dsi_cio_uninit(dssdev); 4757 dsi_cio_uninit(dsidev);
4524err2: 4758err2:
4525 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4759 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4526 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4760 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4527 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4761 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4528 4762
4529err1: 4763err1:
4530 dsi_pll_uninit(dsidev, true); 4764 dsi_pll_uninit(dsidev, true);
@@ -4537,6 +4771,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4537{ 4771{
4538 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4772 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4539 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4773 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4774 struct omap_overlay_manager *mgr = dssdev->output->manager;
4540 4775
4541 if (enter_ulps && !dsi->ulps_enabled) 4776 if (enter_ulps && !dsi->ulps_enabled)
4542 dsi_enter_ulps(dsidev); 4777 dsi_enter_ulps(dsidev);
@@ -4550,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4550 4785
4551 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4786 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4552 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4787 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4553 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4788 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4554 dsi_cio_uninit(dssdev); 4789 dsi_cio_uninit(dsidev);
4555 dsi_pll_uninit(dsidev, disconnect_lanes); 4790 dsi_pll_uninit(dsidev, disconnect_lanes);
4556} 4791}
4557 4792
@@ -4559,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4559{ 4794{
4560 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4795 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4561 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4796 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4797 struct omap_dss_output *out = dssdev->output;
4562 int r = 0; 4798 int r = 0;
4563 4799
4564 DSSDBG("dsi_display_enable\n"); 4800 DSSDBG("dsi_display_enable\n");
@@ -4567,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4567 4803
4568 mutex_lock(&dsi->lock); 4804 mutex_lock(&dsi->lock);
4569 4805
4570 if (dssdev->manager == NULL) { 4806 if (out == NULL || out->manager == NULL) {
4571 DSSERR("failed to enable display: no manager\n"); 4807 DSSERR("failed to enable display: no output/manager\n");
4572 r = -ENODEV; 4808 r = -ENODEV;
4573 goto err_start_dev; 4809 goto err_start_dev;
4574 } 4810 }
@@ -4653,17 +4889,83 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4653} 4889}
4654EXPORT_SYMBOL(omapdss_dsi_enable_te); 4890EXPORT_SYMBOL(omapdss_dsi_enable_te);
4655 4891
4656static int __init dsi_init_display(struct omap_dss_device *dssdev) 4892void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
4893 struct omap_video_timings *timings)
4657{ 4894{
4658 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4895 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4659 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4896 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4660 4897
4661 DSSDBG("DSI init\n"); 4898 mutex_lock(&dsi->lock);
4662 4899
4663 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4900 dsi->timings = *timings;
4664 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 4901
4665 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 4902 mutex_unlock(&dsi->lock);
4666 } 4903}
4904EXPORT_SYMBOL(omapdss_dsi_set_timings);
4905
4906void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
4907{
4908 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4909 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4910
4911 mutex_lock(&dsi->lock);
4912
4913 dsi->timings.x_res = w;
4914 dsi->timings.y_res = h;
4915
4916 mutex_unlock(&dsi->lock);
4917}
4918EXPORT_SYMBOL(omapdss_dsi_set_size);
4919
4920void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
4921 enum omap_dss_dsi_pixel_format fmt)
4922{
4923 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4924 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4925
4926 mutex_lock(&dsi->lock);
4927
4928 dsi->pix_fmt = fmt;
4929
4930 mutex_unlock(&dsi->lock);
4931}
4932EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
4933
4934void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
4935 enum omap_dss_dsi_mode mode)
4936{
4937 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4938 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4939
4940 mutex_lock(&dsi->lock);
4941
4942 dsi->mode = mode;
4943
4944 mutex_unlock(&dsi->lock);
4945}
4946EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
4947
4948void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
4949 struct omap_dss_dsi_videomode_timings *timings)
4950{
4951 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4952 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4953
4954 mutex_lock(&dsi->lock);
4955
4956 dsi->vm_timings = *timings;
4957
4958 mutex_unlock(&dsi->lock);
4959}
4960EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
4961
4962static int __init dsi_init_display(struct omap_dss_device *dssdev)
4963{
4964 struct platform_device *dsidev =
4965 dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
4966 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4967
4968 DSSDBG("DSI init\n");
4667 4969
4668 if (dsi->vdds_dsi_reg == NULL) { 4970 if (dsi->vdds_dsi_reg == NULL) {
4669 struct regulator *vdds_dsi; 4971 struct regulator *vdds_dsi;
@@ -4806,11 +5108,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)
4806 clk_put(dsi->sys_clk); 5108 clk_put(dsi->sys_clk);
4807} 5109}
4808 5110
4809static void __init dsi_probe_pdata(struct platform_device *dsidev) 5111static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
4810{ 5112{
4811 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5113 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4812 struct omap_dss_board_info *pdata = dsidev->dev.platform_data; 5114 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
4813 int i, r; 5115 const char *def_disp_name = dss_get_default_display_name();
5116 struct omap_dss_device *def_dssdev;
5117 int i;
5118
5119 def_dssdev = NULL;
4814 5120
4815 for (i = 0; i < pdata->num_devices; ++i) { 5121 for (i = 0; i < pdata->num_devices; ++i) {
4816 struct omap_dss_device *dssdev = pdata->devices[i]; 5122 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -4821,19 +5127,73 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
4821 if (dssdev->phy.dsi.module != dsi->module_id) 5127 if (dssdev->phy.dsi.module != dsi->module_id)
4822 continue; 5128 continue;
4823 5129
4824 r = dsi_init_display(dssdev); 5130 if (def_dssdev == NULL)
4825 if (r) { 5131 def_dssdev = dssdev;
4826 DSSERR("device %s init failed: %d\n", dssdev->name, r); 5132
4827 continue; 5133 if (def_disp_name != NULL &&
5134 strcmp(dssdev->name, def_disp_name) == 0) {
5135 def_dssdev = dssdev;
5136 break;
4828 } 5137 }
5138 }
4829 5139
4830 r = omap_dss_register_device(dssdev, &dsidev->dev, i); 5140 return def_dssdev;
4831 if (r) 5141}
4832 DSSERR("device %s register failed: %d\n", 5142
4833 dssdev->name, r); 5143static void __init dsi_probe_pdata(struct platform_device *dsidev)
5144{
5145 struct omap_dss_device *plat_dssdev;
5146 struct omap_dss_device *dssdev;
5147 int r;
5148
5149 plat_dssdev = dsi_find_dssdev(dsidev);
5150
5151 if (!plat_dssdev)
5152 return;
5153
5154 dssdev = dss_alloc_and_init_device(&dsidev->dev);
5155 if (!dssdev)
5156 return;
5157
5158 dss_copy_device_pdata(dssdev, plat_dssdev);
5159
5160 r = dsi_init_display(dssdev);
5161 if (r) {
5162 DSSERR("device %s init failed: %d\n", dssdev->name, r);
5163 dss_put_device(dssdev);
5164 return;
5165 }
5166
5167 r = dss_add_device(dssdev);
5168 if (r) {
5169 DSSERR("device %s register failed: %d\n", dssdev->name, r);
5170 dss_put_device(dssdev);
5171 return;
4834 } 5172 }
4835} 5173}
4836 5174
5175static void __init dsi_init_output(struct platform_device *dsidev)
5176{
5177 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5178 struct omap_dss_output *out = &dsi->output;
5179
5180 out->pdev = dsidev;
5181 out->id = dsi->module_id == 0 ?
5182 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
5183
5184 out->type = OMAP_DISPLAY_TYPE_DSI;
5185
5186 dss_register_output(out);
5187}
5188
5189static void __exit dsi_uninit_output(struct platform_device *dsidev)
5190{
5191 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5192 struct omap_dss_output *out = &dsi->output;
5193
5194 dss_unregister_output(out);
5195}
5196
4837/* DSI1 HW IP initialisation */ 5197/* DSI1 HW IP initialisation */
4838static int __init omap_dsihw_probe(struct platform_device *dsidev) 5198static int __init omap_dsihw_probe(struct platform_device *dsidev)
4839{ 5199{
@@ -4848,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
4848 5208
4849 dsi->module_id = dsidev->id; 5209 dsi->module_id = dsidev->id;
4850 dsi->pdev = dsidev; 5210 dsi->pdev = dsidev;
4851 dsi_pdev_map[dsi->module_id] = dsidev;
4852 dev_set_drvdata(&dsidev->dev, dsi); 5211 dev_set_drvdata(&dsidev->dev, dsi);
4853 5212
4854 spin_lock_init(&dsi->irq_lock); 5213 spin_lock_init(&dsi->irq_lock);
@@ -4928,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
4928 else 5287 else
4929 dsi->num_lanes_supported = 3; 5288 dsi->num_lanes_supported = 3;
4930 5289
5290 dsi_init_output(dsidev);
5291
4931 dsi_probe_pdata(dsidev); 5292 dsi_probe_pdata(dsidev);
4932 5293
4933 dsi_runtime_put(dsidev); 5294 dsi_runtime_put(dsidev);
@@ -4957,7 +5318,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
4957 5318
4958 WARN_ON(dsi->scp_clk_refcount > 0); 5319 WARN_ON(dsi->scp_clk_refcount > 0);
4959 5320
4960 omap_dss_unregister_child_devices(&dsidev->dev); 5321 dss_unregister_child_devices(&dsidev->dev);
5322
5323 dsi_uninit_output(dsidev);
4961 5324
4962 pm_runtime_disable(&dsidev->dev); 5325 pm_runtime_disable(&dsidev->dev);
4963 5326
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 04b4586113e3..2ab1c3e96553 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -31,11 +31,11 @@
31#include <linux/clk.h> 31#include <linux/clk.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/gfp.h>
34 35
35#include <video/omapdss.h> 36#include <video/omapdss.h>
36 37
37#include <plat/cpu.h> 38#include <plat/cpu.h>
38#include <plat/clock.h>
39 39
40#include "dss.h" 40#include "dss.h"
41#include "dss_features.h" 41#include "dss_features.h"
@@ -65,6 +65,13 @@ struct dss_reg {
65static int dss_runtime_get(void); 65static int dss_runtime_get(void);
66static void dss_runtime_put(void); 66static void dss_runtime_put(void);
67 67
68struct dss_features {
69 u8 fck_div_max;
70 u8 dss_fck_multiplier;
71 const char *clk_name;
72 int (*dpi_select_source)(enum omap_channel channel);
73};
74
68static struct { 75static struct {
69 struct platform_device *pdev; 76 struct platform_device *pdev;
70 void __iomem *base; 77 void __iomem *base;
@@ -83,6 +90,8 @@ static struct {
83 90
84 bool ctx_valid; 91 bool ctx_valid;
85 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 92 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
93
94 const struct dss_features *feat;
86} dss; 95} dss;
87 96
88static const char * const dss_generic_clk_source_names[] = { 97static const char * const dss_generic_clk_source_names[] = {
@@ -144,7 +153,7 @@ static void dss_restore_context(void)
144#undef SR 153#undef SR
145#undef RR 154#undef RR
146 155
147void dss_sdi_init(u8 datapairs) 156void dss_sdi_init(int datapairs)
148{ 157{
149 u32 l; 158 u32 l;
150 159
@@ -236,7 +245,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
236 return dss_generic_clk_source_names[clk_src]; 245 return dss_generic_clk_source_names[clk_src];
237} 246}
238 247
239
240void dss_dump_clocks(struct seq_file *s) 248void dss_dump_clocks(struct seq_file *s)
241{ 249{
242 unsigned long dpll4_ck_rate; 250 unsigned long dpll4_ck_rate;
@@ -259,18 +267,10 @@ void dss_dump_clocks(struct seq_file *s)
259 267
260 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 268 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
261 269
262 if (cpu_is_omap3630() || cpu_is_omap44xx()) 270 seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n",
263 seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", 271 fclk_name, fclk_real_name, dpll4_ck_rate,
264 fclk_name, fclk_real_name, 272 dpll4_ck_rate / dpll4_m4_ck_rate,
265 dpll4_ck_rate, 273 dss.feat->dss_fck_multiplier, fclk_rate);
266 dpll4_ck_rate / dpll4_m4_ck_rate,
267 fclk_rate);
268 else
269 seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
270 fclk_name, fclk_real_name,
271 dpll4_ck_rate,
272 dpll4_ck_rate / dpll4_m4_ck_rate,
273 fclk_rate);
274 } else { 274 } else {
275 seq_printf(s, "%s (%s) = %lu\n", 275 seq_printf(s, "%s (%s) = %lu\n",
276 fclk_name, fclk_real_name, 276 fclk_name, fclk_real_name,
@@ -431,31 +431,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
431 } 431 }
432} 432}
433 433
434/* calculate clock rates using dividers in cinfo */
435int dss_calc_clock_rates(struct dss_clock_info *cinfo)
436{
437 if (dss.dpll4_m4_ck) {
438 unsigned long prate;
439 u16 fck_div_max = 16;
440
441 if (cpu_is_omap3630() || cpu_is_omap44xx())
442 fck_div_max = 32;
443
444 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
445 return -EINVAL;
446
447 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
448
449 cinfo->fck = prate / cinfo->fck_div;
450 } else {
451 if (cinfo->fck_div != 0)
452 return -EINVAL;
453 cinfo->fck = clk_get_rate(dss.dss_clk);
454 }
455
456 return 0;
457}
458
459int dss_set_clock_div(struct dss_clock_info *cinfo) 434int dss_set_clock_div(struct dss_clock_info *cinfo)
460{ 435{
461 if (dss.dpll4_m4_ck) { 436 if (dss.dpll4_m4_ck) {
@@ -478,26 +453,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
478 return 0; 453 return 0;
479} 454}
480 455
481int dss_get_clock_div(struct dss_clock_info *cinfo)
482{
483 cinfo->fck = clk_get_rate(dss.dss_clk);
484
485 if (dss.dpll4_m4_ck) {
486 unsigned long prate;
487
488 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
489
490 if (cpu_is_omap3630() || cpu_is_omap44xx())
491 cinfo->fck_div = prate / (cinfo->fck);
492 else
493 cinfo->fck_div = prate / (cinfo->fck / 2);
494 } else {
495 cinfo->fck_div = 0;
496 }
497
498 return 0;
499}
500
501unsigned long dss_get_dpll4_rate(void) 456unsigned long dss_get_dpll4_rate(void)
502{ 457{
503 if (dss.dpll4_m4_ck) 458 if (dss.dpll4_m4_ck)
@@ -515,7 +470,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
515 470
516 unsigned long fck, max_dss_fck; 471 unsigned long fck, max_dss_fck;
517 472
518 u16 fck_div, fck_div_max = 16; 473 u16 fck_div;
519 474
520 int match = 0; 475 int match = 0;
521 int min_fck_per_pck; 476 int min_fck_per_pck;
@@ -525,9 +480,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
525 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 480 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
526 481
527 fck = clk_get_rate(dss.dss_clk); 482 fck = clk_get_rate(dss.dss_clk);
528 if (req_pck == dss.cache_req_pck && 483 if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
529 ((cpu_is_omap34xx() && prate == dss.cache_prate) || 484 dss.cache_dss_cinfo.fck == fck) {
530 dss.cache_dss_cinfo.fck == fck)) {
531 DSSDBG("dispc clock info found from cache.\n"); 485 DSSDBG("dispc clock info found from cache.\n");
532 *dss_cinfo = dss.cache_dss_cinfo; 486 *dss_cinfo = dss.cache_dss_cinfo;
533 *dispc_cinfo = dss.cache_dispc_cinfo; 487 *dispc_cinfo = dss.cache_dispc_cinfo;
@@ -564,16 +518,10 @@ retry:
564 518
565 goto found; 519 goto found;
566 } else { 520 } else {
567 if (cpu_is_omap3630() || cpu_is_omap44xx()) 521 for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
568 fck_div_max = 32;
569
570 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
571 struct dispc_clock_info cur_dispc; 522 struct dispc_clock_info cur_dispc;
572 523
573 if (fck_div_max == 32) 524 fck = prate / fck_div * dss.feat->dss_fck_multiplier;
574 fck = prate / fck_div;
575 else
576 fck = prate / fck_div * 2;
577 525
578 if (fck > max_dss_fck) 526 if (fck > max_dss_fck)
579 continue; 527 continue;
@@ -648,9 +596,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)
648 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ 596 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
649} 597}
650 598
651void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) 599void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
652{ 600{
653 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ 601 enum omap_display_type dp;
602 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
603
604 /* Complain about invalid selections */
605 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
606 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
607
608 /* Select only if we have options */
609 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
610 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
654} 611}
655 612
656enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) 613enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
@@ -661,9 +618,71 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
661 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) 618 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
662 return DSS_VENC_TV_CLK; 619 return DSS_VENC_TV_CLK;
663 620
621 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
622 return DSS_HDMI_M_PCLK;
623
664 return REG_GET(DSS_CONTROL, 15, 15); 624 return REG_GET(DSS_CONTROL, 15, 15);
665} 625}
666 626
627static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
628{
629 if (channel != OMAP_DSS_CHANNEL_LCD)
630 return -EINVAL;
631
632 return 0;
633}
634
635static int dss_dpi_select_source_omap4(enum omap_channel channel)
636{
637 int val;
638
639 switch (channel) {
640 case OMAP_DSS_CHANNEL_LCD2:
641 val = 0;
642 break;
643 case OMAP_DSS_CHANNEL_DIGIT:
644 val = 1;
645 break;
646 default:
647 return -EINVAL;
648 }
649
650 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
651
652 return 0;
653}
654
655static int dss_dpi_select_source_omap5(enum omap_channel channel)
656{
657 int val;
658
659 switch (channel) {
660 case OMAP_DSS_CHANNEL_LCD:
661 val = 1;
662 break;
663 case OMAP_DSS_CHANNEL_LCD2:
664 val = 2;
665 break;
666 case OMAP_DSS_CHANNEL_LCD3:
667 val = 3;
668 break;
669 case OMAP_DSS_CHANNEL_DIGIT:
670 val = 0;
671 break;
672 default:
673 return -EINVAL;
674 }
675
676 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
677
678 return 0;
679}
680
681int dss_dpi_select_source(enum omap_channel channel)
682{
683 return dss.feat->dpi_select_source(channel);
684}
685
667static int dss_get_clocks(void) 686static int dss_get_clocks(void)
668{ 687{
669 struct clk *clk; 688 struct clk *clk;
@@ -678,22 +697,11 @@ static int dss_get_clocks(void)
678 697
679 dss.dss_clk = clk; 698 dss.dss_clk = clk;
680 699
681 if (cpu_is_omap34xx()) { 700 clk = clk_get(NULL, dss.feat->clk_name);
682 clk = clk_get(NULL, "dpll4_m4_ck"); 701 if (IS_ERR(clk)) {
683 if (IS_ERR(clk)) { 702 DSSERR("Failed to get %s\n", dss.feat->clk_name);
684 DSSERR("Failed to get dpll4_m4_ck\n"); 703 r = PTR_ERR(clk);
685 r = PTR_ERR(clk); 704 goto err;
686 goto err;
687 }
688 } else if (cpu_is_omap44xx()) {
689 clk = clk_get(NULL, "dpll_per_m5x2_ck");
690 if (IS_ERR(clk)) {
691 DSSERR("Failed to get dpll_per_m5x2_ck\n");
692 r = PTR_ERR(clk);
693 goto err;
694 }
695 } else { /* omap24xx */
696 clk = NULL;
697 } 705 }
698 706
699 dss.dpll4_m4_ck = clk; 707 dss.dpll4_m4_ck = clk;
@@ -749,6 +757,71 @@ void dss_debug_dump_clocks(struct seq_file *s)
749} 757}
750#endif 758#endif
751 759
760static const struct dss_features omap24xx_dss_feats __initconst = {
761 .fck_div_max = 16,
762 .dss_fck_multiplier = 2,
763 .clk_name = NULL,
764 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
765};
766
767static const struct dss_features omap34xx_dss_feats __initconst = {
768 .fck_div_max = 16,
769 .dss_fck_multiplier = 2,
770 .clk_name = "dpll4_m4_ck",
771 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
772};
773
774static const struct dss_features omap3630_dss_feats __initconst = {
775 .fck_div_max = 32,
776 .dss_fck_multiplier = 1,
777 .clk_name = "dpll4_m4_ck",
778 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
779};
780
781static const struct dss_features omap44xx_dss_feats __initconst = {
782 .fck_div_max = 32,
783 .dss_fck_multiplier = 1,
784 .clk_name = "dpll_per_m5x2_ck",
785 .dpi_select_source = &dss_dpi_select_source_omap4,
786};
787
788static const struct dss_features omap54xx_dss_feats __initconst = {
789 .fck_div_max = 64,
790 .dss_fck_multiplier = 1,
791 .clk_name = "dpll_per_h12x2_ck",
792 .dpi_select_source = &dss_dpi_select_source_omap5,
793};
794
795static int __init dss_init_features(struct device *dev)
796{
797 const struct dss_features *src;
798 struct dss_features *dst;
799
800 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
801 if (!dst) {
802 dev_err(dev, "Failed to allocate local DSS Features\n");
803 return -ENOMEM;
804 }
805
806 if (cpu_is_omap24xx())
807 src = &omap24xx_dss_feats;
808 else if (cpu_is_omap34xx())
809 src = &omap34xx_dss_feats;
810 else if (cpu_is_omap3630())
811 src = &omap3630_dss_feats;
812 else if (cpu_is_omap44xx())
813 src = &omap44xx_dss_feats;
814 else if (soc_is_omap54xx())
815 src = &omap54xx_dss_feats;
816 else
817 return -ENODEV;
818
819 memcpy(dst, src, sizeof(*dst));
820 dss.feat = dst;
821
822 return 0;
823}
824
752/* DSS HW IP initialisation */ 825/* DSS HW IP initialisation */
753static int __init omap_dsshw_probe(struct platform_device *pdev) 826static int __init omap_dsshw_probe(struct platform_device *pdev)
754{ 827{
@@ -758,6 +831,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
758 831
759 dss.pdev = pdev; 832 dss.pdev = pdev;
760 833
834 r = dss_init_features(&dss.pdev->dev);
835 if (r)
836 return r;
837
761 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 838 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
762 if (!dss_mem) { 839 if (!dss_mem) {
763 DSSERR("can't get IORESOURCE_MEM DSS\n"); 840 DSSERR("can't get IORESOURCE_MEM DSS\n");
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f67afe76f217..6728892f9dad 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -113,6 +113,17 @@ enum dss_dsi_content_type {
113 DSS_DSI_CONTENT_GENERIC, 113 DSS_DSI_CONTENT_GENERIC,
114}; 114};
115 115
116enum dss_writeback_channel {
117 DSS_WB_LCD1_MGR = 0,
118 DSS_WB_LCD2_MGR = 1,
119 DSS_WB_TV_MGR = 2,
120 DSS_WB_OVL0 = 3,
121 DSS_WB_OVL1 = 4,
122 DSS_WB_OVL2 = 5,
123 DSS_WB_OVL3 = 6,
124 DSS_WB_LCD3_MGR = 7,
125};
126
116struct dss_clock_info { 127struct dss_clock_info {
117 /* rates that we get with dividers below */ 128 /* rates that we get with dividers below */
118 unsigned long fck; 129 unsigned long fck;
@@ -175,6 +186,7 @@ struct seq_file;
175struct platform_device; 186struct platform_device;
176 187
177/* core */ 188/* core */
189const char *dss_get_default_display_name(void);
178struct bus_type *dss_get_bus(void); 190struct bus_type *dss_get_bus(void);
179struct regulator *dss_get_vdds_dsi(void); 191struct regulator *dss_get_vdds_dsi(void);
180struct regulator *dss_get_vdds_sdi(void); 192struct regulator *dss_get_vdds_sdi(void);
@@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
184int dss_set_min_bus_tput(struct device *dev, unsigned long tput); 196int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
185int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); 197int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
186 198
187int omap_dss_register_device(struct omap_dss_device *dssdev, 199struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
188 struct device *parent, int disp_num); 200int dss_add_device(struct omap_dss_device *dssdev);
189void omap_dss_unregister_device(struct omap_dss_device *dssdev); 201void dss_unregister_device(struct omap_dss_device *dssdev);
190void omap_dss_unregister_child_devices(struct device *parent); 202void dss_unregister_child_devices(struct device *parent);
203void dss_put_device(struct omap_dss_device *dssdev);
204void dss_copy_device_pdata(struct omap_dss_device *dst,
205 const struct omap_dss_device *src);
191 206
192/* apply */ 207/* apply */
193void dss_apply_init(void); 208void dss_apply_init(void);
@@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
205int dss_mgr_set_device(struct omap_overlay_manager *mgr, 220int dss_mgr_set_device(struct omap_overlay_manager *mgr,
206 struct omap_dss_device *dssdev); 221 struct omap_dss_device *dssdev);
207int dss_mgr_unset_device(struct omap_overlay_manager *mgr); 222int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
223int dss_mgr_set_output(struct omap_overlay_manager *mgr,
224 struct omap_dss_output *output);
225int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
208void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 226void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
209 struct omap_video_timings *timings); 227 const struct omap_video_timings *timings);
210void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, 228void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
211 const struct dss_lcd_mgr_config *config); 229 const struct dss_lcd_mgr_config *config);
212const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); 230const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
@@ -222,12 +240,17 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
222 struct omap_overlay_manager *mgr); 240 struct omap_overlay_manager *mgr);
223int dss_ovl_unset_manager(struct omap_overlay *ovl); 241int dss_ovl_unset_manager(struct omap_overlay *ovl);
224 242
243/* output */
244void dss_register_output(struct omap_dss_output *out);
245void dss_unregister_output(struct omap_dss_output *out);
246struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
247
225/* display */ 248/* display */
226int dss_suspend_all_devices(void); 249int dss_suspend_all_devices(void);
227int dss_resume_all_devices(void); 250int dss_resume_all_devices(void);
228void dss_disable_all_devices(void); 251void dss_disable_all_devices(void);
229 252
230void dss_init_device(struct platform_device *pdev, 253int dss_init_device(struct platform_device *pdev,
231 struct omap_dss_device *dssdev); 254 struct omap_dss_device *dssdev);
232void dss_uninit_device(struct platform_device *pdev, 255void dss_uninit_device(struct platform_device *pdev,
233 struct omap_dss_device *dssdev); 256 struct omap_dss_device *dssdev);
@@ -254,22 +277,29 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
254 return false; 277 return false;
255} 278}
256 279
280int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
281 struct platform_device *pdev);
282void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
283
257/* overlay */ 284/* overlay */
258void dss_init_overlays(struct platform_device *pdev); 285void dss_init_overlays(struct platform_device *pdev);
259void dss_uninit_overlays(struct platform_device *pdev); 286void dss_uninit_overlays(struct platform_device *pdev);
260void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 287void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
261void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
262int dss_ovl_simple_check(struct omap_overlay *ovl, 288int dss_ovl_simple_check(struct omap_overlay *ovl,
263 const struct omap_overlay_info *info); 289 const struct omap_overlay_info *info);
264int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 290int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
265 const struct omap_video_timings *mgr_timings); 291 const struct omap_video_timings *mgr_timings);
266bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, 292bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
267 enum omap_color_mode mode); 293 enum omap_color_mode mode);
294int dss_overlay_kobj_init(struct omap_overlay *ovl,
295 struct platform_device *pdev);
296void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
268 297
269/* DSS */ 298/* DSS */
270int dss_init_platform_driver(void) __init; 299int dss_init_platform_driver(void) __init;
271void dss_uninit_platform_driver(void); 300void dss_uninit_platform_driver(void);
272 301
302int dss_dpi_select_source(enum omap_channel channel);
273void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 303void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
274enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 304enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
275const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 305const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
@@ -279,7 +309,7 @@ void dss_dump_clocks(struct seq_file *s);
279void dss_debug_dump_clocks(struct seq_file *s); 309void dss_debug_dump_clocks(struct seq_file *s);
280#endif 310#endif
281 311
282void dss_sdi_init(u8 datapairs); 312void dss_sdi_init(int datapairs);
283int dss_sdi_enable(void); 313int dss_sdi_enable(void);
284void dss_sdi_disable(void); 314void dss_sdi_disable(void);
285 315
@@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
296void dss_set_dac_pwrdn_bgz(bool enable); 326void dss_set_dac_pwrdn_bgz(bool enable);
297 327
298unsigned long dss_get_dpll4_rate(void); 328unsigned long dss_get_dpll4_rate(void);
299int dss_calc_clock_rates(struct dss_clock_info *cinfo);
300int dss_set_clock_div(struct dss_clock_info *cinfo); 329int dss_set_clock_div(struct dss_clock_info *cinfo);
301int dss_get_clock_div(struct dss_clock_info *cinfo);
302int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 330int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
303 struct dispc_clock_info *dispc_cinfo); 331 struct dispc_clock_info *dispc_cinfo);
304 332
@@ -427,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
427void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 455void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
428 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, 456 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
429 bool manual_update); 457 bool manual_update);
430int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 458int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
431 bool replication, const struct omap_video_timings *mgr_timings); 459 bool replication, const struct omap_video_timings *mgr_timings,
460 bool mem_to_mem);
432int dispc_ovl_enable(enum omap_plane plane, bool enable); 461int dispc_ovl_enable(enum omap_plane plane, bool enable);
433void dispc_ovl_set_channel_out(enum omap_plane plane, 462void dispc_ovl_set_channel_out(enum omap_plane plane,
434 enum omap_channel channel); 463 enum omap_channel channel);
@@ -457,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
457void dispc_mgr_setup(enum omap_channel channel, 486void dispc_mgr_setup(enum omap_channel channel,
458 struct omap_overlay_manager_info *info); 487 struct omap_overlay_manager_info *info);
459 488
489u32 dispc_wb_get_framedone_irq(void);
490bool dispc_wb_go_busy(void);
491void dispc_wb_go(void);
492void dispc_wb_enable(bool enable);
493bool dispc_wb_is_enabled(void);
494void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
495int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
496 bool mem_to_mem, const struct omap_video_timings *timings);
497
460/* VENC */ 498/* VENC */
461#ifdef CONFIG_OMAP2_DSS_VENC 499#ifdef CONFIG_OMAP2_DSS_VENC
462int venc_init_platform_driver(void) __init; 500int venc_init_platform_driver(void) __init;
@@ -469,6 +507,20 @@ static inline unsigned long venc_get_pixel_clock(void)
469 return 0; 507 return 0;
470} 508}
471#endif 509#endif
510int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
511void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
512void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
513 struct omap_video_timings *timings);
514int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
515 struct omap_video_timings *timings);
516u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
517int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
518void omapdss_venc_set_type(struct omap_dss_device *dssdev,
519 enum omap_dss_venc_type type);
520void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
521 bool invert_polarity);
522int venc_panel_init(void);
523void venc_panel_exit(void);
472 524
473/* HDMI */ 525/* HDMI */
474#ifdef CONFIG_OMAP4_DSS_HDMI 526#ifdef CONFIG_OMAP4_DSS_HDMI
@@ -484,7 +536,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
484#endif 536#endif
485int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); 537int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
486void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); 538void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
487void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); 539void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
540 struct omap_video_timings *timings);
488int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 541int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
489 struct omap_video_timings *timings); 542 struct omap_video_timings *timings);
490int omapdss_hdmi_read_edid(u8 *buf, int len); 543int omapdss_hdmi_read_edid(u8 *buf, int len);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 938709724f0c..acbc1e1efba3 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -46,7 +46,9 @@ struct omap_dss_features {
46 46
47 const int num_mgrs; 47 const int num_mgrs;
48 const int num_ovls; 48 const int num_ovls;
49 const int num_wbs;
49 const enum omap_display_type *supported_displays; 50 const enum omap_display_type *supported_displays;
51 const enum omap_dss_output_id *supported_outputs;
50 const enum omap_color_mode *supported_color_modes; 52 const enum omap_color_mode *supported_color_modes;
51 const enum omap_overlay_caps *overlay_caps; 53 const enum omap_overlay_caps *overlay_caps;
52 const char * const *clksrc_names; 54 const char * const *clksrc_names;
@@ -106,6 +108,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
106 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, 108 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
107}; 109};
108 110
111static const struct dss_reg_field omap5_dss_reg_fields[] = {
112 [FEAT_REG_FIRHINC] = { 12, 0 },
113 [FEAT_REG_FIRVINC] = { 28, 16 },
114 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
115 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
116 [FEAT_REG_FIFOSIZE] = { 15, 0 },
117 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
118 [FEAT_REG_VERTICALACCU] = { 26, 16 },
119 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
120 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
121 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
122 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
123 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
124};
125
109static const enum omap_display_type omap2_dss_supported_displays[] = { 126static const enum omap_display_type omap2_dss_supported_displays[] = {
110 /* OMAP_DSS_CHANNEL_LCD */ 127 /* OMAP_DSS_CHANNEL_LCD */
111 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, 128 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
@@ -144,6 +161,76 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
144 OMAP_DISPLAY_TYPE_DSI, 161 OMAP_DISPLAY_TYPE_DSI,
145}; 162};
146 163
164static const enum omap_display_type omap5_dss_supported_displays[] = {
165 /* OMAP_DSS_CHANNEL_LCD */
166 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
167 OMAP_DISPLAY_TYPE_DSI,
168
169 /* OMAP_DSS_CHANNEL_DIGIT */
170 OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
171
172 /* OMAP_DSS_CHANNEL_LCD2 */
173 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
174 OMAP_DISPLAY_TYPE_DSI,
175};
176
177static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
178 /* OMAP_DSS_CHANNEL_LCD */
179 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
180
181 /* OMAP_DSS_CHANNEL_DIGIT */
182 OMAP_DSS_OUTPUT_VENC,
183};
184
185static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
186 /* OMAP_DSS_CHANNEL_LCD */
187 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
188 OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
189
190 /* OMAP_DSS_CHANNEL_DIGIT */
191 OMAP_DSS_OUTPUT_VENC,
192};
193
194static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
195 /* OMAP_DSS_CHANNEL_LCD */
196 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
197 OMAP_DSS_OUTPUT_DSI1,
198
199 /* OMAP_DSS_CHANNEL_DIGIT */
200 OMAP_DSS_OUTPUT_VENC,
201};
202
203static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
204 /* OMAP_DSS_CHANNEL_LCD */
205 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
206 OMAP_DSS_OUTPUT_DSI1,
207
208 /* OMAP_DSS_CHANNEL_DIGIT */
209 OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
210 OMAP_DSS_OUTPUT_DPI,
211
212 /* OMAP_DSS_CHANNEL_LCD2 */
213 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
214 OMAP_DSS_OUTPUT_DSI2,
215};
216
217static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
218 /* OMAP_DSS_CHANNEL_LCD */
219 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
220 OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
221
222 /* OMAP_DSS_CHANNEL_DIGIT */
223 OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
224
225 /* OMAP_DSS_CHANNEL_LCD2 */
226 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
227 OMAP_DSS_OUTPUT_DSI1,
228
229 /* OMAP_DSS_CHANNEL_LCD3 */
230 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
231 OMAP_DSS_OUTPUT_DSI2,
232};
233
147static const enum omap_color_mode omap2_dss_supported_color_modes[] = { 234static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
148 /* OMAP_DSS_GFX */ 235 /* OMAP_DSS_GFX */
149 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | 236 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
@@ -224,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
224 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | 311 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
225 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | 312 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
226 OMAP_DSS_COLOR_RGBX32, 313 OMAP_DSS_COLOR_RGBX32,
314
315 /* OMAP_DSS_WB */
316 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
317 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
318 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
319 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
320 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
321 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
322 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
323 OMAP_DSS_COLOR_RGBX32,
227}; 324};
228 325
229static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { 326static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
230 /* OMAP_DSS_GFX */ 327 /* OMAP_DSS_GFX */
231 0, 328 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
232 329
233 /* OMAP_DSS_VIDEO1 */ 330 /* OMAP_DSS_VIDEO1 */
234 OMAP_DSS_OVL_CAP_SCALE, 331 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
332 OMAP_DSS_OVL_CAP_REPLICATION,
235 333
236 /* OMAP_DSS_VIDEO2 */ 334 /* OMAP_DSS_VIDEO2 */
237 OMAP_DSS_OVL_CAP_SCALE, 335 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
336 OMAP_DSS_OVL_CAP_REPLICATION,
238}; 337};
239 338
240static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { 339static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
241 /* OMAP_DSS_GFX */ 340 /* OMAP_DSS_GFX */
242 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 341 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
342 OMAP_DSS_OVL_CAP_REPLICATION,
243 343
244 /* OMAP_DSS_VIDEO1 */ 344 /* OMAP_DSS_VIDEO1 */
245 OMAP_DSS_OVL_CAP_SCALE, 345 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
346 OMAP_DSS_OVL_CAP_REPLICATION,
246 347
247 /* OMAP_DSS_VIDEO2 */ 348 /* OMAP_DSS_VIDEO2 */
248 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 349 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
350 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
249}; 351};
250 352
251static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { 353static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
252 /* OMAP_DSS_GFX */ 354 /* OMAP_DSS_GFX */
253 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 355 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
356 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
254 357
255 /* OMAP_DSS_VIDEO1 */ 358 /* OMAP_DSS_VIDEO1 */
256 OMAP_DSS_OVL_CAP_SCALE, 359 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
360 OMAP_DSS_OVL_CAP_REPLICATION,
257 361
258 /* OMAP_DSS_VIDEO2 */ 362 /* OMAP_DSS_VIDEO2 */
259 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 363 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
260 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 364 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
365 OMAP_DSS_OVL_CAP_REPLICATION,
261}; 366};
262 367
263static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { 368static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
264 /* OMAP_DSS_GFX */ 369 /* OMAP_DSS_GFX */
265 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | 370 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
266 OMAP_DSS_OVL_CAP_ZORDER, 371 OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
372 OMAP_DSS_OVL_CAP_REPLICATION,
267 373
268 /* OMAP_DSS_VIDEO1 */ 374 /* OMAP_DSS_VIDEO1 */
269 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 375 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
270 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 376 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
377 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
271 378
272 /* OMAP_DSS_VIDEO2 */ 379 /* OMAP_DSS_VIDEO2 */
273 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 380 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
274 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 381 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
382 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
275 383
276 /* OMAP_DSS_VIDEO3 */ 384 /* OMAP_DSS_VIDEO3 */
277 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 385 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
278 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 386 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
387 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
279}; 388};
280 389
281static const char * const omap2_dss_clk_source_names[] = { 390static const char * const omap2_dss_clk_source_names[] = {
@@ -298,6 +407,14 @@ static const char * const omap4_dss_clk_source_names[] = {
298 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", 407 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
299}; 408};
300 409
410static const char * const omap5_dss_clk_source_names[] = {
411 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
412 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
413 [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
414 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
415 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
416};
417
301static const struct dss_param_range omap2_dss_param_range[] = { 418static const struct dss_param_range omap2_dss_param_range[] = {
302 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 419 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
303 [FEAT_PARAM_DSS_PCD] = { 2, 255 }, 420 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
@@ -326,6 +443,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
326 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, 443 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
327 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 444 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
328 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 445 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
446 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
329 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 447 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
330 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 448 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
331 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, 449 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
@@ -341,6 +459,23 @@ static const struct dss_param_range omap4_dss_param_range[] = {
341 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, 459 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
342 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 460 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
343 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 461 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
462 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
463 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
464 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
465 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
466 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
467};
468
469static const struct dss_param_range omap5_dss_param_range[] = {
470 [FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
471 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
472 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
473 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
474 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
475 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
476 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
477 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
478 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
344 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 479 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
345 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 480 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
346 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, 481 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
@@ -373,6 +508,26 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
373 FEAT_ALPHA_FIXED_ZORDER, 508 FEAT_ALPHA_FIXED_ZORDER,
374 FEAT_FIFO_MERGE, 509 FEAT_FIFO_MERGE,
375 FEAT_OMAP3_DSI_FIFO_BUG, 510 FEAT_OMAP3_DSI_FIFO_BUG,
511 FEAT_DPI_USES_VDDS_DSI,
512};
513
514static const enum dss_feat_id am35xx_dss_feat_list[] = {
515 FEAT_LCDENABLEPOL,
516 FEAT_LCDENABLESIGNAL,
517 FEAT_PCKFREEENABLE,
518 FEAT_FUNCGATED,
519 FEAT_LINEBUFFERSPLIT,
520 FEAT_ROWREPEATENABLE,
521 FEAT_RESIZECONF,
522 FEAT_DSI_PLL_FREQSEL,
523 FEAT_DSI_REVERSE_TXCLKESC,
524 FEAT_VENC_REQUIRES_TV_DAC_CLK,
525 FEAT_CPR,
526 FEAT_PRELOAD,
527 FEAT_FIR_COEF_V,
528 FEAT_ALPHA_FIXED_ZORDER,
529 FEAT_FIFO_MERGE,
530 FEAT_OMAP3_DSI_FIFO_BUG,
376}; 531};
377 532
378static const enum dss_feat_id omap3630_dss_feat_list[] = { 533static const enum dss_feat_id omap3630_dss_feat_list[] = {
@@ -447,6 +602,28 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
447 FEAT_BURST_2D, 602 FEAT_BURST_2D,
448}; 603};
449 604
605static const enum dss_feat_id omap5_dss_feat_list[] = {
606 FEAT_MGR_LCD2,
607 FEAT_CORE_CLK_DIV,
608 FEAT_LCD_CLK_SRC,
609 FEAT_DSI_DCS_CMD_CONFIG_VC,
610 FEAT_DSI_VC_OCP_WIDTH,
611 FEAT_DSI_GNQ,
612 FEAT_HDMI_CTS_SWMODE,
613 FEAT_HDMI_AUDIO_USE_MCLK,
614 FEAT_HANDLE_UV_SEPARATE,
615 FEAT_ATTR2,
616 FEAT_CPR,
617 FEAT_PRELOAD,
618 FEAT_FIR_COEF_V,
619 FEAT_ALPHA_FREE_ZORDER,
620 FEAT_FIFO_MERGE,
621 FEAT_BURST_2D,
622 FEAT_DSI_PLL_SELFREQDCO,
623 FEAT_DSI_PLL_REFSEL,
624 FEAT_DSI_PHY_DCC,
625};
626
450/* OMAP2 DSS Features */ 627/* OMAP2 DSS Features */
451static const struct omap_dss_features omap2_dss_features = { 628static const struct omap_dss_features omap2_dss_features = {
452 .reg_fields = omap2_dss_reg_fields, 629 .reg_fields = omap2_dss_reg_fields,
@@ -458,6 +635,7 @@ static const struct omap_dss_features omap2_dss_features = {
458 .num_mgrs = 2, 635 .num_mgrs = 2,
459 .num_ovls = 3, 636 .num_ovls = 3,
460 .supported_displays = omap2_dss_supported_displays, 637 .supported_displays = omap2_dss_supported_displays,
638 .supported_outputs = omap2_dss_supported_outputs,
461 .supported_color_modes = omap2_dss_supported_color_modes, 639 .supported_color_modes = omap2_dss_supported_color_modes,
462 .overlay_caps = omap2_dss_overlay_caps, 640 .overlay_caps = omap2_dss_overlay_caps,
463 .clksrc_names = omap2_dss_clk_source_names, 641 .clksrc_names = omap2_dss_clk_source_names,
@@ -478,6 +656,31 @@ static const struct omap_dss_features omap3430_dss_features = {
478 .num_mgrs = 2, 656 .num_mgrs = 2,
479 .num_ovls = 3, 657 .num_ovls = 3,
480 .supported_displays = omap3430_dss_supported_displays, 658 .supported_displays = omap3430_dss_supported_displays,
659 .supported_outputs = omap3430_dss_supported_outputs,
660 .supported_color_modes = omap3_dss_supported_color_modes,
661 .overlay_caps = omap3430_dss_overlay_caps,
662 .clksrc_names = omap3_dss_clk_source_names,
663 .dss_params = omap3_dss_param_range,
664 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
665 .buffer_size_unit = 1,
666 .burst_size_unit = 8,
667};
668
669/*
670 * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
671 * vdds_dsi regulator.
672 */
673static const struct omap_dss_features am35xx_dss_features = {
674 .reg_fields = omap3_dss_reg_fields,
675 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
676
677 .features = am35xx_dss_feat_list,
678 .num_features = ARRAY_SIZE(am35xx_dss_feat_list),
679
680 .num_mgrs = 2,
681 .num_ovls = 3,
682 .supported_displays = omap3430_dss_supported_displays,
683 .supported_outputs = omap3430_dss_supported_outputs,
481 .supported_color_modes = omap3_dss_supported_color_modes, 684 .supported_color_modes = omap3_dss_supported_color_modes,
482 .overlay_caps = omap3430_dss_overlay_caps, 685 .overlay_caps = omap3430_dss_overlay_caps,
483 .clksrc_names = omap3_dss_clk_source_names, 686 .clksrc_names = omap3_dss_clk_source_names,
@@ -497,6 +700,7 @@ static const struct omap_dss_features omap3630_dss_features = {
497 .num_mgrs = 2, 700 .num_mgrs = 2,
498 .num_ovls = 3, 701 .num_ovls = 3,
499 .supported_displays = omap3630_dss_supported_displays, 702 .supported_displays = omap3630_dss_supported_displays,
703 .supported_outputs = omap3630_dss_supported_outputs,
500 .supported_color_modes = omap3_dss_supported_color_modes, 704 .supported_color_modes = omap3_dss_supported_color_modes,
501 .overlay_caps = omap3630_dss_overlay_caps, 705 .overlay_caps = omap3630_dss_overlay_caps,
502 .clksrc_names = omap3_dss_clk_source_names, 706 .clksrc_names = omap3_dss_clk_source_names,
@@ -517,7 +721,9 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
517 721
518 .num_mgrs = 3, 722 .num_mgrs = 3,
519 .num_ovls = 4, 723 .num_ovls = 4,
724 .num_wbs = 1,
520 .supported_displays = omap4_dss_supported_displays, 725 .supported_displays = omap4_dss_supported_displays,
726 .supported_outputs = omap4_dss_supported_outputs,
521 .supported_color_modes = omap4_dss_supported_color_modes, 727 .supported_color_modes = omap4_dss_supported_color_modes,
522 .overlay_caps = omap4_dss_overlay_caps, 728 .overlay_caps = omap4_dss_overlay_caps,
523 .clksrc_names = omap4_dss_clk_source_names, 729 .clksrc_names = omap4_dss_clk_source_names,
@@ -537,7 +743,9 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
537 743
538 .num_mgrs = 3, 744 .num_mgrs = 3,
539 .num_ovls = 4, 745 .num_ovls = 4,
746 .num_wbs = 1,
540 .supported_displays = omap4_dss_supported_displays, 747 .supported_displays = omap4_dss_supported_displays,
748 .supported_outputs = omap4_dss_supported_outputs,
541 .supported_color_modes = omap4_dss_supported_color_modes, 749 .supported_color_modes = omap4_dss_supported_color_modes,
542 .overlay_caps = omap4_dss_overlay_caps, 750 .overlay_caps = omap4_dss_overlay_caps,
543 .clksrc_names = omap4_dss_clk_source_names, 751 .clksrc_names = omap4_dss_clk_source_names,
@@ -557,7 +765,9 @@ static const struct omap_dss_features omap4_dss_features = {
557 765
558 .num_mgrs = 3, 766 .num_mgrs = 3,
559 .num_ovls = 4, 767 .num_ovls = 4,
768 .num_wbs = 1,
560 .supported_displays = omap4_dss_supported_displays, 769 .supported_displays = omap4_dss_supported_displays,
770 .supported_outputs = omap4_dss_supported_outputs,
561 .supported_color_modes = omap4_dss_supported_color_modes, 771 .supported_color_modes = omap4_dss_supported_color_modes,
562 .overlay_caps = omap4_dss_overlay_caps, 772 .overlay_caps = omap4_dss_overlay_caps,
563 .clksrc_names = omap4_dss_clk_source_names, 773 .clksrc_names = omap4_dss_clk_source_names,
@@ -567,6 +777,27 @@ static const struct omap_dss_features omap4_dss_features = {
567 .burst_size_unit = 16, 777 .burst_size_unit = 16,
568}; 778};
569 779
780/* OMAP5 DSS Features */
781static const struct omap_dss_features omap5_dss_features = {
782 .reg_fields = omap5_dss_reg_fields,
783 .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
784
785 .features = omap5_dss_feat_list,
786 .num_features = ARRAY_SIZE(omap5_dss_feat_list),
787
788 .num_mgrs = 3,
789 .num_ovls = 4,
790 .supported_displays = omap5_dss_supported_displays,
791 .supported_outputs = omap5_dss_supported_outputs,
792 .supported_color_modes = omap4_dss_supported_color_modes,
793 .overlay_caps = omap4_dss_overlay_caps,
794 .clksrc_names = omap5_dss_clk_source_names,
795 .dss_params = omap5_dss_param_range,
796 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
797 .buffer_size_unit = 16,
798 .burst_size_unit = 16,
799};
800
570#if defined(CONFIG_OMAP4_DSS_HDMI) 801#if defined(CONFIG_OMAP4_DSS_HDMI)
571/* HDMI OMAP4 Functions*/ 802/* HDMI OMAP4 Functions*/
572static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { 803static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
@@ -612,6 +843,11 @@ int dss_feat_get_num_ovls(void)
612 return omap_current_dss_features->num_ovls; 843 return omap_current_dss_features->num_ovls;
613} 844}
614 845
846int dss_feat_get_num_wbs(void)
847{
848 return omap_current_dss_features->num_wbs;
849}
850
615unsigned long dss_feat_get_param_min(enum dss_range_param param) 851unsigned long dss_feat_get_param_min(enum dss_range_param param)
616{ 852{
617 return omap_current_dss_features->dss_params[param].min; 853 return omap_current_dss_features->dss_params[param].min;
@@ -627,6 +863,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
627 return omap_current_dss_features->supported_displays[channel]; 863 return omap_current_dss_features->supported_displays[channel];
628} 864}
629 865
866enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
867{
868 return omap_current_dss_features->supported_outputs[channel];
869}
870
630enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) 871enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
631{ 872{
632 return omap_current_dss_features->supported_color_modes[plane]; 873 return omap_current_dss_features->supported_color_modes[plane];
@@ -694,8 +935,13 @@ void dss_features_init(void)
694 omap_current_dss_features = &omap2_dss_features; 935 omap_current_dss_features = &omap2_dss_features;
695 else if (cpu_is_omap3630()) 936 else if (cpu_is_omap3630())
696 omap_current_dss_features = &omap3630_dss_features; 937 omap_current_dss_features = &omap3630_dss_features;
697 else if (cpu_is_omap34xx()) 938 else if (cpu_is_omap34xx()) {
698 omap_current_dss_features = &omap3430_dss_features; 939 if (soc_is_am35xx()) {
940 omap_current_dss_features = &am35xx_dss_features;
941 } else {
942 omap_current_dss_features = &omap3430_dss_features;
943 }
944 }
699 else if (omap_rev() == OMAP4430_REV_ES1_0) 945 else if (omap_rev() == OMAP4430_REV_ES1_0)
700 omap_current_dss_features = &omap4430_es1_0_dss_features; 946 omap_current_dss_features = &omap4430_es1_0_dss_features;
701 else if (omap_rev() == OMAP4430_REV_ES2_0 || 947 else if (omap_rev() == OMAP4430_REV_ES2_0 ||
@@ -704,6 +950,8 @@ void dss_features_init(void)
704 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; 950 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
705 else if (cpu_is_omap44xx()) 951 else if (cpu_is_omap44xx())
706 omap_current_dss_features = &omap4_dss_features; 952 omap_current_dss_features = &omap4_dss_features;
953 else if (soc_is_omap54xx())
954 omap_current_dss_features = &omap5_dss_features;
707 else 955 else
708 DSSWARN("Unsupported OMAP version"); 956 DSSWARN("Unsupported OMAP version");
709} 957}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 996ffcbfed58..9218113b5e88 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -50,6 +50,7 @@ enum dss_feat_id {
50 FEAT_DSI_VC_OCP_WIDTH, 50 FEAT_DSI_VC_OCP_WIDTH,
51 FEAT_DSI_REVERSE_TXCLKESC, 51 FEAT_DSI_REVERSE_TXCLKESC,
52 FEAT_DSI_GNQ, 52 FEAT_DSI_GNQ,
53 FEAT_DPI_USES_VDDS_DSI,
53 FEAT_HDMI_CTS_SWMODE, 54 FEAT_HDMI_CTS_SWMODE,
54 FEAT_HDMI_AUDIO_USE_MCLK, 55 FEAT_HDMI_AUDIO_USE_MCLK,
55 FEAT_HANDLE_UV_SEPARATE, 56 FEAT_HANDLE_UV_SEPARATE,
@@ -64,6 +65,9 @@ enum dss_feat_id {
64 /* An unknown HW bug causing the normal FIFO thresholds not to work */ 65 /* An unknown HW bug causing the normal FIFO thresholds not to work */
65 FEAT_OMAP3_DSI_FIFO_BUG, 66 FEAT_OMAP3_DSI_FIFO_BUG,
66 FEAT_BURST_2D, 67 FEAT_BURST_2D,
68 FEAT_DSI_PLL_SELFREQDCO,
69 FEAT_DSI_PLL_REFSEL,
70 FEAT_DSI_PHY_DCC,
67}; 71};
68 72
69/* DSS register field id */ 73/* DSS register field id */
@@ -91,6 +95,7 @@ enum dss_range_param {
91 FEAT_PARAM_DSIPLL_REGM_DSI, 95 FEAT_PARAM_DSIPLL_REGM_DSI,
92 FEAT_PARAM_DSIPLL_FINT, 96 FEAT_PARAM_DSIPLL_FINT,
93 FEAT_PARAM_DSIPLL_LPDIV, 97 FEAT_PARAM_DSIPLL_LPDIV,
98 FEAT_PARAM_DSI_FCK,
94 FEAT_PARAM_DOWNSCALE, 99 FEAT_PARAM_DOWNSCALE,
95 FEAT_PARAM_LINEWIDTH, 100 FEAT_PARAM_LINEWIDTH,
96 FEAT_PARAM_MGR_WIDTH, 101 FEAT_PARAM_MGR_WIDTH,
@@ -100,9 +105,11 @@ enum dss_range_param {
100/* DSS Feature Functions */ 105/* DSS Feature Functions */
101int dss_feat_get_num_mgrs(void); 106int dss_feat_get_num_mgrs(void);
102int dss_feat_get_num_ovls(void); 107int dss_feat_get_num_ovls(void);
108int dss_feat_get_num_wbs(void);
103unsigned long dss_feat_get_param_min(enum dss_range_param param); 109unsigned long dss_feat_get_param_min(enum dss_range_param param);
104unsigned long dss_feat_get_param_max(enum dss_range_param param); 110unsigned long dss_feat_get_param_max(enum dss_range_param param);
105enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); 111enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
112enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
106enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); 113enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
107enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 114enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
108bool dss_feat_color_mode_supported(enum omap_plane plane, 115bool dss_feat_color_mode_supported(enum omap_plane plane,
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 060216fdc578..a48a7dd75b33 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -32,6 +32,8 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#include <linux/gpio.h>
36#include <linux/regulator/consumer.h>
35#include <video/omapdss.h> 37#include <video/omapdss.h>
36 38
37#include "ti_hdmi.h" 39#include "ti_hdmi.h"
@@ -61,6 +63,13 @@ static struct {
61 struct hdmi_ip_data ip_data; 63 struct hdmi_ip_data ip_data;
62 64
63 struct clk *sys_clk; 65 struct clk *sys_clk;
66 struct regulator *vdda_hdmi_dac_reg;
67
68 int ct_cp_hpd_gpio;
69 int ls_oe_gpio;
70 int hpd_gpio;
71
72 struct omap_dss_output output;
64} hdmi; 73} hdmi;
65 74
66/* 75/*
@@ -314,12 +323,47 @@ static void hdmi_runtime_put(void)
314 323
315static int __init hdmi_init_display(struct omap_dss_device *dssdev) 324static int __init hdmi_init_display(struct omap_dss_device *dssdev)
316{ 325{
326 int r;
327
328 struct gpio gpios[] = {
329 { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
330 { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
331 { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
332 };
333
317 DSSDBG("init_display\n"); 334 DSSDBG("init_display\n");
318 335
319 dss_init_hdmi_ip_ops(&hdmi.ip_data); 336 dss_init_hdmi_ip_ops(&hdmi.ip_data);
337
338 if (hdmi.vdda_hdmi_dac_reg == NULL) {
339 struct regulator *reg;
340
341 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
342
343 if (IS_ERR(reg)) {
344 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
345 return PTR_ERR(reg);
346 }
347
348 hdmi.vdda_hdmi_dac_reg = reg;
349 }
350
351 r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
352 if (r)
353 return r;
354
320 return 0; 355 return 0;
321} 356}
322 357
358static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
359{
360 DSSDBG("uninit_display\n");
361
362 gpio_free(hdmi.ct_cp_hpd_gpio);
363 gpio_free(hdmi.ls_oe_gpio);
364 gpio_free(hdmi.hpd_gpio);
365}
366
323static const struct hdmi_config *hdmi_find_timing( 367static const struct hdmi_config *hdmi_find_timing(
324 const struct hdmi_config *timings_arr, 368 const struct hdmi_config *timings_arr,
325 int len) 369 int len)
@@ -459,32 +503,30 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
459static int hdmi_power_on(struct omap_dss_device *dssdev) 503static int hdmi_power_on(struct omap_dss_device *dssdev)
460{ 504{
461 int r; 505 int r;
462 const struct hdmi_config *timing;
463 struct omap_video_timings *p; 506 struct omap_video_timings *p;
507 struct omap_overlay_manager *mgr = dssdev->output->manager;
464 unsigned long phy; 508 unsigned long phy;
465 509
510 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
511 gpio_set_value(hdmi.ls_oe_gpio, 1);
512
513 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
514 udelay(300);
515
516 r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
517 if (r)
518 goto err_vdac_enable;
519
466 r = hdmi_runtime_get(); 520 r = hdmi_runtime_get();
467 if (r) 521 if (r)
468 return r; 522 goto err_runtime_get;
469 523
470 dss_mgr_disable(dssdev->manager); 524 dss_mgr_disable(mgr);
471 525
472 p = &dssdev->panel.timings; 526 p = &hdmi.ip_data.cfg.timings;
473 527
474 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", 528 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
475 dssdev->panel.timings.x_res,
476 dssdev->panel.timings.y_res);
477 529
478 timing = hdmi_get_timings();
479 if (timing == NULL) {
480 /* HDMI code 4 corresponds to 640 * 480 VGA */
481 hdmi.ip_data.cfg.cm.code = 4;
482 /* DVI mode 1 corresponds to HDMI 0 to DVI */
483 hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
484 hdmi.ip_data.cfg = vesa_timings[0];
485 } else {
486 hdmi.ip_data.cfg = *timing;
487 }
488 phy = p->pixel_clock; 530 phy = p->pixel_clock;
489 531
490 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 532 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
@@ -495,13 +537,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
495 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 537 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
496 if (r) { 538 if (r) {
497 DSSDBG("Failed to lock PLL\n"); 539 DSSDBG("Failed to lock PLL\n");
498 goto err; 540 goto err_pll_enable;
499 } 541 }
500 542
501 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); 543 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
502 if (r) { 544 if (r) {
503 DSSDBG("Failed to start PHY\n"); 545 DSSDBG("Failed to start PHY\n");
504 goto err; 546 goto err_phy_enable;
505 } 547 }
506 548
507 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 549 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
@@ -521,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
521 dispc_enable_gamma_table(0); 563 dispc_enable_gamma_table(0);
522 564
523 /* tv size */ 565 /* tv size */
524 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 566 dss_mgr_set_timings(mgr, p);
525 567
526 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); 568 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
527 if (r) 569 if (r)
528 goto err_vid_enable; 570 goto err_vid_enable;
529 571
530 r = dss_mgr_enable(dssdev->manager); 572 r = dss_mgr_enable(mgr);
531 if (r) 573 if (r)
532 goto err_mgr_enable; 574 goto err_mgr_enable;
533 575
@@ -537,20 +579,33 @@ err_mgr_enable:
537 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 579 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
538err_vid_enable: 580err_vid_enable:
539 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 581 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
582err_phy_enable:
540 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 583 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
541err: 584err_pll_enable:
542 hdmi_runtime_put(); 585 hdmi_runtime_put();
586err_runtime_get:
587 regulator_disable(hdmi.vdda_hdmi_dac_reg);
588err_vdac_enable:
589 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
590 gpio_set_value(hdmi.ls_oe_gpio, 0);
543 return -EIO; 591 return -EIO;
544} 592}
545 593
546static void hdmi_power_off(struct omap_dss_device *dssdev) 594static void hdmi_power_off(struct omap_dss_device *dssdev)
547{ 595{
548 dss_mgr_disable(dssdev->manager); 596 struct omap_overlay_manager *mgr = dssdev->output->manager;
597
598 dss_mgr_disable(mgr);
549 599
550 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 600 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
551 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 601 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
552 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 602 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
553 hdmi_runtime_put(); 603 hdmi_runtime_put();
604
605 regulator_disable(hdmi.vdda_hdmi_dac_reg);
606
607 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
608 gpio_set_value(hdmi.ls_oe_gpio, 0);
554} 609}
555 610
556int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 611int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -567,25 +622,22 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
567 622
568} 623}
569 624
570void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) 625void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
626 struct omap_video_timings *timings)
571{ 627{
572 struct hdmi_cm cm; 628 struct hdmi_cm cm;
629 const struct hdmi_config *t;
573 630
574 cm = hdmi_get_code(&dssdev->panel.timings); 631 mutex_lock(&hdmi.lock);
575 hdmi.ip_data.cfg.cm.code = cm.code;
576 hdmi.ip_data.cfg.cm.mode = cm.mode;
577 632
578 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 633 cm = hdmi_get_code(timings);
579 int r; 634 hdmi.ip_data.cfg.cm = cm;
580 635
581 hdmi_power_off(dssdev); 636 t = hdmi_get_timings();
637 if (t != NULL)
638 hdmi.ip_data.cfg = *t;
582 639
583 r = hdmi_power_on(dssdev); 640 mutex_unlock(&hdmi.lock);
584 if (r)
585 DSSERR("failed to power on device\n");
586 } else {
587 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
588 }
589} 641}
590 642
591static void hdmi_dump_regs(struct seq_file *s) 643static void hdmi_dump_regs(struct seq_file *s)
@@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void)
640 692
641int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) 693int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
642{ 694{
643 struct omap_dss_hdmi_data *priv = dssdev->data; 695 struct omap_dss_output *out = dssdev->output;
644 int r = 0; 696 int r = 0;
645 697
646 DSSDBG("ENTER hdmi_display_enable\n"); 698 DSSDBG("ENTER hdmi_display_enable\n");
647 699
648 mutex_lock(&hdmi.lock); 700 mutex_lock(&hdmi.lock);
649 701
650 if (dssdev->manager == NULL) { 702 if (out == NULL || out->manager == NULL) {
651 DSSERR("failed to enable display: no manager\n"); 703 DSSERR("failed to enable display: no output/manager\n");
652 r = -ENODEV; 704 r = -ENODEV;
653 goto err0; 705 goto err0;
654 } 706 }
655 707
656 hdmi.ip_data.hpd_gpio = priv->hpd_gpio; 708 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
657 709
658 r = omap_dss_start_device(dssdev); 710 r = omap_dss_start_device(dssdev);
659 if (r) { 711 if (r) {
@@ -661,26 +713,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
661 goto err0; 713 goto err0;
662 } 714 }
663 715
664 if (dssdev->platform_enable) {
665 r = dssdev->platform_enable(dssdev);
666 if (r) {
667 DSSERR("failed to enable GPIO's\n");
668 goto err1;
669 }
670 }
671
672 r = hdmi_power_on(dssdev); 716 r = hdmi_power_on(dssdev);
673 if (r) { 717 if (r) {
674 DSSERR("failed to power on device\n"); 718 DSSERR("failed to power on device\n");
675 goto err2; 719 goto err1;
676 } 720 }
677 721
678 mutex_unlock(&hdmi.lock); 722 mutex_unlock(&hdmi.lock);
679 return 0; 723 return 0;
680 724
681err2:
682 if (dssdev->platform_disable)
683 dssdev->platform_disable(dssdev);
684err1: 725err1:
685 omap_dss_stop_device(dssdev); 726 omap_dss_stop_device(dssdev);
686err0: 727err0:
@@ -696,9 +737,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
696 737
697 hdmi_power_off(dssdev); 738 hdmi_power_off(dssdev);
698 739
699 if (dssdev->platform_disable)
700 dssdev->platform_disable(dssdev);
701
702 omap_dss_stop_device(dssdev); 740 omap_dss_stop_device(dssdev);
703 741
704 mutex_unlock(&hdmi.lock); 742 mutex_unlock(&hdmi.lock);
@@ -869,10 +907,14 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
869 907
870#endif 908#endif
871 909
872static void __init hdmi_probe_pdata(struct platform_device *pdev) 910static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
873{ 911{
874 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 912 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
875 int r, i; 913 const char *def_disp_name = dss_get_default_display_name();
914 struct omap_dss_device *def_dssdev;
915 int i;
916
917 def_dssdev = NULL;
876 918
877 for (i = 0; i < pdata->num_devices; ++i) { 919 for (i = 0; i < pdata->num_devices; ++i) {
878 struct omap_dss_device *dssdev = pdata->devices[i]; 920 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -880,17 +922,76 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
880 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) 922 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
881 continue; 923 continue;
882 924
883 r = hdmi_init_display(dssdev); 925 if (def_dssdev == NULL)
884 if (r) { 926 def_dssdev = dssdev;
885 DSSERR("device %s init failed: %d\n", dssdev->name, r); 927
886 continue; 928 if (def_disp_name != NULL &&
929 strcmp(dssdev->name, def_disp_name) == 0) {
930 def_dssdev = dssdev;
931 break;
887 } 932 }
933 }
888 934
889 r = omap_dss_register_device(dssdev, &pdev->dev, i); 935 return def_dssdev;
890 if (r) 936}
891 DSSERR("device %s register failed: %d\n", 937
892 dssdev->name, r); 938static void __init hdmi_probe_pdata(struct platform_device *pdev)
939{
940 struct omap_dss_device *plat_dssdev;
941 struct omap_dss_device *dssdev;
942 struct omap_dss_hdmi_data *priv;
943 int r;
944
945 plat_dssdev = hdmi_find_dssdev(pdev);
946
947 if (!plat_dssdev)
948 return;
949
950 dssdev = dss_alloc_and_init_device(&pdev->dev);
951 if (!dssdev)
952 return;
953
954 dss_copy_device_pdata(dssdev, plat_dssdev);
955
956 priv = dssdev->data;
957
958 hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
959 hdmi.ls_oe_gpio = priv->ls_oe_gpio;
960 hdmi.hpd_gpio = priv->hpd_gpio;
961
962 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
963
964 r = hdmi_init_display(dssdev);
965 if (r) {
966 DSSERR("device %s init failed: %d\n", dssdev->name, r);
967 dss_put_device(dssdev);
968 return;
893 } 969 }
970
971 r = dss_add_device(dssdev);
972 if (r) {
973 DSSERR("device %s register failed: %d\n", dssdev->name, r);
974 dss_put_device(dssdev);
975 return;
976 }
977}
978
979static void __init hdmi_init_output(struct platform_device *pdev)
980{
981 struct omap_dss_output *out = &hdmi.output;
982
983 out->pdev = pdev;
984 out->id = OMAP_DSS_OUTPUT_HDMI;
985 out->type = OMAP_DISPLAY_TYPE_HDMI;
986
987 dss_register_output(out);
988}
989
990static void __exit hdmi_uninit_output(struct platform_device *pdev)
991{
992 struct omap_dss_output *out = &hdmi.output;
993
994 dss_unregister_output(out);
894} 995}
895 996
896/* HDMI HW IP initialisation */ 997/* HDMI HW IP initialisation */
@@ -929,23 +1030,37 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
929 hdmi.ip_data.core_av_offset = HDMI_CORE_AV; 1030 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
930 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1031 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
931 hdmi.ip_data.phy_offset = HDMI_PHY; 1032 hdmi.ip_data.phy_offset = HDMI_PHY;
1033
932 mutex_init(&hdmi.ip_data.lock); 1034 mutex_init(&hdmi.ip_data.lock);
933 1035
934 hdmi_panel_init(); 1036 hdmi_panel_init();
935 1037
936 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 1038 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
937 1039
1040 hdmi_init_output(pdev);
1041
938 hdmi_probe_pdata(pdev); 1042 hdmi_probe_pdata(pdev);
939 1043
940 return 0; 1044 return 0;
941} 1045}
942 1046
1047static int __exit hdmi_remove_child(struct device *dev, void *data)
1048{
1049 struct omap_dss_device *dssdev = to_dss_device(dev);
1050 hdmi_uninit_display(dssdev);
1051 return 0;
1052}
1053
943static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) 1054static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
944{ 1055{
945 omap_dss_unregister_child_devices(&pdev->dev); 1056 device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
1057
1058 dss_unregister_child_devices(&pdev->dev);
946 1059
947 hdmi_panel_exit(); 1060 hdmi_panel_exit();
948 1061
1062 hdmi_uninit_output(pdev);
1063
949 pm_runtime_disable(&pdev->dev); 1064 pm_runtime_disable(&pdev->dev);
950 1065
951 hdmi_put_clocks(); 1066 hdmi_put_clocks();
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index e10844faadf9..69fb115bab32 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -41,17 +41,34 @@ static struct {
41 41
42static int hdmi_panel_probe(struct omap_dss_device *dssdev) 42static int hdmi_panel_probe(struct omap_dss_device *dssdev)
43{ 43{
44 /* Initialize default timings to VGA in DVI mode */
45 const struct omap_video_timings default_timings = {
46 .x_res = 640,
47 .y_res = 480,
48 .pixel_clock = 25175,
49 .hsw = 96,
50 .hfp = 16,
51 .hbp = 48,
52 .vsw = 2,
53 .vfp = 11,
54 .vbp = 31,
55
56 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
57 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
58
59 .interlace = false,
60 };
61
44 DSSDBG("ENTER hdmi_panel_probe\n"); 62 DSSDBG("ENTER hdmi_panel_probe\n");
45 63
46 dssdev->panel.timings = (struct omap_video_timings) 64 dssdev->panel.timings = default_timings;
47 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
48 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
49 false,
50 };
51 65
52 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", 66 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
53 dssdev->panel.timings.x_res, 67 dssdev->panel.timings.x_res,
54 dssdev->panel.timings.y_res); 68 dssdev->panel.timings.y_res);
69
70 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
71
55 return 0; 72 return 0;
56} 73}
57 74
@@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
228 goto err; 245 goto err;
229 } 246 }
230 247
248 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
249
231 r = omapdss_hdmi_display_enable(dssdev); 250 r = omapdss_hdmi_display_enable(dssdev);
232 if (r) { 251 if (r) {
233 DSSERR("failed to power on\n"); 252 DSSERR("failed to power on\n");
@@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
336 */ 355 */
337 hdmi_panel_audio_disable(dssdev); 356 hdmi_panel_audio_disable(dssdev);
338 357
358 omapdss_hdmi_display_set_timing(dssdev, timings);
339 dssdev->panel.timings = *timings; 359 dssdev->panel.timings = *timings;
340 omapdss_hdmi_display_set_timing(dssdev);
341 360
342 mutex_unlock(&hdmi.lock); 361 mutex_unlock(&hdmi.lock);
343} 362}
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
new file mode 100644
index 000000000000..9a2fb59b6f89
--- /dev/null
+++ b/drivers/video/omap2/dss/manager-sysfs.c
@@ -0,0 +1,512 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "MANAGER"
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/jiffies.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
37}
38
39static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 struct omap_dss_device *dssdev = mgr->get_device(mgr);
42
43 return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
44 dssdev->name : "<none>");
45}
46
47static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
48 const char *buf, size_t size)
49{
50 int r = 0;
51 size_t len = size;
52 struct omap_dss_device *dssdev = NULL;
53
54 int match(struct omap_dss_device *dssdev, void *data)
55 {
56 const char *str = data;
57 return sysfs_streq(dssdev->name, str);
58 }
59
60 if (buf[size-1] == '\n')
61 --len;
62
63 if (len > 0)
64 dssdev = omap_dss_find_device((void *)buf, match);
65
66 if (len > 0 && dssdev == NULL)
67 return -EINVAL;
68
69 if (dssdev)
70 DSSDBG("display %s found\n", dssdev->name);
71
72 if (mgr->output) {
73 r = mgr->unset_output(mgr);
74 if (r) {
75 DSSERR("failed to unset current output\n");
76 goto put_device;
77 }
78 }
79
80 if (dssdev) {
81 struct omap_dss_output *out = dssdev->output;
82
83 /*
84 * a registered device should have an output connected to it
85 * already
86 */
87 if (!out) {
88 DSSERR("device has no output connected to it\n");
89 goto put_device;
90 }
91
92 r = mgr->set_output(mgr, out);
93 if (r) {
94 DSSERR("failed to set manager output\n");
95 goto put_device;
96 }
97
98 r = mgr->apply(mgr);
99 if (r) {
100 DSSERR("failed to apply dispc config\n");
101 goto put_device;
102 }
103 }
104
105put_device:
106 if (dssdev)
107 omap_dss_put_device(dssdev);
108
109 return r ? r : size;
110}
111
112static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
113 char *buf)
114{
115 struct omap_overlay_manager_info info;
116
117 mgr->get_manager_info(mgr, &info);
118
119 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
120}
121
122static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
123 const char *buf, size_t size)
124{
125 struct omap_overlay_manager_info info;
126 u32 color;
127 int r;
128
129 r = kstrtouint(buf, 0, &color);
130 if (r)
131 return r;
132
133 mgr->get_manager_info(mgr, &info);
134
135 info.default_color = color;
136
137 r = mgr->set_manager_info(mgr, &info);
138 if (r)
139 return r;
140
141 r = mgr->apply(mgr);
142 if (r)
143 return r;
144
145 return size;
146}
147
148static const char *trans_key_type_str[] = {
149 "gfx-destination",
150 "video-source",
151};
152
153static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
154 char *buf)
155{
156 enum omap_dss_trans_key_type key_type;
157 struct omap_overlay_manager_info info;
158
159 mgr->get_manager_info(mgr, &info);
160
161 key_type = info.trans_key_type;
162 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
163
164 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
165}
166
167static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
168 const char *buf, size_t size)
169{
170 enum omap_dss_trans_key_type key_type;
171 struct omap_overlay_manager_info info;
172 int r;
173
174 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
175 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
176 if (sysfs_streq(buf, trans_key_type_str[key_type]))
177 break;
178 }
179
180 if (key_type == ARRAY_SIZE(trans_key_type_str))
181 return -EINVAL;
182
183 mgr->get_manager_info(mgr, &info);
184
185 info.trans_key_type = key_type;
186
187 r = mgr->set_manager_info(mgr, &info);
188 if (r)
189 return r;
190
191 r = mgr->apply(mgr);
192 if (r)
193 return r;
194
195 return size;
196}
197
198static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
199 char *buf)
200{
201 struct omap_overlay_manager_info info;
202
203 mgr->get_manager_info(mgr, &info);
204
205 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
206}
207
208static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
209 const char *buf, size_t size)
210{
211 struct omap_overlay_manager_info info;
212 u32 key_value;
213 int r;
214
215 r = kstrtouint(buf, 0, &key_value);
216 if (r)
217 return r;
218
219 mgr->get_manager_info(mgr, &info);
220
221 info.trans_key = key_value;
222
223 r = mgr->set_manager_info(mgr, &info);
224 if (r)
225 return r;
226
227 r = mgr->apply(mgr);
228 if (r)
229 return r;
230
231 return size;
232}
233
234static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
235 char *buf)
236{
237 struct omap_overlay_manager_info info;
238
239 mgr->get_manager_info(mgr, &info);
240
241 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
242}
243
244static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
245 const char *buf, size_t size)
246{
247 struct omap_overlay_manager_info info;
248 bool enable;
249 int r;
250
251 r = strtobool(buf, &enable);
252 if (r)
253 return r;
254
255 mgr->get_manager_info(mgr, &info);
256
257 info.trans_enabled = enable;
258
259 r = mgr->set_manager_info(mgr, &info);
260 if (r)
261 return r;
262
263 r = mgr->apply(mgr);
264 if (r)
265 return r;
266
267 return size;
268}
269
270static ssize_t manager_alpha_blending_enabled_show(
271 struct omap_overlay_manager *mgr, char *buf)
272{
273 struct omap_overlay_manager_info info;
274
275 mgr->get_manager_info(mgr, &info);
276
277 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
278
279 return snprintf(buf, PAGE_SIZE, "%d\n",
280 info.partial_alpha_enabled);
281}
282
283static ssize_t manager_alpha_blending_enabled_store(
284 struct omap_overlay_manager *mgr,
285 const char *buf, size_t size)
286{
287 struct omap_overlay_manager_info info;
288 bool enable;
289 int r;
290
291 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
292
293 r = strtobool(buf, &enable);
294 if (r)
295 return r;
296
297 mgr->get_manager_info(mgr, &info);
298
299 info.partial_alpha_enabled = enable;
300
301 r = mgr->set_manager_info(mgr, &info);
302 if (r)
303 return r;
304
305 r = mgr->apply(mgr);
306 if (r)
307 return r;
308
309 return size;
310}
311
312static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
313 char *buf)
314{
315 struct omap_overlay_manager_info info;
316
317 mgr->get_manager_info(mgr, &info);
318
319 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
320}
321
322static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
323 const char *buf, size_t size)
324{
325 struct omap_overlay_manager_info info;
326 int r;
327 bool enable;
328
329 if (!dss_has_feature(FEAT_CPR))
330 return -ENODEV;
331
332 r = strtobool(buf, &enable);
333 if (r)
334 return r;
335
336 mgr->get_manager_info(mgr, &info);
337
338 if (info.cpr_enable == enable)
339 return size;
340
341 info.cpr_enable = enable;
342
343 r = mgr->set_manager_info(mgr, &info);
344 if (r)
345 return r;
346
347 r = mgr->apply(mgr);
348 if (r)
349 return r;
350
351 return size;
352}
353
354static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
355 char *buf)
356{
357 struct omap_overlay_manager_info info;
358
359 mgr->get_manager_info(mgr, &info);
360
361 return snprintf(buf, PAGE_SIZE,
362 "%d %d %d %d %d %d %d %d %d\n",
363 info.cpr_coefs.rr,
364 info.cpr_coefs.rg,
365 info.cpr_coefs.rb,
366 info.cpr_coefs.gr,
367 info.cpr_coefs.gg,
368 info.cpr_coefs.gb,
369 info.cpr_coefs.br,
370 info.cpr_coefs.bg,
371 info.cpr_coefs.bb);
372}
373
374static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
375 const char *buf, size_t size)
376{
377 struct omap_overlay_manager_info info;
378 struct omap_dss_cpr_coefs coefs;
379 int r, i;
380 s16 *arr;
381
382 if (!dss_has_feature(FEAT_CPR))
383 return -ENODEV;
384
385 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
386 &coefs.rr, &coefs.rg, &coefs.rb,
387 &coefs.gr, &coefs.gg, &coefs.gb,
388 &coefs.br, &coefs.bg, &coefs.bb) != 9)
389 return -EINVAL;
390
391 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
392 coefs.gr, coefs.gg, coefs.gb,
393 coefs.br, coefs.bg, coefs.bb };
394
395 for (i = 0; i < 9; ++i) {
396 if (arr[i] < -512 || arr[i] > 511)
397 return -EINVAL;
398 }
399
400 mgr->get_manager_info(mgr, &info);
401
402 info.cpr_coefs = coefs;
403
404 r = mgr->set_manager_info(mgr, &info);
405 if (r)
406 return r;
407
408 r = mgr->apply(mgr);
409 if (r)
410 return r;
411
412 return size;
413}
414
415struct manager_attribute {
416 struct attribute attr;
417 ssize_t (*show)(struct omap_overlay_manager *, char *);
418 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
419};
420
421#define MANAGER_ATTR(_name, _mode, _show, _store) \
422 struct manager_attribute manager_attr_##_name = \
423 __ATTR(_name, _mode, _show, _store)
424
425static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
426static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
427 manager_display_show, manager_display_store);
428static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
429 manager_default_color_show, manager_default_color_store);
430static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
431 manager_trans_key_type_show, manager_trans_key_type_store);
432static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
433 manager_trans_key_value_show, manager_trans_key_value_store);
434static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
435 manager_trans_key_enabled_show,
436 manager_trans_key_enabled_store);
437static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
438 manager_alpha_blending_enabled_show,
439 manager_alpha_blending_enabled_store);
440static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
441 manager_cpr_enable_show,
442 manager_cpr_enable_store);
443static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
444 manager_cpr_coef_show,
445 manager_cpr_coef_store);
446
447
448static struct attribute *manager_sysfs_attrs[] = {
449 &manager_attr_name.attr,
450 &manager_attr_display.attr,
451 &manager_attr_default_color.attr,
452 &manager_attr_trans_key_type.attr,
453 &manager_attr_trans_key_value.attr,
454 &manager_attr_trans_key_enabled.attr,
455 &manager_attr_alpha_blending_enabled.attr,
456 &manager_attr_cpr_enable.attr,
457 &manager_attr_cpr_coef.attr,
458 NULL
459};
460
461static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
462 char *buf)
463{
464 struct omap_overlay_manager *manager;
465 struct manager_attribute *manager_attr;
466
467 manager = container_of(kobj, struct omap_overlay_manager, kobj);
468 manager_attr = container_of(attr, struct manager_attribute, attr);
469
470 if (!manager_attr->show)
471 return -ENOENT;
472
473 return manager_attr->show(manager, buf);
474}
475
476static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
477 const char *buf, size_t size)
478{
479 struct omap_overlay_manager *manager;
480 struct manager_attribute *manager_attr;
481
482 manager = container_of(kobj, struct omap_overlay_manager, kobj);
483 manager_attr = container_of(attr, struct manager_attribute, attr);
484
485 if (!manager_attr->store)
486 return -ENOENT;
487
488 return manager_attr->store(manager, buf, size);
489}
490
491static const struct sysfs_ops manager_sysfs_ops = {
492 .show = manager_attr_show,
493 .store = manager_attr_store,
494};
495
496static struct kobj_type manager_ktype = {
497 .sysfs_ops = &manager_sysfs_ops,
498 .default_attrs = manager_sysfs_attrs,
499};
500
501int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
502 struct platform_device *pdev)
503{
504 return kobject_init_and_add(&mgr->kobj, &manager_ktype,
505 &pdev->dev.kobj, "manager%d", mgr->id);
506}
507
508void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
509{
510 kobject_del(&mgr->kobj);
511 kobject_put(&mgr->kobj);
512}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 53710fadc82d..c54d2f620ce3 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -36,463 +36,15 @@
36static int num_managers; 36static int num_managers;
37static struct omap_overlay_manager *managers; 37static struct omap_overlay_manager *managers;
38 38
39static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 39static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
40{ 40{
41 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); 41 return mgr->output ? mgr->output->device : NULL;
42} 42}
43 43
44static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
45{
46 return snprintf(buf, PAGE_SIZE, "%s\n",
47 mgr->device ? mgr->device->name : "<none>");
48}
49
50static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
51 const char *buf, size_t size)
52{
53 int r = 0;
54 size_t len = size;
55 struct omap_dss_device *dssdev = NULL;
56
57 int match(struct omap_dss_device *dssdev, void *data)
58 {
59 const char *str = data;
60 return sysfs_streq(dssdev->name, str);
61 }
62
63 if (buf[size-1] == '\n')
64 --len;
65
66 if (len > 0)
67 dssdev = omap_dss_find_device((void *)buf, match);
68
69 if (len > 0 && dssdev == NULL)
70 return -EINVAL;
71
72 if (dssdev)
73 DSSDBG("display %s found\n", dssdev->name);
74
75 if (mgr->device) {
76 r = mgr->unset_device(mgr);
77 if (r) {
78 DSSERR("failed to unset display\n");
79 goto put_device;
80 }
81 }
82
83 if (dssdev) {
84 r = mgr->set_device(mgr, dssdev);
85 if (r) {
86 DSSERR("failed to set manager\n");
87 goto put_device;
88 }
89
90 r = mgr->apply(mgr);
91 if (r) {
92 DSSERR("failed to apply dispc config\n");
93 goto put_device;
94 }
95 }
96
97put_device:
98 if (dssdev)
99 omap_dss_put_device(dssdev);
100
101 return r ? r : size;
102}
103
104static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
105 char *buf)
106{
107 struct omap_overlay_manager_info info;
108
109 mgr->get_manager_info(mgr, &info);
110
111 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
112}
113
114static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
115 const char *buf, size_t size)
116{
117 struct omap_overlay_manager_info info;
118 u32 color;
119 int r;
120
121 r = kstrtouint(buf, 0, &color);
122 if (r)
123 return r;
124
125 mgr->get_manager_info(mgr, &info);
126
127 info.default_color = color;
128
129 r = mgr->set_manager_info(mgr, &info);
130 if (r)
131 return r;
132
133 r = mgr->apply(mgr);
134 if (r)
135 return r;
136
137 return size;
138}
139
140static const char *trans_key_type_str[] = {
141 "gfx-destination",
142 "video-source",
143};
144
145static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
146 char *buf)
147{
148 enum omap_dss_trans_key_type key_type;
149 struct omap_overlay_manager_info info;
150
151 mgr->get_manager_info(mgr, &info);
152
153 key_type = info.trans_key_type;
154 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
155
156 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
157}
158
159static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
160 const char *buf, size_t size)
161{
162 enum omap_dss_trans_key_type key_type;
163 struct omap_overlay_manager_info info;
164 int r;
165
166 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
167 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
168 if (sysfs_streq(buf, trans_key_type_str[key_type]))
169 break;
170 }
171
172 if (key_type == ARRAY_SIZE(trans_key_type_str))
173 return -EINVAL;
174
175 mgr->get_manager_info(mgr, &info);
176
177 info.trans_key_type = key_type;
178
179 r = mgr->set_manager_info(mgr, &info);
180 if (r)
181 return r;
182
183 r = mgr->apply(mgr);
184 if (r)
185 return r;
186
187 return size;
188}
189
190static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
191 char *buf)
192{
193 struct omap_overlay_manager_info info;
194
195 mgr->get_manager_info(mgr, &info);
196
197 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
198}
199
200static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
201 const char *buf, size_t size)
202{
203 struct omap_overlay_manager_info info;
204 u32 key_value;
205 int r;
206
207 r = kstrtouint(buf, 0, &key_value);
208 if (r)
209 return r;
210
211 mgr->get_manager_info(mgr, &info);
212
213 info.trans_key = key_value;
214
215 r = mgr->set_manager_info(mgr, &info);
216 if (r)
217 return r;
218
219 r = mgr->apply(mgr);
220 if (r)
221 return r;
222
223 return size;
224}
225
226static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
227 char *buf)
228{
229 struct omap_overlay_manager_info info;
230
231 mgr->get_manager_info(mgr, &info);
232
233 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
234}
235
236static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
237 const char *buf, size_t size)
238{
239 struct omap_overlay_manager_info info;
240 bool enable;
241 int r;
242
243 r = strtobool(buf, &enable);
244 if (r)
245 return r;
246
247 mgr->get_manager_info(mgr, &info);
248
249 info.trans_enabled = enable;
250
251 r = mgr->set_manager_info(mgr, &info);
252 if (r)
253 return r;
254
255 r = mgr->apply(mgr);
256 if (r)
257 return r;
258
259 return size;
260}
261
262static ssize_t manager_alpha_blending_enabled_show(
263 struct omap_overlay_manager *mgr, char *buf)
264{
265 struct omap_overlay_manager_info info;
266
267 mgr->get_manager_info(mgr, &info);
268
269 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
270
271 return snprintf(buf, PAGE_SIZE, "%d\n",
272 info.partial_alpha_enabled);
273}
274
275static ssize_t manager_alpha_blending_enabled_store(
276 struct omap_overlay_manager *mgr,
277 const char *buf, size_t size)
278{
279 struct omap_overlay_manager_info info;
280 bool enable;
281 int r;
282
283 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
284
285 r = strtobool(buf, &enable);
286 if (r)
287 return r;
288
289 mgr->get_manager_info(mgr, &info);
290
291 info.partial_alpha_enabled = enable;
292
293 r = mgr->set_manager_info(mgr, &info);
294 if (r)
295 return r;
296
297 r = mgr->apply(mgr);
298 if (r)
299 return r;
300
301 return size;
302}
303
304static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
305 char *buf)
306{
307 struct omap_overlay_manager_info info;
308
309 mgr->get_manager_info(mgr, &info);
310
311 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
312}
313
314static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
315 const char *buf, size_t size)
316{
317 struct omap_overlay_manager_info info;
318 int r;
319 bool enable;
320
321 if (!dss_has_feature(FEAT_CPR))
322 return -ENODEV;
323
324 r = strtobool(buf, &enable);
325 if (r)
326 return r;
327
328 mgr->get_manager_info(mgr, &info);
329
330 if (info.cpr_enable == enable)
331 return size;
332
333 info.cpr_enable = enable;
334
335 r = mgr->set_manager_info(mgr, &info);
336 if (r)
337 return r;
338
339 r = mgr->apply(mgr);
340 if (r)
341 return r;
342
343 return size;
344}
345
346static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
347 char *buf)
348{
349 struct omap_overlay_manager_info info;
350
351 mgr->get_manager_info(mgr, &info);
352
353 return snprintf(buf, PAGE_SIZE,
354 "%d %d %d %d %d %d %d %d %d\n",
355 info.cpr_coefs.rr,
356 info.cpr_coefs.rg,
357 info.cpr_coefs.rb,
358 info.cpr_coefs.gr,
359 info.cpr_coefs.gg,
360 info.cpr_coefs.gb,
361 info.cpr_coefs.br,
362 info.cpr_coefs.bg,
363 info.cpr_coefs.bb);
364}
365
366static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
367 const char *buf, size_t size)
368{
369 struct omap_overlay_manager_info info;
370 struct omap_dss_cpr_coefs coefs;
371 int r, i;
372 s16 *arr;
373
374 if (!dss_has_feature(FEAT_CPR))
375 return -ENODEV;
376
377 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
378 &coefs.rr, &coefs.rg, &coefs.rb,
379 &coefs.gr, &coefs.gg, &coefs.gb,
380 &coefs.br, &coefs.bg, &coefs.bb) != 9)
381 return -EINVAL;
382
383 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
384 coefs.gr, coefs.gg, coefs.gb,
385 coefs.br, coefs.bg, coefs.bb };
386
387 for (i = 0; i < 9; ++i) {
388 if (arr[i] < -512 || arr[i] > 511)
389 return -EINVAL;
390 }
391
392 mgr->get_manager_info(mgr, &info);
393
394 info.cpr_coefs = coefs;
395
396 r = mgr->set_manager_info(mgr, &info);
397 if (r)
398 return r;
399
400 r = mgr->apply(mgr);
401 if (r)
402 return r;
403
404 return size;
405}
406
407struct manager_attribute {
408 struct attribute attr;
409 ssize_t (*show)(struct omap_overlay_manager *, char *);
410 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
411};
412
413#define MANAGER_ATTR(_name, _mode, _show, _store) \
414 struct manager_attribute manager_attr_##_name = \
415 __ATTR(_name, _mode, _show, _store)
416
417static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
418static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
419 manager_display_show, manager_display_store);
420static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
421 manager_default_color_show, manager_default_color_store);
422static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
423 manager_trans_key_type_show, manager_trans_key_type_store);
424static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
425 manager_trans_key_value_show, manager_trans_key_value_store);
426static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
427 manager_trans_key_enabled_show,
428 manager_trans_key_enabled_store);
429static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
430 manager_alpha_blending_enabled_show,
431 manager_alpha_blending_enabled_store);
432static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
433 manager_cpr_enable_show,
434 manager_cpr_enable_store);
435static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
436 manager_cpr_coef_show,
437 manager_cpr_coef_store);
438
439
440static struct attribute *manager_sysfs_attrs[] = {
441 &manager_attr_name.attr,
442 &manager_attr_display.attr,
443 &manager_attr_default_color.attr,
444 &manager_attr_trans_key_type.attr,
445 &manager_attr_trans_key_value.attr,
446 &manager_attr_trans_key_enabled.attr,
447 &manager_attr_alpha_blending_enabled.attr,
448 &manager_attr_cpr_enable.attr,
449 &manager_attr_cpr_coef.attr,
450 NULL
451};
452
453static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
454 char *buf)
455{
456 struct omap_overlay_manager *manager;
457 struct manager_attribute *manager_attr;
458
459 manager = container_of(kobj, struct omap_overlay_manager, kobj);
460 manager_attr = container_of(attr, struct manager_attribute, attr);
461
462 if (!manager_attr->show)
463 return -ENOENT;
464
465 return manager_attr->show(manager, buf);
466}
467
468static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
469 const char *buf, size_t size)
470{
471 struct omap_overlay_manager *manager;
472 struct manager_attribute *manager_attr;
473
474 manager = container_of(kobj, struct omap_overlay_manager, kobj);
475 manager_attr = container_of(attr, struct manager_attribute, attr);
476
477 if (!manager_attr->store)
478 return -ENOENT;
479
480 return manager_attr->store(manager, buf, size);
481}
482
483static const struct sysfs_ops manager_sysfs_ops = {
484 .show = manager_attr_show,
485 .store = manager_attr_store,
486};
487
488static struct kobj_type manager_ktype = {
489 .sysfs_ops = &manager_sysfs_ops,
490 .default_attrs = manager_sysfs_attrs,
491};
492
493static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 44static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
494{ 45{
495 unsigned long timeout = msecs_to_jiffies(500); 46 unsigned long timeout = msecs_to_jiffies(500);
47 struct omap_dss_device *dssdev = mgr->get_device(mgr);
496 u32 irq; 48 u32 irq;
497 int r; 49 int r;
498 50
@@ -500,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
500 if (r) 52 if (r)
501 return r; 53 return r;
502 54
503 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) 55 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
504 irq = DISPC_IRQ_EVSYNC_ODD; 56 irq = DISPC_IRQ_EVSYNC_ODD;
505 else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) 57 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
506 irq = DISPC_IRQ_EVSYNC_EVEN; 58 irq = DISPC_IRQ_EVSYNC_EVEN;
507 else 59 else
508 irq = dispc_mgr_get_vsync_irq(mgr->id); 60 irq = dispc_mgr_get_vsync_irq(mgr->id);
@@ -547,23 +99,24 @@ int dss_init_overlay_managers(struct platform_device *pdev)
547 break; 99 break;
548 } 100 }
549 101
550 mgr->set_device = &dss_mgr_set_device; 102 mgr->set_output = &dss_mgr_set_output;
551 mgr->unset_device = &dss_mgr_unset_device; 103 mgr->unset_output = &dss_mgr_unset_output;
552 mgr->apply = &omap_dss_mgr_apply; 104 mgr->apply = &omap_dss_mgr_apply;
553 mgr->set_manager_info = &dss_mgr_set_info; 105 mgr->set_manager_info = &dss_mgr_set_info;
554 mgr->get_manager_info = &dss_mgr_get_info; 106 mgr->get_manager_info = &dss_mgr_get_info;
555 mgr->wait_for_go = &dss_mgr_wait_for_go; 107 mgr->wait_for_go = &dss_mgr_wait_for_go;
556 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; 108 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
109 mgr->get_device = &dss_mgr_get_device;
557 110
558 mgr->caps = 0; 111 mgr->caps = 0;
559 mgr->supported_displays = 112 mgr->supported_displays =
560 dss_feat_get_supported_displays(mgr->id); 113 dss_feat_get_supported_displays(mgr->id);
114 mgr->supported_outputs =
115 dss_feat_get_supported_outputs(mgr->id);
561 116
562 INIT_LIST_HEAD(&mgr->overlays); 117 INIT_LIST_HEAD(&mgr->overlays);
563 118
564 r = kobject_init_and_add(&mgr->kobj, &manager_ktype, 119 r = dss_manager_kobj_init(mgr, pdev);
565 &pdev->dev.kobj, "manager%d", i);
566
567 if (r) 120 if (r)
568 DSSERR("failed to create sysfs file\n"); 121 DSSERR("failed to create sysfs file\n");
569 } 122 }
@@ -577,9 +130,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
577 130
578 for (i = 0; i < num_managers; ++i) { 131 for (i = 0; i < num_managers; ++i) {
579 struct omap_overlay_manager *mgr = &managers[i]; 132 struct omap_overlay_manager *mgr = &managers[i];
580 133 dss_manager_kobj_uninit(mgr);
581 kobject_del(&mgr->kobj);
582 kobject_put(&mgr->kobj);
583 } 134 }
584 135
585 kfree(managers); 136 kfree(managers);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
new file mode 100644
index 000000000000..813f26682b7a
--- /dev/null
+++ b/drivers/video/omap2/dss/output.c
@@ -0,0 +1,148 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Ltd
3 * Author: Archit Taneja <archit@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#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23#include <video/omapdss.h>
24
25#include "dss.h"
26
27static LIST_HEAD(output_list);
28static DEFINE_MUTEX(output_lock);
29
30int omapdss_output_set_device(struct omap_dss_output *out,
31 struct omap_dss_device *dssdev)
32{
33 int r;
34
35 mutex_lock(&output_lock);
36
37 if (out->device) {
38 DSSERR("output already has device %s connected to it\n",
39 out->device->name);
40 r = -EINVAL;
41 goto err;
42 }
43
44 if (out->type != dssdev->type) {
45 DSSERR("output type and display type don't match\n");
46 r = -EINVAL;
47 goto err;
48 }
49
50 out->device = dssdev;
51 dssdev->output = out;
52
53 mutex_unlock(&output_lock);
54
55 return 0;
56err:
57 mutex_unlock(&output_lock);
58
59 return r;
60}
61EXPORT_SYMBOL(omapdss_output_set_device);
62
63int omapdss_output_unset_device(struct omap_dss_output *out)
64{
65 int r;
66
67 mutex_lock(&output_lock);
68
69 if (!out->device) {
70 DSSERR("output doesn't have a device connected to it\n");
71 r = -EINVAL;
72 goto err;
73 }
74
75 if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
76 DSSERR("device %s is not disabled, cannot unset device\n",
77 out->device->name);
78 r = -EINVAL;
79 goto err;
80 }
81
82 out->device->output = NULL;
83 out->device = NULL;
84
85 mutex_unlock(&output_lock);
86
87 return 0;
88err:
89 mutex_unlock(&output_lock);
90
91 return r;
92}
93EXPORT_SYMBOL(omapdss_output_unset_device);
94
95void dss_register_output(struct omap_dss_output *out)
96{
97 list_add_tail(&out->list, &output_list);
98}
99
100void dss_unregister_output(struct omap_dss_output *out)
101{
102 list_del(&out->list);
103}
104
105struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
106{
107 struct omap_dss_output *out;
108
109 list_for_each_entry(out, &output_list, list) {
110 if (out->id == id)
111 return out;
112 }
113
114 return NULL;
115}
116
117struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
118{
119 struct omap_dss_output *out = NULL;
120 enum omap_dss_output_id id;
121
122 switch (dssdev->type) {
123 case OMAP_DISPLAY_TYPE_DPI:
124 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
125 break;
126 case OMAP_DISPLAY_TYPE_DBI:
127 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
128 break;
129 case OMAP_DISPLAY_TYPE_SDI:
130 out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
131 break;
132 case OMAP_DISPLAY_TYPE_VENC:
133 out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
134 break;
135 case OMAP_DISPLAY_TYPE_HDMI:
136 out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
137 break;
138 case OMAP_DISPLAY_TYPE_DSI:
139 id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
140 OMAP_DSS_OUTPUT_DSI2;
141 out = omap_dss_get_output(id);
142 break;
143 default:
144 break;
145 }
146
147 return out;
148}
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
new file mode 100644
index 000000000000..4cc5ddebfb34
--- /dev/null
+++ b/drivers/video/omap2/dss/overlay-sysfs.c
@@ -0,0 +1,456 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "OVERLAY"
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/sysfs.h>
26#include <linux/kobject.h>
27#include <linux/platform_device.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
37}
38
39static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n",
42 ovl->manager ? ovl->manager->name : "<none>");
43}
44
45static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
46 size_t size)
47{
48 int i, r;
49 struct omap_overlay_manager *mgr = NULL;
50 struct omap_overlay_manager *old_mgr;
51 int len = size;
52
53 if (buf[size-1] == '\n')
54 --len;
55
56 if (len > 0) {
57 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
58 mgr = omap_dss_get_overlay_manager(i);
59
60 if (sysfs_streq(buf, mgr->name))
61 break;
62
63 mgr = NULL;
64 }
65 }
66
67 if (len > 0 && mgr == NULL)
68 return -EINVAL;
69
70 if (mgr)
71 DSSDBG("manager %s found\n", mgr->name);
72
73 if (mgr == ovl->manager)
74 return size;
75
76 old_mgr = ovl->manager;
77
78 r = dispc_runtime_get();
79 if (r)
80 return r;
81
82 /* detach old manager */
83 if (old_mgr) {
84 r = ovl->unset_manager(ovl);
85 if (r) {
86 DSSERR("detach failed\n");
87 goto err;
88 }
89
90 r = old_mgr->apply(old_mgr);
91 if (r)
92 goto err;
93 }
94
95 if (mgr) {
96 r = ovl->set_manager(ovl, mgr);
97 if (r) {
98 DSSERR("Failed to attach overlay\n");
99 goto err;
100 }
101
102 r = mgr->apply(mgr);
103 if (r)
104 goto err;
105 }
106
107 dispc_runtime_put();
108
109 return size;
110
111err:
112 dispc_runtime_put();
113 return r;
114}
115
116static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
117{
118 struct omap_overlay_info info;
119
120 ovl->get_overlay_info(ovl, &info);
121
122 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
123 info.width, info.height);
124}
125
126static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
127{
128 struct omap_overlay_info info;
129
130 ovl->get_overlay_info(ovl, &info);
131
132 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
133}
134
135static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
142 info.pos_x, info.pos_y);
143}
144
145static ssize_t overlay_position_store(struct omap_overlay *ovl,
146 const char *buf, size_t size)
147{
148 int r;
149 char *last;
150 struct omap_overlay_info info;
151
152 ovl->get_overlay_info(ovl, &info);
153
154 info.pos_x = simple_strtoul(buf, &last, 10);
155 ++last;
156 if (last - buf >= size)
157 return -EINVAL;
158
159 info.pos_y = simple_strtoul(last, &last, 10);
160
161 r = ovl->set_overlay_info(ovl, &info);
162 if (r)
163 return r;
164
165 if (ovl->manager) {
166 r = ovl->manager->apply(ovl->manager);
167 if (r)
168 return r;
169 }
170
171 return size;
172}
173
174static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
175{
176 struct omap_overlay_info info;
177
178 ovl->get_overlay_info(ovl, &info);
179
180 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
181 info.out_width, info.out_height);
182}
183
184static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
185 const char *buf, size_t size)
186{
187 int r;
188 char *last;
189 struct omap_overlay_info info;
190
191 ovl->get_overlay_info(ovl, &info);
192
193 info.out_width = simple_strtoul(buf, &last, 10);
194 ++last;
195 if (last - buf >= size)
196 return -EINVAL;
197
198 info.out_height = simple_strtoul(last, &last, 10);
199
200 r = ovl->set_overlay_info(ovl, &info);
201 if (r)
202 return r;
203
204 if (ovl->manager) {
205 r = ovl->manager->apply(ovl->manager);
206 if (r)
207 return r;
208 }
209
210 return size;
211}
212
213static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
214{
215 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
216}
217
218static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
219 size_t size)
220{
221 int r;
222 bool enable;
223
224 r = strtobool(buf, &enable);
225 if (r)
226 return r;
227
228 if (enable)
229 r = ovl->enable(ovl);
230 else
231 r = ovl->disable(ovl);
232
233 if (r)
234 return r;
235
236 return size;
237}
238
239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240{
241 struct omap_overlay_info info;
242
243 ovl->get_overlay_info(ovl, &info);
244
245 return snprintf(buf, PAGE_SIZE, "%d\n",
246 info.global_alpha);
247}
248
249static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
250 const char *buf, size_t size)
251{
252 int r;
253 u8 alpha;
254 struct omap_overlay_info info;
255
256 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
257 return -ENODEV;
258
259 r = kstrtou8(buf, 0, &alpha);
260 if (r)
261 return r;
262
263 ovl->get_overlay_info(ovl, &info);
264
265 info.global_alpha = alpha;
266
267 r = ovl->set_overlay_info(ovl, &info);
268 if (r)
269 return r;
270
271 if (ovl->manager) {
272 r = ovl->manager->apply(ovl->manager);
273 if (r)
274 return r;
275 }
276
277 return size;
278}
279
280static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
281 char *buf)
282{
283 struct omap_overlay_info info;
284
285 ovl->get_overlay_info(ovl, &info);
286
287 return snprintf(buf, PAGE_SIZE, "%d\n",
288 info.pre_mult_alpha);
289}
290
291static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
292 const char *buf, size_t size)
293{
294 int r;
295 u8 alpha;
296 struct omap_overlay_info info;
297
298 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
299 return -ENODEV;
300
301 r = kstrtou8(buf, 0, &alpha);
302 if (r)
303 return r;
304
305 ovl->get_overlay_info(ovl, &info);
306
307 info.pre_mult_alpha = alpha;
308
309 r = ovl->set_overlay_info(ovl, &info);
310 if (r)
311 return r;
312
313 if (ovl->manager) {
314 r = ovl->manager->apply(ovl->manager);
315 if (r)
316 return r;
317 }
318
319 return size;
320}
321
322static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
323{
324 struct omap_overlay_info info;
325
326 ovl->get_overlay_info(ovl, &info);
327
328 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
329}
330
331static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
332 const char *buf, size_t size)
333{
334 int r;
335 u8 zorder;
336 struct omap_overlay_info info;
337
338 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
339 return -ENODEV;
340
341 r = kstrtou8(buf, 0, &zorder);
342 if (r)
343 return r;
344
345 ovl->get_overlay_info(ovl, &info);
346
347 info.zorder = zorder;
348
349 r = ovl->set_overlay_info(ovl, &info);
350 if (r)
351 return r;
352
353 if (ovl->manager) {
354 r = ovl->manager->apply(ovl->manager);
355 if (r)
356 return r;
357 }
358
359 return size;
360}
361
362struct overlay_attribute {
363 struct attribute attr;
364 ssize_t (*show)(struct omap_overlay *, char *);
365 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
366};
367
368#define OVERLAY_ATTR(_name, _mode, _show, _store) \
369 struct overlay_attribute overlay_attr_##_name = \
370 __ATTR(_name, _mode, _show, _store)
371
372static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
373static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
374 overlay_manager_show, overlay_manager_store);
375static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
376static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
377static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
378 overlay_position_show, overlay_position_store);
379static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
380 overlay_output_size_show, overlay_output_size_store);
381static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
382 overlay_enabled_show, overlay_enabled_store);
383static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
384 overlay_global_alpha_show, overlay_global_alpha_store);
385static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
386 overlay_pre_mult_alpha_show,
387 overlay_pre_mult_alpha_store);
388static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
389 overlay_zorder_show, overlay_zorder_store);
390
391static struct attribute *overlay_sysfs_attrs[] = {
392 &overlay_attr_name.attr,
393 &overlay_attr_manager.attr,
394 &overlay_attr_input_size.attr,
395 &overlay_attr_screen_width.attr,
396 &overlay_attr_position.attr,
397 &overlay_attr_output_size.attr,
398 &overlay_attr_enabled.attr,
399 &overlay_attr_global_alpha.attr,
400 &overlay_attr_pre_mult_alpha.attr,
401 &overlay_attr_zorder.attr,
402 NULL
403};
404
405static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
406 char *buf)
407{
408 struct omap_overlay *overlay;
409 struct overlay_attribute *overlay_attr;
410
411 overlay = container_of(kobj, struct omap_overlay, kobj);
412 overlay_attr = container_of(attr, struct overlay_attribute, attr);
413
414 if (!overlay_attr->show)
415 return -ENOENT;
416
417 return overlay_attr->show(overlay, buf);
418}
419
420static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
421 const char *buf, size_t size)
422{
423 struct omap_overlay *overlay;
424 struct overlay_attribute *overlay_attr;
425
426 overlay = container_of(kobj, struct omap_overlay, kobj);
427 overlay_attr = container_of(attr, struct overlay_attribute, attr);
428
429 if (!overlay_attr->store)
430 return -ENOENT;
431
432 return overlay_attr->store(overlay, buf, size);
433}
434
435static const struct sysfs_ops overlay_sysfs_ops = {
436 .show = overlay_attr_show,
437 .store = overlay_attr_store,
438};
439
440static struct kobj_type overlay_ktype = {
441 .sysfs_ops = &overlay_sysfs_ops,
442 .default_attrs = overlay_sysfs_attrs,
443};
444
445int dss_overlay_kobj_init(struct omap_overlay *ovl,
446 struct platform_device *pdev)
447{
448 return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
449 &pdev->dev.kobj, "overlay%d", ovl->id);
450}
451
452void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
453{
454 kobject_del(&ovl->kobj);
455 kobject_put(&ovl->kobj);
456}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 952c6fad9a81..45f4994bc6b0 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -26,13 +26,11 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/sysfs.h> 28#include <linux/sysfs.h>
29#include <linux/kobject.h>
30#include <linux/platform_device.h> 29#include <linux/platform_device.h>
31#include <linux/delay.h> 30#include <linux/delay.h>
32#include <linux/slab.h> 31#include <linux/slab.h>
33 32
34#include <video/omapdss.h> 33#include <video/omapdss.h>
35#include <plat/cpu.h>
36 34
37#include "dss.h" 35#include "dss.h"
38#include "dss_features.h" 36#include "dss_features.h"
@@ -40,417 +38,13 @@
40static int num_overlays; 38static int num_overlays;
41static struct omap_overlay *overlays; 39static struct omap_overlay *overlays;
42 40
43static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) 41static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
44{ 42{
45 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); 43 return ovl->manager ?
44 (ovl->manager->output ? ovl->manager->output->device : NULL) :
45 NULL;
46} 46}
47 47
48static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
49{
50 return snprintf(buf, PAGE_SIZE, "%s\n",
51 ovl->manager ? ovl->manager->name : "<none>");
52}
53
54static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
55 size_t size)
56{
57 int i, r;
58 struct omap_overlay_manager *mgr = NULL;
59 struct omap_overlay_manager *old_mgr;
60 int len = size;
61
62 if (buf[size-1] == '\n')
63 --len;
64
65 if (len > 0) {
66 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
67 mgr = omap_dss_get_overlay_manager(i);
68
69 if (sysfs_streq(buf, mgr->name))
70 break;
71
72 mgr = NULL;
73 }
74 }
75
76 if (len > 0 && mgr == NULL)
77 return -EINVAL;
78
79 if (mgr)
80 DSSDBG("manager %s found\n", mgr->name);
81
82 if (mgr == ovl->manager)
83 return size;
84
85 old_mgr = ovl->manager;
86
87 r = dispc_runtime_get();
88 if (r)
89 return r;
90
91 /* detach old manager */
92 if (old_mgr) {
93 r = ovl->unset_manager(ovl);
94 if (r) {
95 DSSERR("detach failed\n");
96 goto err;
97 }
98
99 r = old_mgr->apply(old_mgr);
100 if (r)
101 goto err;
102 }
103
104 if (mgr) {
105 r = ovl->set_manager(ovl, mgr);
106 if (r) {
107 DSSERR("Failed to attach overlay\n");
108 goto err;
109 }
110
111 r = mgr->apply(mgr);
112 if (r)
113 goto err;
114 }
115
116 dispc_runtime_put();
117
118 return size;
119
120err:
121 dispc_runtime_put();
122 return r;
123}
124
125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
126{
127 struct omap_overlay_info info;
128
129 ovl->get_overlay_info(ovl, &info);
130
131 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
132 info.width, info.height);
133}
134
135static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
142}
143
144static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
145{
146 struct omap_overlay_info info;
147
148 ovl->get_overlay_info(ovl, &info);
149
150 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
151 info.pos_x, info.pos_y);
152}
153
154static ssize_t overlay_position_store(struct omap_overlay *ovl,
155 const char *buf, size_t size)
156{
157 int r;
158 char *last;
159 struct omap_overlay_info info;
160
161 ovl->get_overlay_info(ovl, &info);
162
163 info.pos_x = simple_strtoul(buf, &last, 10);
164 ++last;
165 if (last - buf >= size)
166 return -EINVAL;
167
168 info.pos_y = simple_strtoul(last, &last, 10);
169
170 r = ovl->set_overlay_info(ovl, &info);
171 if (r)
172 return r;
173
174 if (ovl->manager) {
175 r = ovl->manager->apply(ovl->manager);
176 if (r)
177 return r;
178 }
179
180 return size;
181}
182
183static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
184{
185 struct omap_overlay_info info;
186
187 ovl->get_overlay_info(ovl, &info);
188
189 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
190 info.out_width, info.out_height);
191}
192
193static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
194 const char *buf, size_t size)
195{
196 int r;
197 char *last;
198 struct omap_overlay_info info;
199
200 ovl->get_overlay_info(ovl, &info);
201
202 info.out_width = simple_strtoul(buf, &last, 10);
203 ++last;
204 if (last - buf >= size)
205 return -EINVAL;
206
207 info.out_height = simple_strtoul(last, &last, 10);
208
209 r = ovl->set_overlay_info(ovl, &info);
210 if (r)
211 return r;
212
213 if (ovl->manager) {
214 r = ovl->manager->apply(ovl->manager);
215 if (r)
216 return r;
217 }
218
219 return size;
220}
221
222static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
223{
224 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
225}
226
227static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
228 size_t size)
229{
230 int r;
231 bool enable;
232
233 r = strtobool(buf, &enable);
234 if (r)
235 return r;
236
237 if (enable)
238 r = ovl->enable(ovl);
239 else
240 r = ovl->disable(ovl);
241
242 if (r)
243 return r;
244
245 return size;
246}
247
248static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
249{
250 struct omap_overlay_info info;
251
252 ovl->get_overlay_info(ovl, &info);
253
254 return snprintf(buf, PAGE_SIZE, "%d\n",
255 info.global_alpha);
256}
257
258static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
259 const char *buf, size_t size)
260{
261 int r;
262 u8 alpha;
263 struct omap_overlay_info info;
264
265 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
266 return -ENODEV;
267
268 r = kstrtou8(buf, 0, &alpha);
269 if (r)
270 return r;
271
272 ovl->get_overlay_info(ovl, &info);
273
274 info.global_alpha = alpha;
275
276 r = ovl->set_overlay_info(ovl, &info);
277 if (r)
278 return r;
279
280 if (ovl->manager) {
281 r = ovl->manager->apply(ovl->manager);
282 if (r)
283 return r;
284 }
285
286 return size;
287}
288
289static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
290 char *buf)
291{
292 struct omap_overlay_info info;
293
294 ovl->get_overlay_info(ovl, &info);
295
296 return snprintf(buf, PAGE_SIZE, "%d\n",
297 info.pre_mult_alpha);
298}
299
300static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
301 const char *buf, size_t size)
302{
303 int r;
304 u8 alpha;
305 struct omap_overlay_info info;
306
307 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
308 return -ENODEV;
309
310 r = kstrtou8(buf, 0, &alpha);
311 if (r)
312 return r;
313
314 ovl->get_overlay_info(ovl, &info);
315
316 info.pre_mult_alpha = alpha;
317
318 r = ovl->set_overlay_info(ovl, &info);
319 if (r)
320 return r;
321
322 if (ovl->manager) {
323 r = ovl->manager->apply(ovl->manager);
324 if (r)
325 return r;
326 }
327
328 return size;
329}
330
331static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
332{
333 struct omap_overlay_info info;
334
335 ovl->get_overlay_info(ovl, &info);
336
337 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
338}
339
340static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
341 const char *buf, size_t size)
342{
343 int r;
344 u8 zorder;
345 struct omap_overlay_info info;
346
347 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
348 return -ENODEV;
349
350 r = kstrtou8(buf, 0, &zorder);
351 if (r)
352 return r;
353
354 ovl->get_overlay_info(ovl, &info);
355
356 info.zorder = zorder;
357
358 r = ovl->set_overlay_info(ovl, &info);
359 if (r)
360 return r;
361
362 if (ovl->manager) {
363 r = ovl->manager->apply(ovl->manager);
364 if (r)
365 return r;
366 }
367
368 return size;
369}
370
371struct overlay_attribute {
372 struct attribute attr;
373 ssize_t (*show)(struct omap_overlay *, char *);
374 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
375};
376
377#define OVERLAY_ATTR(_name, _mode, _show, _store) \
378 struct overlay_attribute overlay_attr_##_name = \
379 __ATTR(_name, _mode, _show, _store)
380
381static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
382static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
383 overlay_manager_show, overlay_manager_store);
384static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
385static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
386static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
387 overlay_position_show, overlay_position_store);
388static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
389 overlay_output_size_show, overlay_output_size_store);
390static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
391 overlay_enabled_show, overlay_enabled_store);
392static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
393 overlay_global_alpha_show, overlay_global_alpha_store);
394static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
395 overlay_pre_mult_alpha_show,
396 overlay_pre_mult_alpha_store);
397static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
398 overlay_zorder_show, overlay_zorder_store);
399
400static struct attribute *overlay_sysfs_attrs[] = {
401 &overlay_attr_name.attr,
402 &overlay_attr_manager.attr,
403 &overlay_attr_input_size.attr,
404 &overlay_attr_screen_width.attr,
405 &overlay_attr_position.attr,
406 &overlay_attr_output_size.attr,
407 &overlay_attr_enabled.attr,
408 &overlay_attr_global_alpha.attr,
409 &overlay_attr_pre_mult_alpha.attr,
410 &overlay_attr_zorder.attr,
411 NULL
412};
413
414static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
415 char *buf)
416{
417 struct omap_overlay *overlay;
418 struct overlay_attribute *overlay_attr;
419
420 overlay = container_of(kobj, struct omap_overlay, kobj);
421 overlay_attr = container_of(attr, struct overlay_attribute, attr);
422
423 if (!overlay_attr->show)
424 return -ENOENT;
425
426 return overlay_attr->show(overlay, buf);
427}
428
429static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
430 const char *buf, size_t size)
431{
432 struct omap_overlay *overlay;
433 struct overlay_attribute *overlay_attr;
434
435 overlay = container_of(kobj, struct omap_overlay, kobj);
436 overlay_attr = container_of(attr, struct overlay_attribute, attr);
437
438 if (!overlay_attr->store)
439 return -ENOENT;
440
441 return overlay_attr->store(overlay, buf, size);
442}
443
444static const struct sysfs_ops overlay_sysfs_ops = {
445 .show = overlay_attr_show,
446 .store = overlay_attr_store,
447};
448
449static struct kobj_type overlay_ktype = {
450 .sysfs_ops = &overlay_sysfs_ops,
451 .default_attrs = overlay_sysfs_attrs,
452};
453
454int omap_dss_get_num_overlays(void) 48int omap_dss_get_num_overlays(void)
455{ 49{
456 return num_overlays; 50 return num_overlays;
@@ -507,97 +101,25 @@ void dss_init_overlays(struct platform_device *pdev)
507 ovl->set_overlay_info = &dss_ovl_set_info; 101 ovl->set_overlay_info = &dss_ovl_set_info;
508 ovl->get_overlay_info = &dss_ovl_get_info; 102 ovl->get_overlay_info = &dss_ovl_get_info;
509 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; 103 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
104 ovl->get_device = &dss_ovl_get_device;
510 105
511 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 106 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
512 ovl->supported_modes = 107 ovl->supported_modes =
513 dss_feat_get_supported_color_modes(ovl->id); 108 dss_feat_get_supported_color_modes(ovl->id);
514 109
515 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 110 r = dss_overlay_kobj_init(ovl, pdev);
516 &pdev->dev.kobj, "overlay%d", i);
517
518 if (r) 111 if (r)
519 DSSERR("failed to create sysfs file\n"); 112 DSSERR("failed to create sysfs file\n");
520 } 113 }
521} 114}
522 115
523/* connect overlays to the new device, if not already connected. if force
524 * selected, connect always. */
525void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
526{
527 int i;
528 struct omap_overlay_manager *lcd_mgr;
529 struct omap_overlay_manager *tv_mgr;
530 struct omap_overlay_manager *lcd2_mgr = NULL;
531 struct omap_overlay_manager *lcd3_mgr = NULL;
532 struct omap_overlay_manager *mgr = NULL;
533
534 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
535 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
536 if (dss_has_feature(FEAT_MGR_LCD3))
537 lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
538 if (dss_has_feature(FEAT_MGR_LCD2))
539 lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
540
541 if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
542 if (!lcd3_mgr->device || force) {
543 if (lcd3_mgr->device)
544 lcd3_mgr->unset_device(lcd3_mgr);
545 lcd3_mgr->set_device(lcd3_mgr, dssdev);
546 mgr = lcd3_mgr;
547 }
548 } else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
549 if (!lcd2_mgr->device || force) {
550 if (lcd2_mgr->device)
551 lcd2_mgr->unset_device(lcd2_mgr);
552 lcd2_mgr->set_device(lcd2_mgr, dssdev);
553 mgr = lcd2_mgr;
554 }
555 } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
556 && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
557 if (!lcd_mgr->device || force) {
558 if (lcd_mgr->device)
559 lcd_mgr->unset_device(lcd_mgr);
560 lcd_mgr->set_device(lcd_mgr, dssdev);
561 mgr = lcd_mgr;
562 }
563 }
564
565 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
566 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
567 if (!tv_mgr->device || force) {
568 if (tv_mgr->device)
569 tv_mgr->unset_device(tv_mgr);
570 tv_mgr->set_device(tv_mgr, dssdev);
571 mgr = tv_mgr;
572 }
573 }
574
575 if (mgr) {
576 dispc_runtime_get();
577
578 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
579 struct omap_overlay *ovl;
580 ovl = omap_dss_get_overlay(i);
581 if (!ovl->manager || force) {
582 if (ovl->manager)
583 ovl->unset_manager(ovl);
584 ovl->set_manager(ovl, mgr);
585 }
586 }
587
588 dispc_runtime_put();
589 }
590}
591
592void dss_uninit_overlays(struct platform_device *pdev) 116void dss_uninit_overlays(struct platform_device *pdev)
593{ 117{
594 int i; 118 int i;
595 119
596 for (i = 0; i < num_overlays; ++i) { 120 for (i = 0; i < num_overlays; ++i) {
597 struct omap_overlay *ovl = &overlays[i]; 121 struct omap_overlay *ovl = &overlays[i];
598 122 dss_overlay_kobj_uninit(ovl);
599 kobject_del(&ovl->kobj);
600 kobject_put(&ovl->kobj);
601 } 123 }
602 124
603 kfree(overlays); 125 kfree(overlays);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7c087424b634..7282e5af3e1a 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -111,6 +111,13 @@ static struct {
111 struct omap_dss_device *dssdev[2]; 111 struct omap_dss_device *dssdev[2];
112 112
113 struct semaphore bus_lock; 113 struct semaphore bus_lock;
114
115 struct omap_video_timings timings;
116 int pixel_size;
117 int data_lines;
118 struct rfbi_timings intf_timings;
119
120 struct omap_dss_output output;
114} rfbi; 121} rfbi;
115 122
116static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 123static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
300} 307}
301EXPORT_SYMBOL(omap_rfbi_write_pixels); 308EXPORT_SYMBOL(omap_rfbi_write_pixels);
302 309
303static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, 310static int rfbi_transfer_area(struct omap_dss_device *dssdev,
304 u16 height, void (*callback)(void *data), void *data) 311 void (*callback)(void *data), void *data)
305{ 312{
306 u32 l; 313 u32 l;
307 int r; 314 int r;
308 struct omap_video_timings timings = { 315 struct omap_overlay_manager *mgr = dssdev->output->manager;
309 .hsw = 1, 316 u16 width = rfbi.timings.x_res;
310 .hfp = 1, 317 u16 height = rfbi.timings.y_res;
311 .hbp = 1,
312 .vsw = 1,
313 .vfp = 0,
314 .vbp = 0,
315 .x_res = width,
316 .y_res = height,
317 };
318 318
319 /*BUG_ON(callback == 0);*/ 319 /*BUG_ON(callback == 0);*/
320 BUG_ON(rfbi.framedone_callback != NULL); 320 BUG_ON(rfbi.framedone_callback != NULL);
321 321
322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
323 323
324 dss_mgr_set_timings(dssdev->manager, &timings); 324 dss_mgr_set_timings(mgr, &rfbi.timings);
325 325
326 r = dss_mgr_enable(dssdev->manager); 326 r = dss_mgr_enable(mgr);
327 if (r) 327 if (r)
328 return r; 328 return r;
329 329
@@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
770 return 0; 770 return 0;
771} 771}
772 772
773int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, 773int omap_rfbi_configure(struct omap_dss_device *dssdev)
774 int data_lines)
775{ 774{
776 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); 775 return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
776 rfbi.data_lines);
777} 777}
778EXPORT_SYMBOL(omap_rfbi_configure); 778EXPORT_SYMBOL(omap_rfbi_configure);
779 779
780int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, 780int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
781 u16 *x, u16 *y, u16 *w, u16 *h) 781 void *data)
782{ 782{
783 u16 dw, dh; 783 return rfbi_transfer_area(dssdev, callback, data);
784 struct omap_video_timings timings = { 784}
785 .hsw = 1, 785EXPORT_SYMBOL(omap_rfbi_update);
786 .hfp = 1,
787 .hbp = 1,
788 .vsw = 1,
789 .vfp = 0,
790 .vbp = 0,
791 .x_res = *w,
792 .y_res = *h,
793 };
794
795 dssdev->driver->get_resolution(dssdev, &dw, &dh);
796
797 if (*x > dw || *y > dh)
798 return -EINVAL;
799
800 if (*x + *w > dw)
801 return -EINVAL;
802
803 if (*y + *h > dh)
804 return -EINVAL;
805
806 if (*w == 1)
807 return -EINVAL;
808
809 if (*w == 0 || *h == 0)
810 return -EINVAL;
811
812 dss_mgr_set_timings(dssdev->manager, &timings);
813 786
814 return 0; 787void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
788{
789 rfbi.timings.x_res = w;
790 rfbi.timings.y_res = h;
815} 791}
816EXPORT_SYMBOL(omap_rfbi_prepare_update); 792EXPORT_SYMBOL(omapdss_rfbi_set_size);
817 793
818int omap_rfbi_update(struct omap_dss_device *dssdev, 794void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
819 u16 x, u16 y, u16 w, u16 h,
820 void (*callback)(void *), void *data)
821{ 795{
822 int r; 796 rfbi.pixel_size = pixel_size;
797}
798EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
823 799
824 r = rfbi_transfer_area(dssdev, w, h, callback, data); 800void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
801{
802 rfbi.data_lines = data_lines;
803}
804EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
825 805
826 return r; 806void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
807 struct rfbi_timings *timings)
808{
809 rfbi.intf_timings = *timings;
827} 810}
828EXPORT_SYMBOL(omap_rfbi_update); 811EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
829 812
830static void rfbi_dump_regs(struct seq_file *s) 813static void rfbi_dump_regs(struct seq_file *s)
831{ 814{
@@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)
869 852
870static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) 853static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
871{ 854{
855 struct omap_overlay_manager *mgr = dssdev->output->manager;
872 struct dss_lcd_mgr_config mgr_config; 856 struct dss_lcd_mgr_config mgr_config;
873 857
874 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; 858 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
@@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
877 /* Do we need fifohandcheck for RFBI? */ 861 /* Do we need fifohandcheck for RFBI? */
878 mgr_config.fifohandcheck = false; 862 mgr_config.fifohandcheck = false;
879 863
880 mgr_config.video_port_width = dssdev->ctrl.pixel_size; 864 mgr_config.video_port_width = rfbi.pixel_size;
881 mgr_config.lcden_sig_polarity = 0; 865 mgr_config.lcden_sig_polarity = 0;
882 866
883 dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); 867 dss_mgr_set_lcd_config(mgr, &mgr_config);
868
869 /*
870 * Set rfbi.timings with default values, the x_res and y_res fields
871 * are expected to be already configured by the panel driver via
872 * omapdss_rfbi_set_size()
873 */
874 rfbi.timings.hsw = 1;
875 rfbi.timings.hfp = 1;
876 rfbi.timings.hbp = 1;
877 rfbi.timings.vsw = 1;
878 rfbi.timings.vfp = 0;
879 rfbi.timings.vbp = 0;
880
881 rfbi.timings.interlace = false;
882 rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
883 rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
884 rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
885 rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
886 rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
887
888 dss_mgr_set_timings(mgr, &rfbi.timings);
884} 889}
885 890
886int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 891int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
887{ 892{
893 struct omap_dss_output *out = dssdev->output;
888 int r; 894 int r;
889 895
890 if (dssdev->manager == NULL) { 896 if (out == NULL || out->manager == NULL) {
891 DSSERR("failed to enable display: no manager\n"); 897 DSSERR("failed to enable display: no output/manager\n");
892 return -ENODEV; 898 return -ENODEV;
893 } 899 }
894 900
@@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
911 917
912 rfbi_config_lcd_manager(dssdev); 918 rfbi_config_lcd_manager(dssdev);
913 919
914 rfbi_configure(dssdev->phy.rfbi.channel, 920 rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
915 dssdev->ctrl.pixel_size, 921 rfbi.data_lines);
916 dssdev->phy.rfbi.data_lines);
917
918 rfbi_set_timings(dssdev->phy.rfbi.channel,
919 &dssdev->ctrl.rfbi_timings);
920 922
923 rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
921 924
922 return 0; 925 return 0;
923err1: 926err1:
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
941static int __init rfbi_init_display(struct omap_dss_device *dssdev) 944static int __init rfbi_init_display(struct omap_dss_device *dssdev)
942{ 945{
943 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 946 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
944 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
945 return 0; 947 return 0;
946} 948}
947 949
948static void __init rfbi_probe_pdata(struct platform_device *pdev) 950static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
949{ 951{
950 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 952 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
951 int i, r; 953 const char *def_disp_name = dss_get_default_display_name();
954 struct omap_dss_device *def_dssdev;
955 int i;
956
957 def_dssdev = NULL;
952 958
953 for (i = 0; i < pdata->num_devices; ++i) { 959 for (i = 0; i < pdata->num_devices; ++i) {
954 struct omap_dss_device *dssdev = pdata->devices[i]; 960 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
956 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) 962 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
957 continue; 963 continue;
958 964
959 r = rfbi_init_display(dssdev); 965 if (def_dssdev == NULL)
960 if (r) { 966 def_dssdev = dssdev;
961 DSSERR("device %s init failed: %d\n", dssdev->name, r); 967
962 continue; 968 if (def_disp_name != NULL &&
969 strcmp(dssdev->name, def_disp_name) == 0) {
970 def_dssdev = dssdev;
971 break;
963 } 972 }
973 }
974
975 return def_dssdev;
976}
977
978static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
979{
980 struct omap_dss_device *plat_dssdev;
981 struct omap_dss_device *dssdev;
982 int r;
983
984 plat_dssdev = rfbi_find_dssdev(rfbidev);
985
986 if (!plat_dssdev)
987 return;
988
989 dssdev = dss_alloc_and_init_device(&rfbidev->dev);
990 if (!dssdev)
991 return;
992
993 dss_copy_device_pdata(dssdev, plat_dssdev);
964 994
965 r = omap_dss_register_device(dssdev, &pdev->dev, i); 995 r = rfbi_init_display(dssdev);
966 if (r) 996 if (r) {
967 DSSERR("device %s register failed: %d\n", 997 DSSERR("device %s init failed: %d\n", dssdev->name, r);
968 dssdev->name, r); 998 dss_put_device(dssdev);
999 return;
969 } 1000 }
1001
1002 r = dss_add_device(dssdev);
1003 if (r) {
1004 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1005 dss_put_device(dssdev);
1006 return;
1007 }
1008}
1009
1010static void __init rfbi_init_output(struct platform_device *pdev)
1011{
1012 struct omap_dss_output *out = &rfbi.output;
1013
1014 out->pdev = pdev;
1015 out->id = OMAP_DSS_OUTPUT_DBI;
1016 out->type = OMAP_DISPLAY_TYPE_DBI;
1017
1018 dss_register_output(out);
1019}
1020
1021static void __exit rfbi_uninit_output(struct platform_device *pdev)
1022{
1023 struct omap_dss_output *out = &rfbi.output;
1024
1025 dss_unregister_output(out);
970} 1026}
971 1027
972/* RFBI HW IP initialisation */ 1028/* RFBI HW IP initialisation */
@@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
1020 1076
1021 dss_debugfs_create_file("rfbi", rfbi_dump_regs); 1077 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1022 1078
1079 rfbi_init_output(pdev);
1080
1023 rfbi_probe_pdata(pdev); 1081 rfbi_probe_pdata(pdev);
1024 1082
1025 return 0; 1083 return 0;
@@ -1031,8 +1089,12 @@ err_runtime_get:
1031 1089
1032static int __exit omap_rfbihw_remove(struct platform_device *pdev) 1090static int __exit omap_rfbihw_remove(struct platform_device *pdev)
1033{ 1091{
1034 omap_dss_unregister_child_devices(&pdev->dev); 1092 dss_unregister_child_devices(&pdev->dev);
1093
1094 rfbi_uninit_output(pdev);
1095
1035 pm_runtime_disable(&pdev->dev); 1096 pm_runtime_disable(&pdev->dev);
1097
1036 return 0; 1098 return 0;
1037} 1099}
1038 1100
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index f43bfe17b3b6..7760851f6e5d 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -25,6 +25,7 @@
25#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
26#include <linux/export.h> 26#include <linux/export.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/string.h>
28 29
29#include <video/omapdss.h> 30#include <video/omapdss.h>
30#include "dss.h" 31#include "dss.h"
@@ -34,10 +35,16 @@ static struct {
34 struct regulator *vdds_sdi_reg; 35 struct regulator *vdds_sdi_reg;
35 36
36 struct dss_lcd_mgr_config mgr_config; 37 struct dss_lcd_mgr_config mgr_config;
38 struct omap_video_timings timings;
39 int datapairs;
40
41 struct omap_dss_output output;
37} sdi; 42} sdi;
38 43
39static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) 44static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
40{ 45{
46 struct omap_overlay_manager *mgr = dssdev->output->manager;
47
41 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 48 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
42 49
43 sdi.mgr_config.stallmode = false; 50 sdi.mgr_config.stallmode = false;
@@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
46 sdi.mgr_config.video_port_width = 24; 53 sdi.mgr_config.video_port_width = 24;
47 sdi.mgr_config.lcden_sig_polarity = 1; 54 sdi.mgr_config.lcden_sig_polarity = 1;
48 55
49 dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config); 56 dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
50} 57}
51 58
52int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) 59int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
53{ 60{
54 struct omap_video_timings *t = &dssdev->panel.timings; 61 struct omap_dss_output *out = dssdev->output;
62 struct omap_video_timings *t = &sdi.timings;
55 struct dss_clock_info dss_cinfo; 63 struct dss_clock_info dss_cinfo;
56 struct dispc_clock_info dispc_cinfo; 64 struct dispc_clock_info dispc_cinfo;
57 unsigned long pck; 65 unsigned long pck;
58 int r; 66 int r;
59 67
60 if (dssdev->manager == NULL) { 68 if (out == NULL || out->manager == NULL) {
61 DSSERR("failed to enable display: no manager\n"); 69 DSSERR("failed to enable display: no output/manager\n");
62 return -ENODEV; 70 return -ENODEV;
63 } 71 }
64 72
@@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
77 goto err_get_dispc; 85 goto err_get_dispc;
78 86
79 /* 15.5.9.1.2 */ 87 /* 15.5.9.1.2 */
80 dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 88 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
81 dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 89 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
82 90
83 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); 91 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
84 if (r) 92 if (r)
@@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
97 } 105 }
98 106
99 107
100 dss_mgr_set_timings(dssdev->manager, t); 108 dss_mgr_set_timings(out->manager, t);
101 109
102 r = dss_set_clock_div(&dss_cinfo); 110 r = dss_set_clock_div(&dss_cinfo);
103 if (r) 111 if (r)
@@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
116 * need to care about the shadow register mechanism for pck-free. The 124 * need to care about the shadow register mechanism for pck-free. The
117 * exact reason for this is unknown. 125 * exact reason for this is unknown.
118 */ 126 */
119 dispc_mgr_set_clock_div(dssdev->manager->id, 127 dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
120 &sdi.mgr_config.clock_info);
121 128
122 dss_sdi_init(dssdev->phy.sdi.datapairs); 129 dss_sdi_init(sdi.datapairs);
123 r = dss_sdi_enable(); 130 r = dss_sdi_enable();
124 if (r) 131 if (r)
125 goto err_sdi_enable; 132 goto err_sdi_enable;
126 mdelay(2); 133 mdelay(2);
127 134
128 r = dss_mgr_enable(dssdev->manager); 135 r = dss_mgr_enable(out->manager);
129 if (r) 136 if (r)
130 goto err_mgr_enable; 137 goto err_mgr_enable;
131 138
@@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
148 155
149void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 156void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
150{ 157{
151 dss_mgr_disable(dssdev->manager); 158 struct omap_overlay_manager *mgr = dssdev->output->manager;
159
160 dss_mgr_disable(mgr);
152 161
153 dss_sdi_disable(); 162 dss_sdi_disable();
154 163
@@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
160} 169}
161EXPORT_SYMBOL(omapdss_sdi_display_disable); 170EXPORT_SYMBOL(omapdss_sdi_display_disable);
162 171
172void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
173 struct omap_video_timings *timings)
174{
175 sdi.timings = *timings;
176}
177EXPORT_SYMBOL(omapdss_sdi_set_timings);
178
179void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
180{
181 sdi.datapairs = datapairs;
182}
183EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
184
163static int __init sdi_init_display(struct omap_dss_device *dssdev) 185static int __init sdi_init_display(struct omap_dss_device *dssdev)
164{ 186{
165 DSSDBG("SDI init\n"); 187 DSSDBG("SDI init\n");
@@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
180 return 0; 202 return 0;
181} 203}
182 204
183static void __init sdi_probe_pdata(struct platform_device *pdev) 205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
184{ 206{
185 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 207 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
186 int i, r; 208 const char *def_disp_name = dss_get_default_display_name();
209 struct omap_dss_device *def_dssdev;
210 int i;
211
212 def_dssdev = NULL;
187 213
188 for (i = 0; i < pdata->num_devices; ++i) { 214 for (i = 0; i < pdata->num_devices; ++i) {
189 struct omap_dss_device *dssdev = pdata->devices[i]; 215 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
191 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) 217 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
192 continue; 218 continue;
193 219
194 r = sdi_init_display(dssdev); 220 if (def_dssdev == NULL)
195 if (r) { 221 def_dssdev = dssdev;
196 DSSERR("device %s init failed: %d\n", dssdev->name, r); 222
197 continue; 223 if (def_disp_name != NULL &&
224 strcmp(dssdev->name, def_disp_name) == 0) {
225 def_dssdev = dssdev;
226 break;
198 } 227 }
228 }
229
230 return def_dssdev;
231}
232
233static void __init sdi_probe_pdata(struct platform_device *sdidev)
234{
235 struct omap_dss_device *plat_dssdev;
236 struct omap_dss_device *dssdev;
237 int r;
238
239 plat_dssdev = sdi_find_dssdev(sdidev);
199 240
200 r = omap_dss_register_device(dssdev, &pdev->dev, i); 241 if (!plat_dssdev)
201 if (r) 242 return;
202 DSSERR("device %s register failed: %d\n", 243
203 dssdev->name, r); 244 dssdev = dss_alloc_and_init_device(&sdidev->dev);
245 if (!dssdev)
246 return;
247
248 dss_copy_device_pdata(dssdev, plat_dssdev);
249
250 r = sdi_init_display(dssdev);
251 if (r) {
252 DSSERR("device %s init failed: %d\n", dssdev->name, r);
253 dss_put_device(dssdev);
254 return;
204 } 255 }
256
257 r = dss_add_device(dssdev);
258 if (r) {
259 DSSERR("device %s register failed: %d\n", dssdev->name, r);
260 dss_put_device(dssdev);
261 return;
262 }
263}
264
265static void __init sdi_init_output(struct platform_device *pdev)
266{
267 struct omap_dss_output *out = &sdi.output;
268
269 out->pdev = pdev;
270 out->id = OMAP_DSS_OUTPUT_SDI;
271 out->type = OMAP_DISPLAY_TYPE_SDI;
272
273 dss_register_output(out);
274}
275
276static void __exit sdi_uninit_output(struct platform_device *pdev)
277{
278 struct omap_dss_output *out = &sdi.output;
279
280 dss_unregister_output(out);
205} 281}
206 282
207static int __init omap_sdi_probe(struct platform_device *pdev) 283static int __init omap_sdi_probe(struct platform_device *pdev)
208{ 284{
285 sdi_init_output(pdev);
286
209 sdi_probe_pdata(pdev); 287 sdi_probe_pdata(pdev);
210 288
211 return 0; 289 return 0;
@@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev)
213 291
214static int __exit omap_sdi_remove(struct platform_device *pdev) 292static int __exit omap_sdi_remove(struct platform_device *pdev)
215{ 293{
216 omap_dss_unregister_child_devices(&pdev->dev); 294 dss_unregister_child_devices(&pdev->dev);
295
296 sdi_uninit_output(pdev);
217 297
218 return 0; 298 return 0;
219} 299}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 3a220877461a..56efa3bb465d 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -36,7 +36,6 @@
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37 37
38#include <video/omapdss.h> 38#include <video/omapdss.h>
39#include <plat/cpu.h>
40 39
41#include "dss.h" 40#include "dss.h"
42#include "dss_features.h" 41#include "dss_features.h"
@@ -300,6 +299,12 @@ static struct {
300 struct regulator *vdda_dac_reg; 299 struct regulator *vdda_dac_reg;
301 300
302 struct clk *tv_dac_clk; 301 struct clk *tv_dac_clk;
302
303 struct omap_video_timings timings;
304 enum omap_dss_venc_type type;
305 bool invert_polarity;
306
307 struct omap_dss_output output;
303} venc; 308} venc;
304 309
305static inline void venc_write_reg(int idx, u32 val) 310static inline void venc_write_reg(int idx, u32 val)
@@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config(
424 429
425static int venc_power_on(struct omap_dss_device *dssdev) 430static int venc_power_on(struct omap_dss_device *dssdev)
426{ 431{
432 struct omap_overlay_manager *mgr = dssdev->output->manager;
427 u32 l; 433 u32 l;
428 int r; 434 int r;
429 435
436 r = venc_runtime_get();
437 if (r)
438 goto err0;
439
430 venc_reset(); 440 venc_reset();
431 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); 441 venc_write_config(venc_timings_to_config(&venc.timings));
432 442
433 dss_set_venc_output(dssdev->phy.venc.type); 443 dss_set_venc_output(venc.type);
434 dss_set_dac_pwrdn_bgz(1); 444 dss_set_dac_pwrdn_bgz(1);
435 445
436 l = 0; 446 l = 0;
437 447
438 if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) 448 if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
439 l |= 1 << 1; 449 l |= 1 << 1;
440 else /* S-Video */ 450 else /* S-Video */
441 l |= (1 << 0) | (1 << 2); 451 l |= (1 << 0) | (1 << 2);
442 452
443 if (dssdev->phy.venc.invert_polarity == false) 453 if (venc.invert_polarity == false)
444 l |= 1 << 3; 454 l |= 1 << 3;
445 455
446 venc_write_reg(VENC_OUTPUT_CONTROL, l); 456 venc_write_reg(VENC_OUTPUT_CONTROL, l);
447 457
448 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 458 dss_mgr_set_timings(mgr, &venc.timings);
449 459
450 r = regulator_enable(venc.vdda_dac_reg); 460 r = regulator_enable(venc.vdda_dac_reg);
451 if (r) 461 if (r)
452 goto err; 462 goto err1;
453
454 if (dssdev->platform_enable)
455 dssdev->platform_enable(dssdev);
456 463
457 r = dss_mgr_enable(dssdev->manager); 464 r = dss_mgr_enable(mgr);
458 if (r) 465 if (r)
459 goto err; 466 goto err2;
460 467
461 return 0; 468 return 0;
462 469
463err: 470err2:
471 regulator_disable(venc.vdda_dac_reg);
472err1:
464 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 473 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
465 dss_set_dac_pwrdn_bgz(0); 474 dss_set_dac_pwrdn_bgz(0);
466 475
467 if (dssdev->platform_disable) 476 venc_runtime_put();
468 dssdev->platform_disable(dssdev); 477err0:
469
470 regulator_disable(venc.vdda_dac_reg);
471
472 return r; 478 return r;
473} 479}
474 480
475static void venc_power_off(struct omap_dss_device *dssdev) 481static void venc_power_off(struct omap_dss_device *dssdev)
476{ 482{
483 struct omap_overlay_manager *mgr = dssdev->output->manager;
484
477 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 485 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
478 dss_set_dac_pwrdn_bgz(0); 486 dss_set_dac_pwrdn_bgz(0);
479 487
480 dss_mgr_disable(dssdev->manager); 488 dss_mgr_disable(mgr);
481
482 if (dssdev->platform_disable)
483 dssdev->platform_disable(dssdev);
484 489
485 regulator_disable(venc.vdda_dac_reg); 490 regulator_disable(venc.vdda_dac_reg);
491
492 venc_runtime_put();
486} 493}
487 494
488unsigned long venc_get_pixel_clock(void) 495unsigned long venc_get_pixel_clock(void)
@@ -491,171 +498,83 @@ unsigned long venc_get_pixel_clock(void)
491 return 13500000; 498 return 13500000;
492} 499}
493 500
494static ssize_t display_output_type_show(struct device *dev, 501int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
495 struct device_attribute *attr, char *buf)
496{ 502{
497 struct omap_dss_device *dssdev = to_dss_device(dev); 503 struct omap_dss_output *out = dssdev->output;
498 const char *ret; 504 int r;
499
500 switch (dssdev->phy.venc.type) {
501 case OMAP_DSS_VENC_TYPE_COMPOSITE:
502 ret = "composite";
503 break;
504 case OMAP_DSS_VENC_TYPE_SVIDEO:
505 ret = "svideo";
506 break;
507 default:
508 return -EINVAL;
509 }
510
511 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
512}
513 505
514static ssize_t display_output_type_store(struct device *dev, 506 DSSDBG("venc_display_enable\n");
515 struct device_attribute *attr, const char *buf, size_t size)
516{
517 struct omap_dss_device *dssdev = to_dss_device(dev);
518 enum omap_dss_venc_type new_type;
519
520 if (sysfs_streq("composite", buf))
521 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
522 else if (sysfs_streq("svideo", buf))
523 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
524 else
525 return -EINVAL;
526 507
527 mutex_lock(&venc.venc_lock); 508 mutex_lock(&venc.venc_lock);
528 509
529 if (dssdev->phy.venc.type != new_type) { 510 if (out == NULL || out->manager == NULL) {
530 dssdev->phy.venc.type = new_type; 511 DSSERR("Failed to enable display: no output/manager\n");
531 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 512 r = -ENODEV;
532 venc_power_off(dssdev); 513 goto err0;
533 venc_power_on(dssdev);
534 }
535 } 514 }
536 515
537 mutex_unlock(&venc.venc_lock);
538
539 return size;
540}
541
542static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
543 display_output_type_show, display_output_type_store);
544
545/* driver */
546static int venc_panel_probe(struct omap_dss_device *dssdev)
547{
548 dssdev->panel.timings = omap_dss_pal_timings;
549
550 return device_create_file(&dssdev->dev, &dev_attr_output_type);
551}
552
553static void venc_panel_remove(struct omap_dss_device *dssdev)
554{
555 device_remove_file(&dssdev->dev, &dev_attr_output_type);
556}
557
558static int venc_panel_enable(struct omap_dss_device *dssdev)
559{
560 int r = 0;
561
562 DSSDBG("venc_enable_display\n");
563
564 mutex_lock(&venc.venc_lock);
565
566 r = omap_dss_start_device(dssdev); 516 r = omap_dss_start_device(dssdev);
567 if (r) { 517 if (r) {
568 DSSERR("failed to start device\n"); 518 DSSERR("failed to start device\n");
569 goto err0; 519 goto err0;
570 } 520 }
571 521
572 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { 522 if (dssdev->platform_enable)
573 r = -EINVAL; 523 dssdev->platform_enable(dssdev);
574 goto err1;
575 }
576 524
577 r = venc_runtime_get();
578 if (r)
579 goto err1;
580 525
581 r = venc_power_on(dssdev); 526 r = venc_power_on(dssdev);
582 if (r) 527 if (r)
583 goto err2; 528 goto err1;
584 529
585 venc.wss_data = 0; 530 venc.wss_data = 0;
586 531
587 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
588
589 mutex_unlock(&venc.venc_lock); 532 mutex_unlock(&venc.venc_lock);
533
590 return 0; 534 return 0;
591err2:
592 venc_runtime_put();
593err1: 535err1:
536 if (dssdev->platform_disable)
537 dssdev->platform_disable(dssdev);
594 omap_dss_stop_device(dssdev); 538 omap_dss_stop_device(dssdev);
595err0: 539err0:
596 mutex_unlock(&venc.venc_lock); 540 mutex_unlock(&venc.venc_lock);
597
598 return r; 541 return r;
599} 542}
600 543
601static void venc_panel_disable(struct omap_dss_device *dssdev) 544void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
602{ 545{
603 DSSDBG("venc_disable_display\n"); 546 DSSDBG("venc_display_disable\n");
604 547
605 mutex_lock(&venc.venc_lock); 548 mutex_lock(&venc.venc_lock);
606 549
607 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
608 goto end;
609
610 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
611 /* suspended is the same as disabled with venc */
612 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
613 goto end;
614 }
615
616 venc_power_off(dssdev); 550 venc_power_off(dssdev);
617 551
618 venc_runtime_put();
619
620 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
621
622 omap_dss_stop_device(dssdev); 552 omap_dss_stop_device(dssdev);
623end:
624 mutex_unlock(&venc.venc_lock);
625}
626 553
627static int venc_panel_suspend(struct omap_dss_device *dssdev) 554 if (dssdev->platform_disable)
628{ 555 dssdev->platform_disable(dssdev);
629 venc_panel_disable(dssdev);
630 return 0;
631}
632 556
633static int venc_panel_resume(struct omap_dss_device *dssdev) 557 mutex_unlock(&venc.venc_lock);
634{
635 return venc_panel_enable(dssdev);
636} 558}
637 559
638static void venc_set_timings(struct omap_dss_device *dssdev, 560void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
639 struct omap_video_timings *timings) 561 struct omap_video_timings *timings)
640{ 562{
641 DSSDBG("venc_set_timings\n"); 563 DSSDBG("venc_set_timings\n");
642 564
565 mutex_lock(&venc.venc_lock);
566
643 /* Reset WSS data when the TV standard changes. */ 567 /* Reset WSS data when the TV standard changes. */
644 if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) 568 if (memcmp(&venc.timings, timings, sizeof(*timings)))
645 venc.wss_data = 0; 569 venc.wss_data = 0;
646 570
647 dssdev->panel.timings = *timings; 571 venc.timings = *timings;
648 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 572
649 /* turn the venc off and on to get new timings to use */ 573 mutex_unlock(&venc.venc_lock);
650 venc_panel_disable(dssdev);
651 venc_panel_enable(dssdev);
652 } else {
653 dss_mgr_set_timings(dssdev->manager, timings);
654 }
655} 574}
656 575
657static int venc_check_timings(struct omap_dss_device *dssdev, 576int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
658 struct omap_video_timings *timings) 577 struct omap_video_timings *timings)
659{ 578{
660 DSSDBG("venc_check_timings\n"); 579 DSSDBG("venc_check_timings\n");
661 580
@@ -668,13 +587,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
668 return -EINVAL; 587 return -EINVAL;
669} 588}
670 589
671static u32 venc_get_wss(struct omap_dss_device *dssdev) 590u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
672{ 591{
673 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 592 /* Invert due to VENC_L21_WC_CTL:INV=1 */
674 return (venc.wss_data >> 8) ^ 0xfffff; 593 return (venc.wss_data >> 8) ^ 0xfffff;
675} 594}
676 595
677static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 596int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
678{ 597{
679 const struct venc_config *config; 598 const struct venc_config *config;
680 int r; 599 int r;
@@ -683,7 +602,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
683 602
684 mutex_lock(&venc.venc_lock); 603 mutex_lock(&venc.venc_lock);
685 604
686 config = venc_timings_to_config(&dssdev->panel.timings); 605 config = venc_timings_to_config(&venc.timings);
687 606
688 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 607 /* Invert due to VENC_L21_WC_CTL:INV=1 */
689 venc.wss_data = (wss ^ 0xfffff) << 8; 608 venc.wss_data = (wss ^ 0xfffff) << 8;
@@ -703,30 +622,25 @@ err:
703 return r; 622 return r;
704} 623}
705 624
706static struct omap_dss_driver venc_driver = { 625void omapdss_venc_set_type(struct omap_dss_device *dssdev,
707 .probe = venc_panel_probe, 626 enum omap_dss_venc_type type)
708 .remove = venc_panel_remove, 627{
628 mutex_lock(&venc.venc_lock);
709 629
710 .enable = venc_panel_enable, 630 venc.type = type;
711 .disable = venc_panel_disable,
712 .suspend = venc_panel_suspend,
713 .resume = venc_panel_resume,
714 631
715 .get_resolution = omapdss_default_get_resolution, 632 mutex_unlock(&venc.venc_lock);
716 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 633}
717 634
718 .set_timings = venc_set_timings, 635void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
719 .check_timings = venc_check_timings, 636 bool invert_polarity)
637{
638 mutex_lock(&venc.venc_lock);
720 639
721 .get_wss = venc_get_wss, 640 venc.invert_polarity = invert_polarity;
722 .set_wss = venc_set_wss,
723 641
724 .driver = { 642 mutex_unlock(&venc.venc_lock);
725 .name = "venc", 643}
726 .owner = THIS_MODULE,
727 },
728};
729/* driver end */
730 644
731static int __init venc_init_display(struct omap_dss_device *dssdev) 645static int __init venc_init_display(struct omap_dss_device *dssdev)
732{ 646{
@@ -752,11 +666,6 @@ static void venc_dump_regs(struct seq_file *s)
752{ 666{
753#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 667#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
754 668
755 if (cpu_is_omap44xx()) {
756 seq_printf(s, "VENC currently disabled on OMAP44xx\n");
757 return;
758 }
759
760 if (venc_runtime_get()) 669 if (venc_runtime_get())
761 return; 670 return;
762 671
@@ -832,10 +741,14 @@ static void venc_put_clocks(void)
832 clk_put(venc.tv_dac_clk); 741 clk_put(venc.tv_dac_clk);
833} 742}
834 743
835static void __init venc_probe_pdata(struct platform_device *pdev) 744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
836{ 745{
837 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 746 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
838 int r, i; 747 const char *def_disp_name = dss_get_default_display_name();
748 struct omap_dss_device *def_dssdev;
749 int i;
750
751 def_dssdev = NULL;
839 752
840 for (i = 0; i < pdata->num_devices; ++i) { 753 for (i = 0; i < pdata->num_devices; ++i) {
841 struct omap_dss_device *dssdev = pdata->devices[i]; 754 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -843,17 +756,69 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
843 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) 756 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
844 continue; 757 continue;
845 758
846 r = venc_init_display(dssdev); 759 if (def_dssdev == NULL)
847 if (r) { 760 def_dssdev = dssdev;
848 DSSERR("device %s init failed: %d\n", dssdev->name, r); 761
849 continue; 762 if (def_disp_name != NULL &&
763 strcmp(dssdev->name, def_disp_name) == 0) {
764 def_dssdev = dssdev;
765 break;
850 } 766 }
767 }
768
769 return def_dssdev;
770}
771
772static void __init venc_probe_pdata(struct platform_device *vencdev)
773{
774 struct omap_dss_device *plat_dssdev;
775 struct omap_dss_device *dssdev;
776 int r;
777
778 plat_dssdev = venc_find_dssdev(vencdev);
851 779
852 r = omap_dss_register_device(dssdev, &pdev->dev, i); 780 if (!plat_dssdev)
853 if (r) 781 return;
854 DSSERR("device %s register failed: %d\n", 782
855 dssdev->name, r); 783 dssdev = dss_alloc_and_init_device(&vencdev->dev);
784 if (!dssdev)
785 return;
786
787 dss_copy_device_pdata(dssdev, plat_dssdev);
788
789 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
790
791 r = venc_init_display(dssdev);
792 if (r) {
793 DSSERR("device %s init failed: %d\n", dssdev->name, r);
794 dss_put_device(dssdev);
795 return;
856 } 796 }
797
798 r = dss_add_device(dssdev);
799 if (r) {
800 DSSERR("device %s register failed: %d\n", dssdev->name, r);
801 dss_put_device(dssdev);
802 return;
803 }
804}
805
806static void __init venc_init_output(struct platform_device *pdev)
807{
808 struct omap_dss_output *out = &venc.output;
809
810 out->pdev = pdev;
811 out->id = OMAP_DSS_OUTPUT_VENC;
812 out->type = OMAP_DISPLAY_TYPE_VENC;
813
814 dss_register_output(out);
815}
816
817static void __exit venc_uninit_output(struct platform_device *pdev)
818{
819 struct omap_dss_output *out = &venc.output;
820
821 dss_unregister_output(out);
857} 822}
858 823
859/* VENC HW IP initialisation */ 824/* VENC HW IP initialisation */
@@ -897,17 +862,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
897 862
898 venc_runtime_put(); 863 venc_runtime_put();
899 864
900 r = omap_dss_register_driver(&venc_driver); 865 r = venc_panel_init();
901 if (r) 866 if (r)
902 goto err_reg_panel_driver; 867 goto err_panel_init;
903 868
904 dss_debugfs_create_file("venc", venc_dump_regs); 869 dss_debugfs_create_file("venc", venc_dump_regs);
905 870
871 venc_init_output(pdev);
872
906 venc_probe_pdata(pdev); 873 venc_probe_pdata(pdev);
907 874
908 return 0; 875 return 0;
909 876
910err_reg_panel_driver: 877err_panel_init:
911err_runtime_get: 878err_runtime_get:
912 pm_runtime_disable(&pdev->dev); 879 pm_runtime_disable(&pdev->dev);
913 venc_put_clocks(); 880 venc_put_clocks();
@@ -916,14 +883,16 @@ err_runtime_get:
916 883
917static int __exit omap_venchw_remove(struct platform_device *pdev) 884static int __exit omap_venchw_remove(struct platform_device *pdev)
918{ 885{
919 omap_dss_unregister_child_devices(&pdev->dev); 886 dss_unregister_child_devices(&pdev->dev);
920 887
921 if (venc.vdda_dac_reg != NULL) { 888 if (venc.vdda_dac_reg != NULL) {
922 regulator_put(venc.vdda_dac_reg); 889 regulator_put(venc.vdda_dac_reg);
923 venc.vdda_dac_reg = NULL; 890 venc.vdda_dac_reg = NULL;
924 } 891 }
925 892
926 omap_dss_unregister_driver(&venc_driver); 893 venc_panel_exit();
894
895 venc_uninit_output(pdev);
927 896
928 pm_runtime_disable(&pdev->dev); 897 pm_runtime_disable(&pdev->dev);
929 venc_put_clocks(); 898 venc_put_clocks();
@@ -971,16 +940,10 @@ static struct platform_driver omap_venchw_driver = {
971 940
972int __init venc_init_platform_driver(void) 941int __init venc_init_platform_driver(void)
973{ 942{
974 if (cpu_is_omap44xx())
975 return 0;
976
977 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); 943 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
978} 944}
979 945
980void __exit venc_uninit_platform_driver(void) 946void __exit venc_uninit_platform_driver(void)
981{ 947{
982 if (cpu_is_omap44xx())
983 return;
984
985 platform_driver_unregister(&omap_venchw_driver); 948 platform_driver_unregister(&omap_venchw_driver);
986} 949}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
new file mode 100644
index 000000000000..d55b8784ecfd
--- /dev/null
+++ b/drivers/video/omap2/dss/venc_panel.c
@@ -0,0 +1,251 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * VENC panel driver
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/mutex.h>
24#include <linux/module.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29
30static struct {
31 struct mutex lock;
32} venc_panel;
33
34static ssize_t display_output_type_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 const char *ret;
39
40 switch (dssdev->phy.venc.type) {
41 case OMAP_DSS_VENC_TYPE_COMPOSITE:
42 ret = "composite";
43 break;
44 case OMAP_DSS_VENC_TYPE_SVIDEO:
45 ret = "svideo";
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
52}
53
54static ssize_t display_output_type_store(struct device *dev,
55 struct device_attribute *attr, const char *buf, size_t size)
56{
57 struct omap_dss_device *dssdev = to_dss_device(dev);
58 enum omap_dss_venc_type new_type;
59
60 if (sysfs_streq("composite", buf))
61 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
62 else if (sysfs_streq("svideo", buf))
63 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
64 else
65 return -EINVAL;
66
67 mutex_lock(&venc_panel.lock);
68
69 if (dssdev->phy.venc.type != new_type) {
70 dssdev->phy.venc.type = new_type;
71 omapdss_venc_set_type(dssdev, new_type);
72 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
73 omapdss_venc_display_disable(dssdev);
74 omapdss_venc_display_enable(dssdev);
75 }
76 }
77
78 mutex_unlock(&venc_panel.lock);
79
80 return size;
81}
82
83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
84 display_output_type_show, display_output_type_store);
85
86static int venc_panel_probe(struct omap_dss_device *dssdev)
87{
88 /* set default timings to PAL */
89 const struct omap_video_timings default_timings = {
90 .x_res = 720,
91 .y_res = 574,
92 .pixel_clock = 13500,
93 .hsw = 64,
94 .hfp = 12,
95 .hbp = 68,
96 .vsw = 5,
97 .vfp = 5,
98 .vbp = 41,
99
100 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
101 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
102
103 .interlace = true,
104 };
105
106 mutex_init(&venc_panel.lock);
107
108 dssdev->panel.timings = default_timings;
109
110 return device_create_file(&dssdev->dev, &dev_attr_output_type);
111}
112
113static void venc_panel_remove(struct omap_dss_device *dssdev)
114{
115 device_remove_file(&dssdev->dev, &dev_attr_output_type);
116}
117
118static int venc_panel_enable(struct omap_dss_device *dssdev)
119{
120 int r;
121
122 dev_dbg(&dssdev->dev, "venc_panel_enable\n");
123
124 mutex_lock(&venc_panel.lock);
125
126 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
127 r = -EINVAL;
128 goto err;
129 }
130
131 omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
132 omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
133 omapdss_venc_invert_vid_out_polarity(dssdev,
134 dssdev->phy.venc.invert_polarity);
135
136 r = omapdss_venc_display_enable(dssdev);
137 if (r)
138 goto err;
139
140 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
141
142 mutex_unlock(&venc_panel.lock);
143
144 return 0;
145err:
146 mutex_unlock(&venc_panel.lock);
147
148 return r;
149}
150
151static void venc_panel_disable(struct omap_dss_device *dssdev)
152{
153 dev_dbg(&dssdev->dev, "venc_panel_disable\n");
154
155 mutex_lock(&venc_panel.lock);
156
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end;
159
160 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
161 /* suspended is the same as disabled with venc */
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163 goto end;
164 }
165
166 omapdss_venc_display_disable(dssdev);
167
168 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
169end:
170 mutex_unlock(&venc_panel.lock);
171}
172
173static int venc_panel_suspend(struct omap_dss_device *dssdev)
174{
175 venc_panel_disable(dssdev);
176 return 0;
177}
178
179static int venc_panel_resume(struct omap_dss_device *dssdev)
180{
181 return venc_panel_enable(dssdev);
182}
183
184static void venc_panel_set_timings(struct omap_dss_device *dssdev,
185 struct omap_video_timings *timings)
186{
187 dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
188
189 mutex_lock(&venc_panel.lock);
190
191 omapdss_venc_set_timings(dssdev, timings);
192 dssdev->panel.timings = *timings;
193
194 mutex_unlock(&venc_panel.lock);
195}
196
197static int venc_panel_check_timings(struct omap_dss_device *dssdev,
198 struct omap_video_timings *timings)
199{
200 dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
201
202 return omapdss_venc_check_timings(dssdev, timings);
203}
204
205static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
206{
207 dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
208
209 return omapdss_venc_get_wss(dssdev);
210}
211
212static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
213{
214 dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
215
216 return omapdss_venc_set_wss(dssdev, wss);
217}
218
219static struct omap_dss_driver venc_driver = {
220 .probe = venc_panel_probe,
221 .remove = venc_panel_remove,
222
223 .enable = venc_panel_enable,
224 .disable = venc_panel_disable,
225 .suspend = venc_panel_suspend,
226 .resume = venc_panel_resume,
227
228 .get_resolution = omapdss_default_get_resolution,
229 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
230
231 .set_timings = venc_panel_set_timings,
232 .check_timings = venc_panel_check_timings,
233
234 .get_wss = venc_panel_get_wss,
235 .set_wss = venc_panel_set_wss,
236
237 .driver = {
238 .name = "venc",
239 .owner = THIS_MODULE,
240 },
241};
242
243int venc_panel_init(void)
244{
245 return omap_dss_register_driver(&venc_driver);
246}
247
248void venc_panel_exit(void)
249{
250 omap_dss_unregister_driver(&venc_driver);
251}