aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-11-16 09:44:08 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-01-25 06:46:18 -0500
commit1d71f42b35ed66d90a9a39bc515bb16cfe2d4a46 (patch)
tree03768b58ff8aabc922de9d65394cd678341da230 /drivers/video
parentfb0119742291b6f30cd97026ee137b2d3d1f4de8 (diff)
OMAPDSS: APPLY: add fifo-merge support
Add fifo-merge support. This is done mainly in four functions: mgr_enable/disable and ovl_enable/disable. These are the functions where overlays are taken into and out of active use. The process to enable and disable fifo-merge is not simple. We need to do it in steps, waiting in between for certain settings to be taken into use, and continuing after that. The reason for this is that fifo-merge is a common thing for all managers/overlays, and its use must be synchronized. As an example, when we disable an overlay, we first set the overlay as disabled, then wait until the overlay is actually disabled in the HW, and only after that we may re-configure the fifos, possibly taking fifo-merge into use. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/apply.c164
1 files changed, 156 insertions, 8 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 604737f1187d..6f7b213e096e 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -902,7 +902,8 @@ static void dss_apply_fifo_merge(bool use_fifo_merge)
902 dss_data.fifo_merge_dirty = true; 902 dss_data.fifo_merge_dirty = true;
903} 903}
904 904
905static void dss_ovl_setup_fifo(struct omap_overlay *ovl) 905static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
906 bool use_fifo_merge)
906{ 907{
907 struct ovl_priv_data *op = get_ovl_priv(ovl); 908 struct ovl_priv_data *op = get_ovl_priv(ovl);
908 struct omap_dss_device *dssdev; 909 struct omap_dss_device *dssdev;
@@ -914,7 +915,16 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
914 915
915 dssdev = ovl->manager->device; 916 dssdev = ovl->manager->device;
916 917
917 size = dispc_ovl_get_fifo_size(ovl->id); 918 if (use_fifo_merge) {
919 int i;
920
921 size = 0;
922
923 for (i = 0; i < omap_dss_get_num_overlays(); ++i)
924 size += dispc_ovl_get_fifo_size(i);
925 } else {
926 size = dispc_ovl_get_fifo_size(ovl->id);
927 }
918 928
919 burst_size = dispc_ovl_get_burst_size(ovl->id); 929 burst_size = dispc_ovl_get_burst_size(ovl->id);
920 930
@@ -940,7 +950,8 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
940 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 950 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
941} 951}
942 952
943static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) 953static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
954 bool use_fifo_merge)
944{ 955{
945 struct omap_overlay *ovl; 956 struct omap_overlay *ovl;
946 struct mgr_priv_data *mp; 957 struct mgr_priv_data *mp;
@@ -951,10 +962,10 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
951 return; 962 return;
952 963
953 list_for_each_entry(ovl, &mgr->overlays, list) 964 list_for_each_entry(ovl, &mgr->overlays, list)
954 dss_ovl_setup_fifo(ovl); 965 dss_ovl_setup_fifo(ovl, use_fifo_merge);
955} 966}
956 967
957static void dss_setup_fifos(void) 968static void dss_setup_fifos(bool use_fifo_merge)
958{ 969{
959 const int num_mgrs = omap_dss_get_num_overlay_managers(); 970 const int num_mgrs = omap_dss_get_num_overlay_managers();
960 struct omap_overlay_manager *mgr; 971 struct omap_overlay_manager *mgr;
@@ -962,15 +973,91 @@ static void dss_setup_fifos(void)
962 973
963 for (i = 0; i < num_mgrs; ++i) { 974 for (i = 0; i < num_mgrs; ++i) {
964 mgr = omap_dss_get_overlay_manager(i); 975 mgr = omap_dss_get_overlay_manager(i);
965 dss_mgr_setup_fifos(mgr); 976 dss_mgr_setup_fifos(mgr, use_fifo_merge);
966 } 977 }
967} 978}
968 979
980static int get_num_used_managers(void)
981{
982 const int num_mgrs = omap_dss_get_num_overlay_managers();
983 struct omap_overlay_manager *mgr;
984 struct mgr_priv_data *mp;
985 int i;
986 int enabled_mgrs;
987
988 enabled_mgrs = 0;
989
990 for (i = 0; i < num_mgrs; ++i) {
991 mgr = omap_dss_get_overlay_manager(i);
992 mp = get_mgr_priv(mgr);
993
994 if (!mp->enabled)
995 continue;
996
997 enabled_mgrs++;
998 }
999
1000 return enabled_mgrs;
1001}
1002
1003static int get_num_used_overlays(void)
1004{
1005 const int num_ovls = omap_dss_get_num_overlays();
1006 struct omap_overlay *ovl;
1007 struct ovl_priv_data *op;
1008 struct mgr_priv_data *mp;
1009 int i;
1010 int enabled_ovls;
1011
1012 enabled_ovls = 0;
1013
1014 for (i = 0; i < num_ovls; ++i) {
1015 ovl = omap_dss_get_overlay(i);
1016 op = get_ovl_priv(ovl);
1017
1018 if (!op->enabled && !op->enabling)
1019 continue;
1020
1021 mp = get_mgr_priv(ovl->manager);
1022
1023 if (!mp->enabled)
1024 continue;
1025
1026 enabled_ovls++;
1027 }
1028
1029 return enabled_ovls;
1030}
1031
1032static bool get_use_fifo_merge(void)
1033{
1034 int enabled_mgrs = get_num_used_managers();
1035 int enabled_ovls = get_num_used_overlays();
1036
1037 if (!dss_has_feature(FEAT_FIFO_MERGE))
1038 return false;
1039
1040 /*
1041 * In theory the only requirement for fifomerge is enabled_ovls <= 1.
1042 * However, if we have two managers enabled and set/unset the fifomerge,
1043 * we need to set the GO bits in particular sequence for the managers,
1044 * and wait in between.
1045 *
1046 * This is rather difficult as new apply calls can happen at any time,
1047 * so we simplify the problem by requiring also that enabled_mgrs <= 1.
1048 * In practice this shouldn't matter, because when only one overlay is
1049 * enabled, most likely only one output is enabled.
1050 */
1051
1052 return enabled_mgrs <= 1 && enabled_ovls <= 1;
1053}
1054
969int dss_mgr_enable(struct omap_overlay_manager *mgr) 1055int dss_mgr_enable(struct omap_overlay_manager *mgr)
970{ 1056{
971 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1057 struct mgr_priv_data *mp = get_mgr_priv(mgr);
972 unsigned long flags; 1058 unsigned long flags;
973 int r; 1059 int r;
1060 bool fifo_merge;
974 1061
975 mutex_lock(&apply_lock); 1062 mutex_lock(&apply_lock);
976 1063
@@ -988,11 +1075,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
988 goto err; 1075 goto err;
989 } 1076 }
990 1077
991 dss_setup_fifos(); 1078 /* step 1: setup fifos/fifomerge before enabling the manager */
1079
1080 fifo_merge = get_use_fifo_merge();
1081 dss_setup_fifos(fifo_merge);
1082 dss_apply_fifo_merge(fifo_merge);
992 1083
993 dss_write_regs(); 1084 dss_write_regs();
994 dss_set_go_bits(); 1085 dss_set_go_bits();
995 1086
1087 spin_unlock_irqrestore(&data_lock, flags);
1088
1089 /* wait until fifo config is in */
1090 wait_pending_extra_info_updates();
1091
1092 /* step 2: enable the manager */
1093 spin_lock_irqsave(&data_lock, flags);
1094
996 if (!mgr_manual_update(mgr)) 1095 if (!mgr_manual_update(mgr))
997 mp->updating = true; 1096 mp->updating = true;
998 1097
@@ -1017,6 +1116,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1017{ 1116{
1018 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1117 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1019 unsigned long flags; 1118 unsigned long flags;
1119 bool fifo_merge;
1020 1120
1021 mutex_lock(&apply_lock); 1121 mutex_lock(&apply_lock);
1022 1122
@@ -1031,8 +1131,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1031 mp->updating = false; 1131 mp->updating = false;
1032 mp->enabled = false; 1132 mp->enabled = false;
1033 1133
1134 fifo_merge = get_use_fifo_merge();
1135 dss_setup_fifos(fifo_merge);
1136 dss_apply_fifo_merge(fifo_merge);
1137
1138 dss_write_regs();
1139 dss_set_go_bits();
1140
1034 spin_unlock_irqrestore(&data_lock, flags); 1141 spin_unlock_irqrestore(&data_lock, flags);
1035 1142
1143 wait_pending_extra_info_updates();
1036out: 1144out:
1037 mutex_unlock(&apply_lock); 1145 mutex_unlock(&apply_lock);
1038} 1146}
@@ -1284,6 +1392,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1284{ 1392{
1285 struct ovl_priv_data *op = get_ovl_priv(ovl); 1393 struct ovl_priv_data *op = get_ovl_priv(ovl);
1286 unsigned long flags; 1394 unsigned long flags;
1395 bool fifo_merge;
1287 int r; 1396 int r;
1288 1397
1289 mutex_lock(&apply_lock); 1398 mutex_lock(&apply_lock);
@@ -1309,7 +1418,22 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1309 goto err2; 1418 goto err2;
1310 } 1419 }
1311 1420
1312 dss_setup_fifos(); 1421 /* step 1: configure fifos/fifomerge for currently enabled ovls */
1422
1423 fifo_merge = get_use_fifo_merge();
1424 dss_setup_fifos(fifo_merge);
1425 dss_apply_fifo_merge(fifo_merge);
1426
1427 dss_write_regs();
1428 dss_set_go_bits();
1429
1430 spin_unlock_irqrestore(&data_lock, flags);
1431
1432 /* wait for fifo configs to go in */
1433 wait_pending_extra_info_updates();
1434
1435 /* step 2: enable the overlay */
1436 spin_lock_irqsave(&data_lock, flags);
1313 1437
1314 op->enabling = false; 1438 op->enabling = false;
1315 dss_apply_ovl_enable(ovl, true); 1439 dss_apply_ovl_enable(ovl, true);
@@ -1319,6 +1443,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1319 1443
1320 spin_unlock_irqrestore(&data_lock, flags); 1444 spin_unlock_irqrestore(&data_lock, flags);
1321 1445
1446 /* wait for overlay to be enabled */
1447 wait_pending_extra_info_updates();
1448
1322 mutex_unlock(&apply_lock); 1449 mutex_unlock(&apply_lock);
1323 1450
1324 return 0; 1451 return 0;
@@ -1334,6 +1461,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1334{ 1461{
1335 struct ovl_priv_data *op = get_ovl_priv(ovl); 1462 struct ovl_priv_data *op = get_ovl_priv(ovl);
1336 unsigned long flags; 1463 unsigned long flags;
1464 bool fifo_merge;
1337 int r; 1465 int r;
1338 1466
1339 mutex_lock(&apply_lock); 1467 mutex_lock(&apply_lock);
@@ -1348,14 +1476,34 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1348 goto err; 1476 goto err;
1349 } 1477 }
1350 1478
1479 /* step 1: disable the overlay */
1351 spin_lock_irqsave(&data_lock, flags); 1480 spin_lock_irqsave(&data_lock, flags);
1352 1481
1353 dss_apply_ovl_enable(ovl, false); 1482 dss_apply_ovl_enable(ovl, false);
1483
1354 dss_write_regs(); 1484 dss_write_regs();
1355 dss_set_go_bits(); 1485 dss_set_go_bits();
1356 1486
1357 spin_unlock_irqrestore(&data_lock, flags); 1487 spin_unlock_irqrestore(&data_lock, flags);
1358 1488
1489 /* wait for the overlay to be disabled */
1490 wait_pending_extra_info_updates();
1491
1492 /* step 2: configure fifos/fifomerge */
1493 spin_lock_irqsave(&data_lock, flags);
1494
1495 fifo_merge = get_use_fifo_merge();
1496 dss_setup_fifos(fifo_merge);
1497 dss_apply_fifo_merge(fifo_merge);
1498
1499 dss_write_regs();
1500 dss_set_go_bits();
1501
1502 spin_unlock_irqrestore(&data_lock, flags);
1503
1504 /* wait for fifo config to go in */
1505 wait_pending_extra_info_updates();
1506
1359 mutex_unlock(&apply_lock); 1507 mutex_unlock(&apply_lock);
1360 1508
1361 return 0; 1509 return 0;