/drivers/video/omap2/dsscomp/queue.c
https://bitbucket.org/slukk/jb-tsm-kernel-4.2 · C · 807 lines · 567 code · 124 blank · 116 comment · 144 complexity · 0c995781fe14bc13eaeb49080eae0339 MD5 · raw file
- /*
- * linux/drivers/video/omap2/dsscomp/queue.c
- *
- * DSS Composition queueing support
- *
- * Copyright (C) 2011 Texas Instruments, Inc
- * Author: Lajos Molnar <molnar@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <linux/kernel.h>
- #include <linux/vmalloc.h>
- #include <linux/sched.h>
- #include <linux/slab.h>
- #include <linux/ratelimit.h>
- #include <video/omapdss.h>
- #include <video/dsscomp.h>
- #include <plat/dsscomp.h>
- #include <linux/debugfs.h>
- #include "dsscomp.h"
- /* queue state */
- static DEFINE_MUTEX(mtx);
- /* free overlay structs */
- struct maskref {
- u32 mask;
- u32 refs[MAX_OVERLAYS];
- };
- static struct {
- struct workqueue_struct *apply_workq;
- u32 ovl_mask; /* overlays used on this display */
- struct maskref ovl_qmask; /* overlays queued to this display */
- bool blanking;
- } mgrq[MAX_MANAGERS];
- static struct workqueue_struct *cb_wkq; /* callback work queue */
- static struct dsscomp_dev *cdev;
- #ifdef CONFIG_DEBUG_FS
- LIST_HEAD(dbg_comps);
- DEFINE_MUTEX(dbg_mtx);
- #endif
- #ifdef CONFIG_DSSCOMP_DEBUG_LOG
- struct dbg_event_t dbg_events[128];
- u32 dbg_event_ix;
- #endif
- static inline void __log_state(dsscomp_t c, void *fn, u32 ev)
- {
- #ifdef CONFIG_DSSCOMP_DEBUG_LOG
- if (c->dbg_used < ARRAY_SIZE(c->dbg_log)) {
- u32 t = (u32) ktime_to_ms(ktime_get());
- c->dbg_log[c->dbg_used].t = t;
- c->dbg_log[c->dbg_used++].state = c->state;
- __log_event(20 * c->ix + 20, t, c, ev ? "%pf on %s" : "%pf",
- (u32) fn, (u32) log_status_str(ev));
- }
- #endif
- }
- #define log_state(c, fn, ev) DO_IF_DEBUG_FS(__log_state(c, fn, ev))
- static inline void maskref_incbit(struct maskref *om, u32 ix)
- {
- om->refs[ix]++;
- om->mask |= 1 << ix;
- }
- static void maskref_decmask(struct maskref *om, u32 mask)
- {
- while (mask) {
- u32 ix = fls(mask) - 1, m = 1 << ix;
- if (!--om->refs[ix])
- om->mask &= ~m;
- mask &= ~m;
- }
- }
- /*
- * ===========================================================================
- * EXIT
- * ===========================================================================
- */
- /* Initialize queue structures, and set up state of the displays */
- int dsscomp_queue_init(struct dsscomp_dev *cdev_)
- {
- u32 i, j;
- cdev = cdev_;
- if (ARRAY_SIZE(mgrq) < cdev->num_mgrs)
- return -EINVAL;
- ZERO(mgrq);
- for (i = 0; i < cdev->num_mgrs; i++) {
- struct omap_overlay_manager *mgr;
- mgrq[i].apply_workq = create_singlethread_workqueue("dsscomp_apply");
- if (!mgrq[i].apply_workq)
- goto error;
- /* record overlays on this display */
- mgr = cdev->mgrs[i];
- for (j = 0; j < cdev->num_ovls; j++) {
- if (cdev->ovls[j]->info.enabled &&
- mgr &&
- cdev->ovls[j]->manager == mgr)
- mgrq[i].ovl_mask |= 1 << j;
- }
- }
- cb_wkq = create_singlethread_workqueue("dsscomp_cb");
- if (!cb_wkq)
- goto error;
- return 0;
- error:
- while (i--)
- destroy_workqueue(mgrq[i].apply_workq);
- return -ENOMEM;
- }
- /* get display index from manager */
- static u32 get_display_ix(struct omap_overlay_manager *mgr)
- {
- u32 i;
- /* handle if manager is not attached to a display */
- if (!mgr || !mgr->device)
- return cdev->num_displays;
- /* find manager's display */
- for (i = 0; i < cdev->num_displays; i++)
- if (cdev->displays[i] == mgr->device)
- break;
- return i;
- }
- /*
- * ===========================================================================
- * QUEUING SETUP OPERATIONS
- * ===========================================================================
- */
- /* create a new composition for a display */
- dsscomp_t dsscomp_new(struct omap_overlay_manager *mgr)
- {
- struct dsscomp_data *comp = NULL;
- u32 display_ix = get_display_ix(mgr);
- /* check manager */
- u32 ix = mgr ? mgr->id : cdev->num_mgrs;
- if (ix >= cdev->num_mgrs || display_ix >= cdev->num_displays)
- return ERR_PTR(-EINVAL);
- /* allocate composition */
- comp = kzalloc(sizeof(*comp), GFP_KERNEL);
- if (!comp)
- return NULL;
- /* initialize new composition */
- comp->ix = ix; /* save where this composition came from */
- comp->ovl_mask = comp->ovl_dmask = 0;
- comp->frm.sync_id = 0;
- comp->frm.mgr.ix = display_ix;
- comp->state = DSSCOMP_STATE_ACTIVE;
- DO_IF_DEBUG_FS({
- __log_state(comp, dsscomp_new, 0);
- list_add(&comp->dbg_q, &dbg_comps);
- });
- return comp;
- }
- EXPORT_SYMBOL(dsscomp_new);
- /* returns overlays used in a composition */
- u32 dsscomp_get_ovls(dsscomp_t comp)
- {
- u32 mask;
- mutex_lock(&mtx);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- mask = comp->ovl_mask;
- mutex_unlock(&mtx);
- return mask;
- }
- EXPORT_SYMBOL(dsscomp_get_ovls);
- /* set overlay info */
- int dsscomp_set_ovl(dsscomp_t comp, struct dss2_ovl_info *ovl)
- {
- int r = -EBUSY;
- u32 i, mask, oix, ix;
- struct omap_overlay *o;
- mutex_lock(&mtx);
- BUG_ON(!ovl);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- ix = comp->ix;
- if (ovl->cfg.ix >= cdev->num_ovls) {
- r = -EINVAL;
- goto done;
- }
- /* if overlay is already part of the composition */
- mask = 1 << ovl->cfg.ix;
- if (mask & comp->ovl_mask) {
- /* look up overlay */
- for (oix = 0; oix < comp->frm.num_ovls; oix++) {
- if (comp->ovls[oix].cfg.ix == ovl->cfg.ix)
- break;
- }
- BUG_ON(oix == comp->frm.num_ovls);
- } else {
- /* check if ovl is free to use */
- if (comp->frm.num_ovls >= ARRAY_SIZE(comp->ovls))
- goto done;
- /* not in any other displays queue */
- if (mask & ~mgrq[ix].ovl_qmask.mask) {
- for (i = 0; i < cdev->num_mgrs; i++) {
- if (i == ix)
- continue;
- if (mgrq[i].ovl_qmask.mask & mask)
- goto done;
- }
- }
- /* and disabled (unless forced) if on another manager */
- o = cdev->ovls[ovl->cfg.ix];
- if (o->info.enabled && (!o->manager || o->manager->id != ix))
- goto done;
- /* add overlay to composition & display */
- comp->ovl_mask |= mask;
- oix = comp->frm.num_ovls++;
- maskref_incbit(&mgrq[ix].ovl_qmask, ovl->cfg.ix);
- }
- comp->ovls[oix] = *ovl;
- r = 0;
- done:
- mutex_unlock(&mtx);
- return r;
- }
- EXPORT_SYMBOL(dsscomp_set_ovl);
- /* get overlay info */
- int dsscomp_get_ovl(dsscomp_t comp, u32 ix, struct dss2_ovl_info *ovl)
- {
- int r;
- u32 oix;
- mutex_lock(&mtx);
- BUG_ON(!ovl);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- if (ix >= cdev->num_ovls) {
- r = -EINVAL;
- } else if (comp->ovl_mask & (1 << ix)) {
- r = 0;
- for (oix = 0; oix < comp->frm.num_ovls; oix++)
- if (comp->ovls[oix].cfg.ix == ovl->cfg.ix) {
- *ovl = comp->ovls[oix];
- break;
- }
- BUG_ON(oix == comp->frm.num_ovls);
- } else {
- r = -ENOENT;
- }
- mutex_unlock(&mtx);
- return r;
- }
- EXPORT_SYMBOL(dsscomp_get_ovl);
- /* set manager info */
- int dsscomp_set_mgr(dsscomp_t comp, struct dss2_mgr_info *mgr)
- {
- mutex_lock(&mtx);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- BUG_ON(mgr->ix != comp->frm.mgr.ix);
- comp->frm.mgr = *mgr;
- mutex_unlock(&mtx);
- return 0;
- }
- EXPORT_SYMBOL(dsscomp_set_mgr);
- /* get manager info */
- int dsscomp_get_mgr(dsscomp_t comp, struct dss2_mgr_info *mgr)
- {
- mutex_lock(&mtx);
- BUG_ON(!mgr);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- *mgr = comp->frm.mgr;
- mutex_unlock(&mtx);
- return 0;
- }
- EXPORT_SYMBOL(dsscomp_get_mgr);
- /* get manager info */
- int dsscomp_setup(dsscomp_t comp, enum dsscomp_setup_mode mode,
- struct dss2_rect_t win)
- {
- mutex_lock(&mtx);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- comp->frm.mode = mode;
- comp->frm.win = win;
- mutex_unlock(&mtx);
- return 0;
- }
- EXPORT_SYMBOL(dsscomp_setup);
- /*
- * ===========================================================================
- * QUEUING COMMITTING OPERATIONS
- * ===========================================================================
- */
- void dsscomp_drop(dsscomp_t comp)
- {
- /* decrement unprogrammed references */
- if (comp->state < DSSCOMP_STATE_PROGRAMMED)
- maskref_decmask(&mgrq[comp->ix].ovl_qmask, comp->ovl_mask);
- comp->state = 0;
- if (debug & DEBUG_COMPOSITIONS)
- dev_info(DEV(cdev), "[%p] released\n", comp);
- DO_IF_DEBUG_FS(list_del(&comp->dbg_q));
- kfree(comp);
- }
- EXPORT_SYMBOL(dsscomp_drop);
- struct dsscomp_cb_work {
- struct work_struct work;
- struct dsscomp_data *comp;
- int status;
- };
- static void dsscomp_mgr_delayed_cb(struct work_struct *work)
- {
- struct dsscomp_cb_work *wk = container_of(work, typeof(*wk), work);
- struct dsscomp_data *comp = wk->comp;
- int status = wk->status;
- u32 ix;
- kfree(work);
- mutex_lock(&mtx);
- BUG_ON(comp->state == DSSCOMP_STATE_ACTIVE);
- ix = comp->ix;
- /* call extra callbacks if requested */
- if (comp->extra_cb)
- comp->extra_cb(comp->extra_cb_data, status);
- /* handle programming & release */
- if (status == DSS_COMPLETION_PROGRAMMED) {
- comp->state = DSSCOMP_STATE_PROGRAMMED;
- log_state(comp, dsscomp_mgr_delayed_cb, status);
- /* update used overlay mask */
- mgrq[ix].ovl_mask = comp->ovl_mask & ~comp->ovl_dmask;
- maskref_decmask(&mgrq[ix].ovl_qmask, comp->ovl_mask);
- if (debug & DEBUG_PHASES)
- dev_info(DEV(cdev), "[%p] programmed\n", comp);
- } else if ((status == DSS_COMPLETION_DISPLAYED) &&
- comp->state == DSSCOMP_STATE_PROGRAMMED) {
- /* composition is 1st displayed */
- comp->state = DSSCOMP_STATE_DISPLAYED;
- log_state(comp, dsscomp_mgr_delayed_cb, status);
- if (debug & DEBUG_PHASES)
- dev_info(DEV(cdev), "[%p] displayed\n", comp);
- } else if (status & DSS_COMPLETION_RELEASED) {
- /* composition is no longer displayed */
- log_event(20 * comp->ix + 20, 0, comp, "%pf on %s",
- (u32) dsscomp_mgr_delayed_cb,
- (u32) log_status_str(status));
- dsscomp_drop(comp);
- }
- mutex_unlock(&mtx);
- }
- static u32 dsscomp_mgr_callback(void *data, int id, int status)
- {
- struct dsscomp_data *comp = data;
- if (status == DSS_COMPLETION_PROGRAMMED ||
- (status == DSS_COMPLETION_DISPLAYED &&
- comp->state != DSSCOMP_STATE_DISPLAYED) ||
- (status & DSS_COMPLETION_RELEASED)) {
- struct dsscomp_cb_work *wk = kzalloc(sizeof(*wk), GFP_ATOMIC);
- wk->comp = comp;
- wk->status = status;
- INIT_WORK(&wk->work, dsscomp_mgr_delayed_cb);
- queue_work(cb_wkq, &wk->work);
- }
- /* get each callback only once */
- return ~status;
- }
- static inline bool dssdev_manually_updated(struct omap_dss_device *dev)
- {
- return dev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
- dev->driver->get_update_mode(dev) != OMAP_DSS_UPDATE_AUTO;
- }
- /* apply composition */
- /* at this point the composition is not on any queue */
- static int dsscomp_apply(dsscomp_t comp)
- {
- int i, r = -EFAULT;
- u32 dmask, display_ix;
- struct omap_dss_device *dssdev;
- struct omap_dss_driver *drv;
- struct omap_overlay_manager *mgr;
- struct omap_overlay *ovl;
- struct dsscomp_setup_mgr_data *d;
- u32 oix;
- bool cb_programmed = false;
- struct omapdss_ovl_cb cb = {
- .fn = dsscomp_mgr_callback,
- .data = comp,
- .mask = DSS_COMPLETION_DISPLAYED |
- DSS_COMPLETION_PROGRAMMED | DSS_COMPLETION_RELEASED,
- };
- BUG_ON(comp->state != DSSCOMP_STATE_APPLYING);
- /* check if the display is valid and used */
- r = -ENODEV;
- d = &comp->frm;
- display_ix = d->mgr.ix;
- if (display_ix >= cdev->num_displays)
- goto done;
- dssdev = cdev->displays[display_ix];
- if (!dssdev)
- goto done;
- drv = dssdev->driver;
- mgr = dssdev->manager;
- if (!mgr || !drv || mgr->id >= cdev->num_mgrs)
- goto done;
- dump_comp_info(cdev, d, "apply");
- r = 0;
- dmask = 0;
- for (oix = 0; oix < comp->frm.num_ovls; oix++) {
- struct dss2_ovl_info *oi = comp->ovls + oix;
- /* keep track of disabled overlays */
- if (!oi->cfg.enabled)
- dmask |= 1 << oi->cfg.ix;
- if (r && !comp->must_apply)
- continue;
- dump_ovl_info(cdev, oi);
- if (oi->cfg.ix >= cdev->num_ovls) {
- r = -EINVAL;
- continue;
- }
- ovl = cdev->ovls[oi->cfg.ix];
- /* set overlays' manager & info */
- if (ovl->info.enabled && ovl->manager != mgr) {
- r = -EBUSY;
- goto skip_ovl_set;
- }
- if (ovl->manager != mgr) {
- /*
- * Ideally, we should call ovl->unset_manager(ovl),
- * but it may block on go even though the disabling
- * of the overlay already went through. So instead,
- * we are just clearing the manager.
- */
- ovl->manager = NULL;
- r = ovl->set_manager(ovl, mgr);
- if (r)
- goto skip_ovl_set;
- }
- r = set_dss_ovl_info(oi);
- skip_ovl_set:
- if (r && comp->must_apply) {
- dev_err(DEV(cdev), "[%p] set ovl%d failed %d", comp,
- oi->cfg.ix, r);
- oi->cfg.enabled = false;
- dmask |= 1 << oi->cfg.ix;
- set_dss_ovl_info(oi);
- }
- }
- /*
- * set manager's info - this also sets the completion callback,
- * so if it succeeds, we will use the callback to complete the
- * composition. Otherwise, we can skip the composition now.
- */
- if (!r || comp->must_apply) {
- r = set_dss_mgr_info(&d->mgr, &cb);
- cb_programmed = r == 0;
- }
- if (r && !comp->must_apply) {
- dev_err(DEV(cdev), "[%p] set failed %d\n", comp, r);
- goto done;
- } else {
- if (r)
- dev_warn(DEV(cdev), "[%p] ignoring set failure %d\n",
- comp, r);
- comp->blank = dmask == comp->ovl_mask;
- comp->ovl_dmask = dmask;
- /*
- * Check other overlays that may also use this display.
- * NOTE: This is only needed in case someone changes
- * overlays via sysfs. We use comp->ovl_mask to refresh
- * the overlays actually used on a manager when the
- * composition is programmed.
- */
- for (i = 0; i < cdev->num_ovls; i++) {
- u32 mask = 1 << i;
- if ((~comp->ovl_mask & mask) &&
- cdev->ovls[i]->info.enabled &&
- cdev->ovls[i]->manager == mgr) {
- mutex_lock(&mtx);
- comp->ovl_mask |= mask;
- maskref_incbit(&mgrq[comp->ix].ovl_qmask, i);
- mutex_unlock(&mtx);
- }
- }
- }
- /* apply changes and call update on manual panels */
- /* no need for mutex as no callbacks are scheduled yet */
- comp->state = DSSCOMP_STATE_APPLIED;
- log_state(comp, dsscomp_apply, 0);
- if (!d->win.w && !d->win.x)
- d->win.w = dssdev->panel.timings.x_res - d->win.x;
- if (!d->win.h && !d->win.y)
- d->win.h = dssdev->panel.timings.y_res - d->win.y;
- mutex_lock(&mtx);
- if (mgrq[comp->ix].blanking) {
- pr_info_ratelimited("ignoring apply mgr(%s) while blanking\n",
- mgr->name);
- r = -ENODEV;
- } else {
- r = mgr->apply(mgr);
- if (r)
- dev_err(DEV(cdev), "failed while applying %d", r);
- /* keep error if set_mgr_info failed */
- if (!r && !cb_programmed)
- r = -EINVAL;
- }
- mutex_unlock(&mtx);
- /*
- * TRICKY: try to unregister callback to see if callbacks have
- * been applied (moved into DSS2 pipeline). Unregistering also
- * avoids having to unnecessarily kick out compositions (which
- * would result in screen blinking). If callbacks failed to apply,
- * (e.g. could not set them or apply them) we will need to call
- * them ourselves (we note this by returning an error).
- */
- if (cb_programmed && r) {
- /* clear error if callback already registered */
- if (omap_dss_manager_unregister_callback(mgr, &cb))
- r = 0;
- }
- /* if failed to apply, kick out prior composition */
- if (comp->must_apply && r)
- mgr->blank(mgr, true);
- if (!r && (d->mode & DSSCOMP_SETUP_MODE_DISPLAY)) {
- /* cannot handle update errors, so ignore them */
- if (dssdev_manually_updated(dssdev) && drv->update)
- drv->update(dssdev, d->win.x,
- d->win.y, d->win.w, d->win.h);
- else
- /* wait for sync to do smooth animations */
- mgr->wait_for_vsync(mgr);
- }
- done:
- return r;
- }
- struct dsscomp_apply_work {
- struct work_struct work;
- dsscomp_t comp;
- };
- int dsscomp_state_notifier(struct notifier_block *nb,
- unsigned long arg, void *ptr)
- {
- struct omap_dss_device *dssdev = ptr;
- enum omap_dss_display_state state = arg;
- struct omap_overlay_manager *mgr = dssdev->manager;
- if (mgr) {
- mutex_lock(&mtx);
- if (state == OMAP_DSS_DISPLAY_DISABLED) {
- mgr->blank(mgr, true);
- mgrq[mgr->id].blanking = true;
- } else if (state == OMAP_DSS_DISPLAY_ACTIVE) {
- mgrq[mgr->id].blanking = false;
- }
- mutex_unlock(&mtx);
- }
- return 0;
- }
- static void dsscomp_do_apply(struct work_struct *work)
- {
- struct dsscomp_apply_work *wk = container_of(work, typeof(*wk), work);
- /* complete compositions that failed to apply */
- if (dsscomp_apply(wk->comp))
- dsscomp_mgr_callback(wk->comp, -1, DSS_COMPLETION_ECLIPSED_SET);
- kfree(wk);
- }
- int dsscomp_delayed_apply(dsscomp_t comp)
- {
- /* don't block in case we are called from interrupt context */
- struct dsscomp_apply_work *wk = kzalloc(sizeof(*wk), GFP_NOWAIT);
- if (!wk)
- return -ENOMEM;
- mutex_lock(&mtx);
- BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
- comp->state = DSSCOMP_STATE_APPLYING;
- log_state(comp, dsscomp_delayed_apply, 0);
- if (debug & DEBUG_PHASES)
- dev_info(DEV(cdev), "[%p] applying\n", comp);
- mutex_unlock(&mtx);
- wk->comp = comp;
- INIT_WORK(&wk->work, dsscomp_do_apply);
- return queue_work(mgrq[comp->ix].apply_workq, &wk->work) ? 0 : -EBUSY;
- }
- EXPORT_SYMBOL(dsscomp_delayed_apply);
- /*
- * ===========================================================================
- * DEBUGFS
- * ===========================================================================
- */
- #ifdef CONFIG_DEBUG_FS
- void seq_print_comp(struct seq_file *s, dsscomp_t c)
- {
- struct dsscomp_setup_mgr_data *d = &c->frm;
- int i;
- seq_printf(s, " [%p]: %s%s\n", c, c->blank ? "blank " : "",
- c->state == DSSCOMP_STATE_ACTIVE ? "ACTIVE" :
- c->state == DSSCOMP_STATE_APPLYING ? "APPLYING" :
- c->state == DSSCOMP_STATE_APPLIED ? "APPLIED" :
- c->state == DSSCOMP_STATE_PROGRAMMED ? "PROGRAMMED" :
- c->state == DSSCOMP_STATE_DISPLAYED ? "DISPLAYED" :
- "???");
- seq_printf(s, " sync_id=%x, flags=%c%c%c\n",
- d->sync_id,
- (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
- (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
- (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-');
- for (i = 0; i < d->num_ovls; i++) {
- struct dss2_ovl_info *oi;
- struct dss2_ovl_cfg *g;
- oi = d->ovls + i;
- g = &oi->cfg;
- if (g->zonly) {
- seq_printf(s, " ovl%d={%s z%d}\n",
- g->ix, g->enabled ? "ON" : "off", g->zorder);
- } else {
- seq_printf(s, " ovl%d={%s z%d %s%s *%d%%"
- " %d*%d:%d,%d+%d,%d rot%d%s"
- " => %d,%d+%d,%d %p/%p|%d}\n",
- g->ix, g->enabled ? "ON" : "off", g->zorder,
- dsscomp_get_color_name(g->color_mode) ? : "N/A",
- g->pre_mult_alpha ? " premult" : "",
- (g->global_alpha * 100 + 128) / 255,
- g->width, g->height, g->crop.x, g->crop.y,
- g->crop.w, g->crop.h,
- g->rotation, g->mirror ? "+mir" : "",
- g->win.x, g->win.y, g->win.w, g->win.h,
- (void *) oi->ba, (void *) oi->uv, g->stride);
- }
- }
- if (c->extra_cb)
- seq_printf(s, " gsync=[%p] %pf\n\n", c->extra_cb_data,
- c->extra_cb);
- else
- seq_printf(s, " gsync=[%p] (called)\n\n", c->extra_cb_data);
- }
- #endif
- void dsscomp_dbg_comps(struct seq_file *s)
- {
- #ifdef CONFIG_DEBUG_FS
- dsscomp_t c;
- u32 i;
- mutex_lock(&dbg_mtx);
- for (i = 0; i < cdev->num_mgrs; i++) {
- struct omap_overlay_manager *mgr = cdev->mgrs[i];
- seq_printf(s, "ACTIVE COMPOSITIONS on %s\n\n", mgr->name);
- list_for_each_entry(c, &dbg_comps, dbg_q) {
- struct dss2_mgr_info *mi = &c->frm.mgr;
- if (mi->ix < cdev->num_displays &&
- cdev->displays[mi->ix]->manager == mgr)
- seq_print_comp(s, c);
- }
- /* print manager cache */
- mgr->dump_cb(mgr, s);
- }
- mutex_unlock(&dbg_mtx);
- #endif
- }
- void dsscomp_dbg_events(struct seq_file *s)
- {
- #ifdef CONFIG_DSSCOMP_DEBUG_LOG
- u32 i;
- struct dbg_event_t *d;
- mutex_lock(&dbg_mtx);
- for (i = dbg_event_ix; i < dbg_event_ix + ARRAY_SIZE(dbg_events); i++) {
- d = dbg_events + (i % ARRAY_SIZE(dbg_events));
- if (!d->ms)
- continue;
- seq_printf(s, "[% 5d.%03d] %*s[%08x] ",
- d->ms / 1000, d->ms % 1000,
- d->ix + ((u32) d->data) % 7,
- "", (u32) d->data);
- seq_printf(s, d->fmt, d->a1, d->a2);
- seq_printf(s, "\n");
- }
- mutex_unlock(&dbg_mtx);
- #endif
- }
- /*
- * ===========================================================================
- * EXIT
- * ===========================================================================
- */
- void dsscomp_queue_exit(void)
- {
- if (cdev) {
- int i;
- for (i = 0; i < cdev->num_displays; i++)
- destroy_workqueue(mgrq[i].apply_workq);
- destroy_workqueue(cb_wkq);
- cdev = NULL;
- }
- }
- EXPORT_SYMBOL(dsscomp_queue_exit);