diff options
Diffstat (limited to 'drivers/video/omap2/dss/overlay.c')
-rw-r--r-- | drivers/video/omap2/dss/overlay.c | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 456efef03c2..c84380c53c3 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -31,7 +31,7 @@ #include <linux/delay.h> #include <linux/slab.h> -#include <plat/display.h> +#include <video/omapdss.h> #include <plat/cpu.h> #include "dss.h" @@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, old_mgr = ovl->manager; + r = dispc_runtime_get(); + if (r) + return r; + /* detach old manager */ if (old_mgr) { r = ovl->unset_manager(ovl); if (r) { DSSERR("detach failed\n"); - return r; + goto err; } r = old_mgr->apply(old_mgr); if (r) - return r; + goto err; } if (mgr) { r = ovl->set_manager(ovl, mgr); if (r) { DSSERR("Failed to attach overlay\n"); - return r; + goto err; } r = mgr->apply(mgr); if (r) - return r; + goto err; } + dispc_runtime_put(); + return size; + +err: + dispc_runtime_put(); + return r; } static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) @@ -201,12 +211,16 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, size_t size) { - int r; + int r, enable; struct omap_overlay_info info; ovl->get_overlay_info(ovl, &info); - info.enabled = simple_strtoul(buf, NULL, 10); + r = kstrtoint(buf, 0, &enable); + if (r) + return r; + + info.enabled = !!enable; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -231,8 +245,16 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, const char *buf, size_t size) { int r; + u8 alpha; struct omap_overlay_info info; + if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) + return -ENODEV; + + r = kstrtou8(buf, 0, &alpha); + if (r) + return r; + ovl->get_overlay_info(ovl, &info); /* Video1 plane does not support global alpha @@ -242,7 +264,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, ovl->id == OMAP_DSS_VIDEO1) info.global_alpha = 255; else - info.global_alpha = simple_strtoul(buf, NULL, 10); + info.global_alpha = alpha; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -268,8 +290,13 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, const char *buf, size_t size) { int r; + u8 alpha; struct omap_overlay_info info; + r = kstrtou8(buf, 0, &alpha); + if (r) + return r; + ovl->get_overlay_info(ovl, &info); /* only GFX and Video2 plane support pre alpha multiplied @@ -279,7 +306,7 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, ovl->id == OMAP_DSS_VIDEO1) info.pre_mult_alpha = 0; else - info.pre_mult_alpha = simple_strtoul(buf, NULL, 10); + info.pre_mult_alpha = alpha; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -490,16 +517,19 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, ovl->manager = mgr; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); - /* XXX: on manual update display, in auto update mode, a bug happens - * here. When an overlay is first enabled on LCD, then it's disabled, - * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT - * errors. Waiting before changing the channel_out fixes it. I'm - * guessing that the overlay is still somehow being used for the LCD, - * but I don't understand how or why. */ - msleep(40); + /* XXX: When there is an overlay on a DSI manual update display, and + * the overlay is first disabled, then moved to tv, and enabled, we + * seem to get SYNC_LOST_DIGIT error. + * + * Waiting doesn't seem to help, but updating the manual update display + * after disabling the overlay seems to fix this. This hints that the + * overlay is perhaps somehow tied to the LCD output until the output + * is updated. + * + * Userspace workaround for this is to update the LCD after disabling + * the overlay, but before moving the overlay to TV. + */ dispc_set_channel_out(ovl->id, mgr->id); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); return 0; } @@ -679,7 +709,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) lcd2_mgr->set_device(lcd2_mgr, dssdev); mgr = lcd2_mgr; } - } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { + } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC + && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { if (!lcd_mgr->device || force) { if (lcd_mgr->device) lcd_mgr->unset_device(lcd_mgr); @@ -688,7 +719,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) } } - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC + || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { if (!tv_mgr->device || force) { if (tv_mgr->device) tv_mgr->unset_device(tv_mgr); @@ -698,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) } if (mgr) { + dispc_runtime_get(); + for (i = 0; i < dss_feat_get_num_ovls(); i++) { struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); @@ -707,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) omap_dss_set_manager(ovl, mgr); } } + + dispc_runtime_put(); } } |