diff options
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r-- | drivers/video/omap2/dsscomp/base.c | 6 | ||||
-rw-r--r-- | drivers/video/omap2/dsscomp/gralloc.c | 159 | ||||
-rw-r--r-- | drivers/video/omap2/dsscomp/queue.c | 1 |
3 files changed, 114 insertions, 52 deletions
diff --git a/drivers/video/omap2/dsscomp/base.c b/drivers/video/omap2/dsscomp/base.c index b54fc50..7d208e1 100644 --- a/drivers/video/omap2/dsscomp/base.c +++ b/drivers/video/omap2/dsscomp/base.c @@ -478,6 +478,8 @@ void dump_total_comp_info(struct dsscomp_dev *cdev, struct dsscomp_setup_dispc_data *d, const char *phase) { + int i; + if (!(debug & DEBUG_COMPOSITIONS)) return; @@ -486,6 +488,8 @@ void dump_total_comp_info(struct dsscomp_dev *cdev, (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-', (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-', (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-'); - print_mgr_info(cdev, &d->mgr); + + for (i = 0; i < d->num_mgrs && i < ARRAY_SIZE(d->mgrs); i++) + print_mgr_info(cdev, d->mgrs + i); printk("n=%d\n", d->num_ovls); } diff --git a/drivers/video/omap2/dsscomp/gralloc.c b/drivers/video/omap2/dsscomp/gralloc.c index fe3e2a2..e2a9515 100644 --- a/drivers/video/omap2/dsscomp/gralloc.c +++ b/drivers/video/omap2/dsscomp/gralloc.c @@ -37,7 +37,7 @@ struct dsscomp_gralloc_t { /* queued gralloc compositions */ static LIST_HEAD(flip_queue); -static u32 ovl_set_mask; +static u32 ovl_use_mask[MAX_MANAGERS]; static void unpin_tiler_blocks(struct list_head *slots) { @@ -127,10 +127,15 @@ int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d, int r = 0; struct omap_dss_device *dev; struct omap_overlay_manager *mgr; - dsscomp_t comp; - u32 ovl_new_set_mask = 0; + dsscomp_t comp[MAX_MANAGERS]; + u32 ovl_new_use_mask[MAX_MANAGERS]; + u32 mgr_set_mask = 0; + u32 ovl_set_mask = 0; + + u32 channels[ARRAY_SIZE(d->mgrs)], ch; int skip; struct dsscomp_gralloc_t *gsync; + struct dss2_rect_t win = { .w = 0 }; /* reserve tiler areas if not already done so */ dsscomp_gralloc_init(cdev); @@ -162,47 +167,100 @@ int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d, mutex_unlock(&mtx); + d->num_mgrs = min(d->num_mgrs, (u16) ARRAY_SIZE(d->mgrs)); + d->num_ovls = min(d->num_ovls, (u16) ARRAY_SIZE(d->ovls)); + + memset(comp, 0, sizeof(comp)); + memset(ovl_new_use_mask, 0, sizeof(ovl_new_use_mask)); + if (skip) - goto skip_mgr; + goto skip_comp; + + d->mode = DSSCOMP_SETUP_DISPLAY; + + /* mark managers we are using */ + for (i = 0; i < d->num_mgrs; i++) { + /* verify display is valid & connected, ignore if not */ + if (d->mgrs[i].ix >= cdev->num_displays) + continue; + dev = cdev->displays[d->mgrs[i].ix]; + if (!dev) { + dev_warn(DEV(cdev), "failed to get display%d\n", + d->mgrs[i].ix); + continue; + } + mgr = dev->manager; + if (!mgr) { + dev_warn(DEV(cdev), "no manager for display%d\n", + d->mgrs[i].ix); + continue; + } + channels[i] = ch = mgr->id; + mgr_set_mask |= 1 << ch; - /* verify display is valid and connected */ - if (d->mgr.ix >= cdev->num_displays) { - r = -EINVAL; - goto skip_mgr; - } - dev = cdev->displays[d->mgr.ix]; - if (!dev) { - r = -EINVAL; - goto skip_mgr; - } - mgr = dev->manager; - if (!mgr) { - r = -ENODEV; - goto skip_mgr; + /* swap red & blue if requested */ + if (d->mgrs[i].swap_rb) + swap_rb_in_mgr_info(d->mgrs + i); } - comp = dsscomp_new(mgr); - if (IS_ERR(comp)) { - r = PTR_ERR(comp); - goto skip_mgr; - } + /* create dsscomp objects for set managers (including active ones) */ + for (ch = 0; ch < MAX_MANAGERS; ch++) { + if (!(mgr_set_mask & (1 << ch)) && !ovl_use_mask[ch]) + continue; - comp->frm.mode = DSSCOMP_SETUP_DISPLAY; - comp->must_apply = true; + mgr = cdev->mgrs[ch]; - /* swap red & blue if requested */ - if (d->mgr.swap_rb) { - swap_rb_in_mgr_info(&d->mgr); - for (i = 0; i < d->num_ovls; i++) - swap_rb_in_ovl_info(d->ovls + i); + comp[ch] = dsscomp_new(mgr); + if (IS_ERR(comp[ch])) { + comp[ch] = NULL; + dev_warn(DEV(cdev), "failed to get composition on %s\n", + mgr->name); + continue; + } + + /* set basic manager information for blanked managers */ + if (!(mgr_set_mask & (1 << ch))) { + struct dss2_mgr_info mi = { + .alpha_blending = true, + .ix = comp[ch]->frm.mgr.ix, + }; + dsscomp_set_mgr(comp[ch], &mi); + } + + comp[ch]->must_apply = true; + r = dsscomp_setup(comp[ch], d->mode, win); + if (r) + dev_err(DEV(cdev), "failed to setup comp (%d)\n", r); + } + + /* configure manager data from gralloc composition */ + for (i = 0; i < d->num_mgrs; i++) { + ch = channels[i]; + r = dsscomp_set_mgr(comp[ch], d->mgrs + i); + if (r) + dev_err(DEV(cdev), "failed to set mgr%d (%d)\n", ch, r); } /* NOTE: none of the dsscomp sets should fail as composition is new */ - r = dsscomp_set_mgr(comp, &d->mgr); - if (r) - dev_err(DEV(cdev), "failed to set mgr (%d)\n", r); for (i = 0; i < d->num_ovls; i++) { struct dss2_ovl_info *oi = d->ovls + i; + u32 mgr_ix = oi->cfg.mgr_ix; + + /* verify manager index */ + if (mgr_ix >= d->num_mgrs) { + dev_err(DEV(cdev), "invalid manager for ovl%d\n", + oi->cfg.ix); + continue; + } + ch = channels[mgr_ix]; + + /* skip overlays on compositions we could not create */ + if (!comp[ch]) + continue; + + /* swap red & blue if requested */ + if (d->mgrs[mgr_ix].swap_rb) + swap_rb_in_ovl_info(d->ovls + i); /* map non-TILER buffers to 1D */ if (pas[i] && oi->cfg.enabled) { @@ -228,43 +286,44 @@ int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d, } if (oi->cfg.enabled) - ovl_new_set_mask |= 1 << oi->cfg.ix; + ovl_new_use_mask[ch] |= 1 << oi->cfg.ix; - r = dsscomp_set_ovl(comp, oi); + r = dsscomp_set_ovl(comp[ch], oi); if (r) dev_err(DEV(cdev), "failed to set ovl%d (%d)\n", oi->cfg.ix, r); + else + ovl_set_mask |= 1 << oi->cfg.ix; } - r = dsscomp_setup(comp, d->mode, d->win); - if (r) - dev_err(DEV(cdev), "failed to setup comp (%d)\n", r); - - if (r) { - dsscomp_drop(comp); - } else { + for (ch = 0; ch < MAX_MANAGERS; ch++) { /* disable all overlays not specifically set from prior frame */ - u32 mask = ovl_set_mask & ~ovl_new_set_mask; + u32 mask = ovl_use_mask[ch] & ~ovl_set_mask; + + if (!comp[ch]) + continue; + while (mask) { struct dss2_ovl_info oi = { .cfg.zonly = true, .cfg.enabled = false, .cfg.ix = fls(mask) - 1, }; - dsscomp_set_ovl(comp, &oi); + dsscomp_set_ovl(comp[ch], &oi); mask &= ~(1 << oi.cfg.ix); } - comp->extra_cb = dsscomp_gralloc_cb; - comp->extra_cb_data = gsync; + /* associate dsscomp objects with this gralloc composition */ + comp[ch]->extra_cb = dsscomp_gralloc_cb; + comp[ch]->extra_cb_data = gsync; atomic_inc(&gsync->refs); - r = dsscomp_delayed_apply(comp); + r = dsscomp_delayed_apply(comp[ch]); if (r) dev_err(DEV(cdev), "failed to apply comp (%d)\n", r); else - ovl_set_mask = ovl_new_set_mask; + ovl_use_mask[ch] = ovl_new_use_mask[ch]; } -skip_mgr: +skip_comp: /* release sync object ref - this completes unapplied compositions */ dsscomp_gralloc_cb(gsync, DSS_COMPLETION_RELEASED); @@ -284,7 +343,7 @@ static void dsscomp_early_suspend_cb(void *data, int status) static void dsscomp_early_suspend(struct early_suspend *h) { struct dsscomp_setup_dispc_data d = { - .mgr.alpha_blending = 1, + .num_mgrs = 0, }; int err; diff --git a/drivers/video/omap2/dsscomp/queue.c b/drivers/video/omap2/dsscomp/queue.c index 0f8c8a6..b6f625b 100644 --- a/drivers/video/omap2/dsscomp/queue.c +++ b/drivers/video/omap2/dsscomp/queue.c @@ -579,7 +579,6 @@ skip_ovl_set: done: return r; } -EXPORT_SYMBOL(dsscomp_apply); struct dsscomp_apply_work { struct work_struct work; |