Skip to content

Commit

Permalink
Merge branch 'work/fifomerge'
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomi Valkeinen committed Jan 25, 2012
2 parents 6e2a14d + e0e405b commit 5e36097
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 66 deletions.
221 changes: 191 additions & 30 deletions drivers/video/omap2/dss/apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ static struct {
struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];

bool fifo_merge_dirty;
bool fifo_merge;

bool irq_enabled;
} dss_data;

Expand Down Expand Up @@ -585,11 +588,40 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
}
}

static void dss_write_regs_common(void)
{
const int num_mgrs = omap_dss_get_num_overlay_managers();
int i;

if (!dss_data.fifo_merge_dirty)
return;

for (i = 0; i < num_mgrs; ++i) {
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;

mgr = omap_dss_get_overlay_manager(i);
mp = get_mgr_priv(mgr);

if (mp->enabled) {
if (dss_data.fifo_merge_dirty) {
dispc_enable_fifomerge(dss_data.fifo_merge);
dss_data.fifo_merge_dirty = false;
}

if (mp->updating)
mp->shadow_info_dirty = true;
}
}
}

static void dss_write_regs(void)
{
const int num_mgrs = omap_dss_get_num_overlay_managers();
int i;

dss_write_regs_common();

for (i = 0; i < num_mgrs; ++i) {
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;
Expand Down Expand Up @@ -659,6 +691,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)

dss_mgr_write_regs(mgr);

dss_write_regs_common();

mp->updating = true;

if (!dss_data.irq_enabled && need_isr())
Expand Down Expand Up @@ -859,45 +893,35 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
op->extra_info_dirty = true;
}

static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
static void dss_apply_fifo_merge(bool use_fifo_merge)
{
if (dss_data.fifo_merge == use_fifo_merge)
return;

dss_data.fifo_merge = use_fifo_merge;
dss_data.fifo_merge_dirty = true;
}

static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
bool use_fifo_merge)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
struct omap_dss_device *dssdev;
u32 size, burst_size;
u32 fifo_low, fifo_high;

if (!op->enabled && !op->enabling)
return;

dssdev = ovl->manager->device;

size = dispc_ovl_get_fifo_size(ovl->id);

burst_size = dispc_ovl_get_burst_size(ovl->id);

switch (dssdev->type) {
case OMAP_DISPLAY_TYPE_DPI:
case OMAP_DISPLAY_TYPE_DBI:
case OMAP_DISPLAY_TYPE_SDI:
case OMAP_DISPLAY_TYPE_VENC:
case OMAP_DISPLAY_TYPE_HDMI:
default_get_overlay_fifo_thresholds(ovl->id, size,
burst_size, &fifo_low, &fifo_high);
break;
#ifdef CONFIG_OMAP2_DSS_DSI
case OMAP_DISPLAY_TYPE_DSI:
dsi_get_overlay_fifo_thresholds(ovl->id, size,
burst_size, &fifo_low, &fifo_high);
break;
#endif
default:
BUG();
}
dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
use_fifo_merge);

dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
}

static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
bool use_fifo_merge)
{
struct omap_overlay *ovl;
struct mgr_priv_data *mp;
Expand All @@ -908,26 +932,102 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
return;

list_for_each_entry(ovl, &mgr->overlays, list)
dss_ovl_setup_fifo(ovl);
dss_ovl_setup_fifo(ovl, use_fifo_merge);
}

static void dss_setup_fifos(bool use_fifo_merge)
{
const int num_mgrs = omap_dss_get_num_overlay_managers();
struct omap_overlay_manager *mgr;
int i;

for (i = 0; i < num_mgrs; ++i) {
mgr = omap_dss_get_overlay_manager(i);
dss_mgr_setup_fifos(mgr, use_fifo_merge);
}
}

static void dss_setup_fifos(void)
static int get_num_used_managers(void)
{
const int num_mgrs = omap_dss_get_num_overlay_managers();
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;
int i;
int enabled_mgrs;

enabled_mgrs = 0;

for (i = 0; i < num_mgrs; ++i) {
mgr = omap_dss_get_overlay_manager(i);
dss_mgr_setup_fifos(mgr);
mp = get_mgr_priv(mgr);

if (!mp->enabled)
continue;

enabled_mgrs++;
}

return enabled_mgrs;
}

static int get_num_used_overlays(void)
{
const int num_ovls = omap_dss_get_num_overlays();
struct omap_overlay *ovl;
struct ovl_priv_data *op;
struct mgr_priv_data *mp;
int i;
int enabled_ovls;

enabled_ovls = 0;

for (i = 0; i < num_ovls; ++i) {
ovl = omap_dss_get_overlay(i);
op = get_ovl_priv(ovl);

if (!op->enabled && !op->enabling)
continue;

mp = get_mgr_priv(ovl->manager);

if (!mp->enabled)
continue;

enabled_ovls++;
}

return enabled_ovls;
}

static bool get_use_fifo_merge(void)
{
int enabled_mgrs = get_num_used_managers();
int enabled_ovls = get_num_used_overlays();

if (!dss_has_feature(FEAT_FIFO_MERGE))
return false;

/*
* In theory the only requirement for fifomerge is enabled_ovls <= 1.
* However, if we have two managers enabled and set/unset the fifomerge,
* we need to set the GO bits in particular sequence for the managers,
* and wait in between.
*
* This is rather difficult as new apply calls can happen at any time,
* so we simplify the problem by requiring also that enabled_mgrs <= 1.
* In practice this shouldn't matter, because when only one overlay is
* enabled, most likely only one output is enabled.
*/

return enabled_mgrs <= 1 && enabled_ovls <= 1;
}

int dss_mgr_enable(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
int r;
bool fifo_merge;

mutex_lock(&apply_lock);

Expand All @@ -945,11 +1045,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
goto err;
}

dss_setup_fifos();
/* step 1: setup fifos/fifomerge before enabling the manager */

fifo_merge = get_use_fifo_merge();
dss_setup_fifos(fifo_merge);
dss_apply_fifo_merge(fifo_merge);

dss_write_regs();
dss_set_go_bits();

spin_unlock_irqrestore(&data_lock, flags);

/* wait until fifo config is in */
wait_pending_extra_info_updates();

/* step 2: enable the manager */
spin_lock_irqsave(&data_lock, flags);

if (!mgr_manual_update(mgr))
mp->updating = true;

Expand All @@ -974,6 +1086,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
bool fifo_merge;

mutex_lock(&apply_lock);

Expand All @@ -988,8 +1101,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
mp->updating = false;
mp->enabled = false;

fifo_merge = get_use_fifo_merge();
dss_setup_fifos(fifo_merge);
dss_apply_fifo_merge(fifo_merge);

dss_write_regs();
dss_set_go_bits();

spin_unlock_irqrestore(&data_lock, flags);

wait_pending_extra_info_updates();
out:
mutex_unlock(&apply_lock);
}
Expand Down Expand Up @@ -1241,6 +1362,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
bool fifo_merge;
int r;

mutex_lock(&apply_lock);
Expand All @@ -1266,7 +1388,22 @@ int dss_ovl_enable(struct omap_overlay *ovl)
goto err2;
}

dss_setup_fifos();
/* step 1: configure fifos/fifomerge for currently enabled ovls */

fifo_merge = get_use_fifo_merge();
dss_setup_fifos(fifo_merge);
dss_apply_fifo_merge(fifo_merge);

dss_write_regs();
dss_set_go_bits();

spin_unlock_irqrestore(&data_lock, flags);

/* wait for fifo configs to go in */
wait_pending_extra_info_updates();

/* step 2: enable the overlay */
spin_lock_irqsave(&data_lock, flags);

op->enabling = false;
dss_apply_ovl_enable(ovl, true);
Expand All @@ -1276,6 +1413,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)

spin_unlock_irqrestore(&data_lock, flags);

/* wait for overlay to be enabled */
wait_pending_extra_info_updates();

mutex_unlock(&apply_lock);

return 0;
Expand All @@ -1291,6 +1431,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
bool fifo_merge;
int r;

mutex_lock(&apply_lock);
Expand All @@ -1305,14 +1446,34 @@ int dss_ovl_disable(struct omap_overlay *ovl)
goto err;
}

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

dss_apply_ovl_enable(ovl, false);

dss_write_regs();
dss_set_go_bits();

spin_unlock_irqrestore(&data_lock, flags);

/* wait for the overlay to be disabled */
wait_pending_extra_info_updates();

/* step 2: configure fifos/fifomerge */
spin_lock_irqsave(&data_lock, flags);

fifo_merge = get_use_fifo_merge();
dss_setup_fifos(fifo_merge);
dss_apply_fifo_merge(fifo_merge);

dss_write_regs();
dss_set_go_bits();

spin_unlock_irqrestore(&data_lock, flags);

/* wait for fifo config to go in */
wait_pending_extra_info_updates();

mutex_unlock(&apply_lock);

return 0;
Expand Down
Loading

0 comments on commit 5e36097

Please sign in to comment.