Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 284958
b: refs/heads/master
c: 3951835
h: refs/heads/master
v: v3
  • Loading branch information
Tomi Valkeinen committed Dec 2, 2011
1 parent 51ac467 commit f5fad4e
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f17d04fbbb201c05700359e94e2747c210f99852
refs/heads/master: 39518356ccd6e439abae24e1a24d84dcd12ff207
215 changes: 212 additions & 3 deletions trunk/drivers/video/omap2/dss/apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,169 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
}

/* Check if overlay parameters are compatible with display */
static int dss_ovl_check(struct omap_overlay *ovl,
struct omap_overlay_info *info, struct omap_dss_device *dssdev)
{
u16 outw, outh;
u16 dw, dh;

if (dssdev == NULL)
return 0;

dssdev->driver->get_resolution(dssdev, &dw, &dh);

if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
outw = info->width;
outh = info->height;
} else {
if (info->out_width == 0)
outw = info->width;
else
outw = info->out_width;

if (info->out_height == 0)
outh = info->height;
else
outh = info->out_height;
}

if (dw < info->pos_x + outw) {
DSSERR("overlay %d horizontally not inside the display area "
"(%d + %d >= %d)\n",
ovl->id, info->pos_x, outw, dw);
return -EINVAL;
}

if (dh < info->pos_y + outh) {
DSSERR("overlay %d vertically not inside the display area "
"(%d + %d >= %d)\n",
ovl->id, info->pos_y, outh, dh);
return -EINVAL;
}

return 0;
}

static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
struct omap_overlay_info **overlay_infos)
{
struct omap_overlay *ovl1, *ovl2;
struct ovl_priv_data *op1, *op2;
struct omap_overlay_info *info1, *info2;

list_for_each_entry(ovl1, &mgr->overlays, list) {
op1 = get_ovl_priv(ovl1);
info1 = overlay_infos[ovl1->id];

if (info1 == NULL)
continue;

list_for_each_entry(ovl2, &mgr->overlays, list) {
if (ovl1 == ovl2)
continue;

op2 = get_ovl_priv(ovl2);
info2 = overlay_infos[ovl2->id];

if (info2 == NULL)
continue;

if (info1->zorder == info2->zorder) {
DSSERR("overlays %d and %d have the same "
"zorder %d\n",
ovl1->id, ovl2->id, info1->zorder);
return -EINVAL;
}
}
}

return 0;
}

static int dss_mgr_check(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev,
struct omap_overlay_manager_info *info,
struct omap_overlay_info **overlay_infos)
{
struct omap_overlay *ovl;
int r;

if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
r = dss_mgr_check_zorder(mgr, overlay_infos);
if (r)
return r;
}

list_for_each_entry(ovl, &mgr->overlays, list) {
struct omap_overlay_info *oi;
int r;

oi = overlay_infos[ovl->id];

if (oi == NULL)
continue;

r = dss_ovl_check(ovl, oi, dssdev);
if (r)
return r;
}

return 0;
}
static int dss_check_settings_low(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev, bool applying)
{
struct omap_overlay_info *oi;
struct omap_overlay_manager_info *mi;
struct omap_overlay *ovl;
struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
struct ovl_priv_data *op;
struct mgr_priv_data *mp;

mp = get_mgr_priv(mgr);

if (applying && mp->user_info_dirty)
mi = &mp->user_info;
else
mi = &mp->info;

/* collect the infos to be tested into the array */
list_for_each_entry(ovl, &mgr->overlays, list) {
op = get_ovl_priv(ovl);

if (!op->enabled)
oi = NULL;
else if (applying && op->user_info_dirty)
oi = &op->user_info;
else
oi = &op->info;

ois[ovl->id] = oi;
}

return dss_mgr_check(mgr, dssdev, mi, 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)
{
return dss_check_settings_low(mgr, dssdev, 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)
{
return dss_check_settings_low(mgr, dssdev, true);
}

static bool need_isr(void)
{
const int num_mgrs = dss_feat_get_num_mgrs();
Expand Down Expand Up @@ -517,13 +680,21 @@ static void dss_write_regs(void)
for (i = 0; i < num_mgrs; ++i) {
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;
int r;

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

if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
continue;

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

dss_mgr_write_regs(mgr);

if (need_go(mgr)) {
Expand All @@ -541,11 +712,19 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
int r;

spin_lock_irqsave(&data_lock, flags);

WARN_ON(mp->updating);

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

dss_mgr_write_regs(mgr);

mp->updating = true;
Expand Down Expand Up @@ -690,11 +869,19 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
{
unsigned long flags;
struct omap_overlay *ovl;
int r;

DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);

spin_lock_irqsave(&data_lock, flags);

r = dss_check_settings_apply(mgr, mgr->device);
if (r) {
spin_unlock_irqrestore(&data_lock, flags);
DSSERR("failed to apply settings: illegal configuration.\n");
return r;
}

/* Configure overlays */
list_for_each_entry(ovl, &mgr->overlays, list)
omap_dss_mgr_apply_ovl(ovl);
Expand Down Expand Up @@ -784,6 +971,7 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
int r;

mutex_lock(&apply_lock);

Expand All @@ -792,6 +980,16 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)

spin_lock_irqsave(&data_lock, flags);

mp->enabled = true;
r = dss_check_settings(mgr, mgr->device);
mp->enabled = false;
if (r) {
DSSERR("failed to enable manager %d: check_settings failed\n",
mgr->id);
spin_unlock_irqrestore(&data_lock, flags);
goto out;
}

mp->enabled = true;

dss_mgr_setup_fifos(mgr);
Expand Down Expand Up @@ -1142,16 +1340,25 @@ int dss_ovl_enable(struct omap_overlay *ovl)

if (op->enabled) {
r = 0;
goto err;
goto err1;
}

if (ovl->manager == NULL || ovl->manager->device == NULL) {
r = -EINVAL;
goto err;
goto err1;
}

spin_lock_irqsave(&data_lock, flags);

op->enabled = true;
r = dss_check_settings(ovl->manager, ovl->manager->device);
op->enabled = false;
if (r) {
DSSERR("failed to enable overlay %d: check_settings failed\n",
ovl->id);
goto err2;
}

dss_apply_ovl_enable(ovl, true);

dss_ovl_setup_fifo(ovl);
Expand All @@ -1163,7 +1370,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)
mutex_unlock(&apply_lock);

return 0;
err:
err2:
spin_unlock_irqrestore(&data_lock, flags);
err1:
mutex_unlock(&apply_lock);
return r;
}
Expand Down

0 comments on commit f5fad4e

Please sign in to comment.