diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index b5a542fbd818..d9424bee0457 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -97,6 +97,8 @@ static struct { /* protects dss_data */ static spinlock_t data_lock; +/* lock for blocking functions */ +static DEFINE_MUTEX(apply_lock); static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl) { @@ -639,14 +641,22 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) void dss_mgr_enable(struct omap_overlay_manager *mgr) { + mutex_lock(&apply_lock); + dispc_mgr_enable(mgr->id, true); mgr->enabled = true; + + mutex_unlock(&apply_lock); } void dss_mgr_disable(struct omap_overlay_manager *mgr) { + mutex_lock(&apply_lock); + dispc_mgr_enable(mgr->id, false); mgr->enabled = false; + + mutex_unlock(&apply_lock); } int dss_mgr_set_info(struct omap_overlay_manager *mgr, @@ -669,44 +679,65 @@ int dss_mgr_set_device(struct omap_overlay_manager *mgr, { int r; + mutex_lock(&apply_lock); + if (dssdev->manager) { DSSERR("display '%s' already has a manager '%s'\n", dssdev->name, dssdev->manager->name); - return -EINVAL; + r = -EINVAL; + goto err; } if ((mgr->supported_displays & dssdev->type) == 0) { DSSERR("display '%s' does not support manager '%s'\n", dssdev->name, mgr->name); - return -EINVAL; + r = -EINVAL; + goto err; } dssdev->manager = mgr; mgr->device = dssdev; mgr->device_changed = true; + mutex_unlock(&apply_lock); + return 0; +err: + mutex_unlock(&apply_lock); + return r; } int dss_mgr_unset_device(struct omap_overlay_manager *mgr) { + int r; + + mutex_lock(&apply_lock); + if (!mgr->device) { DSSERR("failed to unset display, display not set.\n"); - return -EINVAL; + r = -EINVAL; + goto err; } /* * Don't allow currently enabled displays to have the overlay manager * pulled out from underneath them */ - if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) - return -EINVAL; + if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) { + r = -EINVAL; + goto err; + } mgr->device->manager = NULL; mgr->device = NULL; mgr->device_changed = true; + mutex_unlock(&apply_lock); + return 0; +err: + mutex_unlock(&apply_lock); + return r; } @@ -729,18 +760,24 @@ void dss_ovl_get_info(struct omap_overlay *ovl, int dss_ovl_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr) { + int r; + if (!mgr) return -EINVAL; + mutex_lock(&apply_lock); + if (ovl->manager) { DSSERR("overlay '%s' already has a manager '%s'\n", ovl->name, ovl->manager->name); - return -EINVAL; + r = -EINVAL; + goto err; } if (ovl->info.enabled) { DSSERR("overlay has to be disabled to change the manager\n"); - return -EINVAL; + r = -EINVAL; + goto err; } ovl->manager = mgr; @@ -760,25 +797,41 @@ int dss_ovl_set_manager(struct omap_overlay *ovl, * the overlay, but before moving the overlay to TV. */ + mutex_unlock(&apply_lock); + return 0; +err: + mutex_unlock(&apply_lock); + return r; } int dss_ovl_unset_manager(struct omap_overlay *ovl) { + int r; + + mutex_lock(&apply_lock); + if (!ovl->manager) { DSSERR("failed to detach overlay: manager not set\n"); - return -EINVAL; + r = -EINVAL; + goto err; } if (ovl->info.enabled) { DSSERR("overlay has to be disabled to unset the manager\n"); - return -EINVAL; + r = -EINVAL; + goto err; } ovl->manager = NULL; list_del(&ovl->list); ovl->manager_changed = true; + mutex_unlock(&apply_lock); + return 0; +err: + mutex_unlock(&apply_lock); + return r; }