Skip to content

Commit 1d71f42

Browse files
committed
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 <[email protected]>
1 parent fb01197 commit 1d71f42

File tree

1 file changed

+156
-8
lines changed

1 file changed

+156
-8
lines changed

drivers/video/omap2/dss/apply.c

Lines changed: 156 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,8 @@ static void dss_apply_fifo_merge(bool use_fifo_merge)
902902
dss_data.fifo_merge_dirty = true;
903903
}
904904

905-
static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
905+
static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
906+
bool use_fifo_merge)
906907
{
907908
struct ovl_priv_data *op = get_ovl_priv(ovl);
908909
struct omap_dss_device *dssdev;
@@ -914,7 +915,16 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
914915

915916
dssdev = ovl->manager->device;
916917

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+
}
918928

919929
burst_size = dispc_ovl_get_burst_size(ovl->id);
920930

@@ -940,7 +950,8 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
940950
dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
941951
}
942952

943-
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
953+
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
954+
bool use_fifo_merge)
944955
{
945956
struct omap_overlay *ovl;
946957
struct mgr_priv_data *mp;
@@ -951,26 +962,102 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
951962
return;
952963

953964
list_for_each_entry(ovl, &mgr->overlays, list)
954-
dss_ovl_setup_fifo(ovl);
965+
dss_ovl_setup_fifo(ovl, use_fifo_merge);
955966
}
956967

957-
static void dss_setup_fifos(void)
968+
static void dss_setup_fifos(bool use_fifo_merge)
958969
{
959970
const int num_mgrs = omap_dss_get_num_overlay_managers();
960971
struct omap_overlay_manager *mgr;
961972
int i;
962973

963974
for (i = 0; i < num_mgrs; ++i) {
964975
mgr = omap_dss_get_overlay_manager(i);
965-
dss_mgr_setup_fifos(mgr);
976+
dss_mgr_setup_fifos(mgr, use_fifo_merge);
966977
}
967978
}
968979

980+
static 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+
1003+
static 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+
1032+
static 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+
9691055
int dss_mgr_enable(struct omap_overlay_manager *mgr)
9701056
{
9711057
struct mgr_priv_data *mp = get_mgr_priv(mgr);
9721058
unsigned long flags;
9731059
int r;
1060+
bool fifo_merge;
9741061

9751062
mutex_lock(&apply_lock);
9761063

@@ -988,11 +1075,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
9881075
goto err;
9891076
}
9901077

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);
9921083

9931084
dss_write_regs();
9941085
dss_set_go_bits();
9951086

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+
9961095
if (!mgr_manual_update(mgr))
9971096
mp->updating = true;
9981097

@@ -1017,6 +1116,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
10171116
{
10181117
struct mgr_priv_data *mp = get_mgr_priv(mgr);
10191118
unsigned long flags;
1119+
bool fifo_merge;
10201120

10211121
mutex_lock(&apply_lock);
10221122

@@ -1031,8 +1131,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
10311131
mp->updating = false;
10321132
mp->enabled = false;
10331133

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+
10341141
spin_unlock_irqrestore(&data_lock, flags);
10351142

1143+
wait_pending_extra_info_updates();
10361144
out:
10371145
mutex_unlock(&apply_lock);
10381146
}
@@ -1284,6 +1392,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
12841392
{
12851393
struct ovl_priv_data *op = get_ovl_priv(ovl);
12861394
unsigned long flags;
1395+
bool fifo_merge;
12871396
int r;
12881397

12891398
mutex_lock(&apply_lock);
@@ -1309,7 +1418,22 @@ int dss_ovl_enable(struct omap_overlay *ovl)
13091418
goto err2;
13101419
}
13111420

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);
13131437

13141438
op->enabling = false;
13151439
dss_apply_ovl_enable(ovl, true);
@@ -1319,6 +1443,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)
13191443

13201444
spin_unlock_irqrestore(&data_lock, flags);
13211445

1446+
/* wait for overlay to be enabled */
1447+
wait_pending_extra_info_updates();
1448+
13221449
mutex_unlock(&apply_lock);
13231450

13241451
return 0;
@@ -1334,6 +1461,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
13341461
{
13351462
struct ovl_priv_data *op = get_ovl_priv(ovl);
13361463
unsigned long flags;
1464+
bool fifo_merge;
13371465
int r;
13381466

13391467
mutex_lock(&apply_lock);
@@ -1348,14 +1476,34 @@ int dss_ovl_disable(struct omap_overlay *ovl)
13481476
goto err;
13491477
}
13501478

1479+
/* step 1: disable the overlay */
13511480
spin_lock_irqsave(&data_lock, flags);
13521481

13531482
dss_apply_ovl_enable(ovl, false);
1483+
13541484
dss_write_regs();
13551485
dss_set_go_bits();
13561486

13571487
spin_unlock_irqrestore(&data_lock, flags);
13581488

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+
13591507
mutex_unlock(&apply_lock);
13601508

13611509
return 0;

0 commit comments

Comments
 (0)