Skip to content

Commit

Permalink
Merge branch 'archit/set-timing-work'
Browse files Browse the repository at this point in the history
An overlay manager's timings (the manager size, and blanking parameters
if an LCD manager) are DISPC shadow registers, and they should hence
follow the correct programming model.

This series makes the video timings an extra_info parameter in manager's
private data. The interface drivers now apply the timings instead of
directly writing to registers.

This change also prevents the need to use display resolution for overlay
checks, hence making some of the APPLY functions less dependent on the
display. Some DISPC functions that needed display width can also use
these privately stored timings.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
  • Loading branch information
Tomi Valkeinen committed May 9, 2012
2 parents 408d9db + 81ab95b commit 1dfafbc
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 90 deletions.
132 changes: 100 additions & 32 deletions drivers/video/omap2/dss/apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ struct mgr_priv_data {

/* If true, a display is enabled using this manager */
bool enabled;

bool extra_info_dirty;
bool shadow_extra_info_dirty;

struct omap_video_timings timings;
};

static struct {
Expand Down Expand Up @@ -176,7 +181,7 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
}

static int dss_check_settings_low(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev, bool applying)
bool applying)
{
struct omap_overlay_info *oi;
struct omap_overlay_manager_info *mi;
Expand All @@ -187,6 +192,9 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,

mp = get_mgr_priv(mgr);

if (!mp->enabled)
return 0;

if (applying && mp->user_info_dirty)
mi = &mp->user_info;
else
Expand All @@ -206,26 +214,24 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,
ois[ovl->id] = oi;
}

return dss_mgr_check(mgr, dssdev, mi, ois);
return dss_mgr_check(mgr, mi, &mp->timings, ois);
}

/*
* check manager and overlay settings using overlay_info from data->info
*/
static int dss_check_settings(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev)
static int dss_check_settings(struct omap_overlay_manager *mgr)
{
return dss_check_settings_low(mgr, dssdev, false);
return dss_check_settings_low(mgr, false);
}

/*
* check manager and overlay settings using overlay_info from ovl->info if
* dirty and from data->info otherwise
*/
static int dss_check_settings_apply(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev)
static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
{
return dss_check_settings_low(mgr, dssdev, true);
return dss_check_settings_low(mgr, true);
}

static bool need_isr(void)
Expand Down Expand Up @@ -261,6 +267,20 @@ static bool need_isr(void)
if (mp->shadow_info_dirty)
return true;

/*
* NOTE: we don't check extra_info flags for disabled
* managers, once the manager is enabled, the extra_info
* related manager changes will be taken in by HW.
*/

/* to write new values to registers */
if (mp->extra_info_dirty)
return true;

/* to set GO bit */
if (mp->shadow_extra_info_dirty)
return true;

list_for_each_entry(ovl, &mgr->overlays, list) {
struct ovl_priv_data *op;

Expand Down Expand Up @@ -305,7 +325,7 @@ static bool need_go(struct omap_overlay_manager *mgr)

mp = get_mgr_priv(mgr);

if (mp->shadow_info_dirty)
if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
return true;

list_for_each_entry(ovl, &mgr->overlays, list) {
Expand All @@ -320,29 +340,32 @@ static bool need_go(struct omap_overlay_manager *mgr)
/* returns true if an extra_info field is currently being updated */
static bool extra_info_update_ongoing(void)
{
const int num_ovls = omap_dss_get_num_overlays();
struct ovl_priv_data *op;
struct omap_overlay *ovl;
struct mgr_priv_data *mp;
const int num_mgrs = dss_feat_get_num_mgrs();
int i;

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

if (!ovl->manager)
continue;
for (i = 0; i < num_mgrs; ++i) {
struct omap_overlay_manager *mgr;
struct omap_overlay *ovl;
struct mgr_priv_data *mp;

mp = get_mgr_priv(ovl->manager);
mgr = omap_dss_get_overlay_manager(i);
mp = get_mgr_priv(mgr);

if (!mp->enabled)
continue;

if (!mp->updating)
continue;

if (op->extra_info_dirty || op->shadow_extra_info_dirty)
if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
return true;

list_for_each_entry(ovl, &mgr->overlays, list) {
struct ovl_priv_data *op = get_ovl_priv(ovl);

if (op->extra_info_dirty || op->shadow_extra_info_dirty)
return true;
}
}

return false;
Expand Down Expand Up @@ -525,11 +548,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)

oi = &op->info;

mp = get_mgr_priv(ovl->manager);

replication = dss_use_replication(ovl->manager->device, oi->color_mode);

ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC;

r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
r = dispc_ovl_setup(ovl->id, oi, ilace, replication, &mp->timings);
if (r) {
/*
* We can't do much here, as this function can be called from
Expand All @@ -543,8 +568,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
return;
}

mp = get_mgr_priv(ovl->manager);

op->info_dirty = false;
if (mp->updating)
op->shadow_info_dirty = true;
Expand Down Expand Up @@ -601,6 +624,22 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
}
}

static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);

DSSDBGF("%d", mgr->id);

if (!mp->extra_info_dirty)
return;

dispc_mgr_set_timings(mgr->id, &mp->timings);

mp->extra_info_dirty = false;
if (mp->updating)
mp->shadow_extra_info_dirty = true;
}

static void dss_write_regs_common(void)
{
const int num_mgrs = omap_dss_get_num_overlay_managers();
Expand Down Expand Up @@ -646,14 +685,15 @@ static void dss_write_regs(void)
if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
continue;

r = dss_check_settings(mgr, mgr->device);
r = dss_check_settings(mgr);
if (r) {
DSSERR("cannot write registers for manager %s: "
"illegal configuration\n", mgr->name);
continue;
}

dss_mgr_write_regs(mgr);
dss_mgr_write_regs_extra(mgr);
}
}

Expand Down Expand Up @@ -693,6 +733,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)

mp = get_mgr_priv(mgr);
mp->shadow_info_dirty = false;
mp->shadow_extra_info_dirty = false;

list_for_each_entry(ovl, &mgr->overlays, list) {
op = get_ovl_priv(ovl);
Expand All @@ -711,14 +752,15 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)

WARN_ON(mp->updating);

r = dss_check_settings(mgr, mgr->device);
r = dss_check_settings(mgr);
if (r) {
DSSERR("cannot start manual update: illegal configuration\n");
spin_unlock_irqrestore(&data_lock, flags);
return;
}

dss_mgr_write_regs(mgr);
dss_mgr_write_regs_extra(mgr);

dss_write_regs_common();

Expand Down Expand Up @@ -857,7 +899,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)

spin_lock_irqsave(&data_lock, flags);

r = dss_check_settings_apply(mgr, mgr->device);
r = dss_check_settings_apply(mgr);
if (r) {
spin_unlock_irqrestore(&data_lock, flags);
DSSERR("failed to apply settings: illegal configuration.\n");
Expand Down Expand Up @@ -918,14 +960,11 @@ 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 fifo_low, fifo_high;

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

dssdev = ovl->manager->device;

dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
use_fifo_merge);

Expand Down Expand Up @@ -1050,7 +1089,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)

mp->enabled = true;

r = dss_check_settings(mgr, mgr->device);
r = dss_check_settings(mgr);
if (r) {
DSSERR("failed to enable manager %d: check_settings failed\n",
mgr->id);
Expand Down Expand Up @@ -1225,6 +1264,35 @@ int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
return r;
}

static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
struct omap_video_timings *timings)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);

mp->timings = *timings;
mp->extra_info_dirty = true;
}

void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
struct omap_video_timings *timings)
{
unsigned long flags;

mutex_lock(&apply_lock);

spin_lock_irqsave(&data_lock, flags);

dss_apply_mgr_timings(mgr, timings);

dss_write_regs();
dss_set_go_bits();

spin_unlock_irqrestore(&data_lock, flags);

wait_pending_extra_info_updates();

mutex_unlock(&apply_lock);
}

int dss_ovl_set_info(struct omap_overlay *ovl,
struct omap_overlay_info *info)
Expand Down Expand Up @@ -1393,7 +1461,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)

op->enabling = true;

r = dss_check_settings(ovl->manager, ovl->manager->device);
r = dss_check_settings(ovl->manager);
if (r) {
DSSERR("failed to enable overlay %d: check_settings failed\n",
ovl->id);
Expand Down
Loading

0 comments on commit 1dfafbc

Please sign in to comment.