diff options
author | Archit Taneja <archit@ti.com> | 2011-09-08 11:29:17 +0530 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-10-03 16:51:55 +0300 |
commit | 54128701ecccbeb6f740030e0cc5f8e5701fe8ee (patch) | |
tree | d0c7e5fee25d9458f105acc20b5f4accc2d82bcd /drivers/video | |
parent | b8c095b4d62f90ed8da0cca7116125863b1d8bef (diff) |
OMAPDSS: DISPC: zorder support for DSS overlays
Add zorder support on OMAP4, this feature allows deciding the visibility order
of the overlays based on the zorder value provided as an overlay info parameter
or a sysfs attribute of the overlay object.
Use the overlay cap OMAP_DSS_OVL_CAP_ZORDER to determine whether zorder is
supported for the overlay or not. Use dss feature FEAT_ALPHA_FREE_ZORDER
if the caps are not available.
Ensure that all overlays that are enabled and connected to the same manager
have different zorders. Swapping zorders of 2 enabled overlays currently
requires disabling one of the overlays.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 24 | ||||
-rw-r--r-- | drivers/video/omap2/dss/overlay.c | 72 |
2 files changed, 96 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index fa7aadfec7b8..6892cfd2e3b7 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -739,6 +739,27 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) dispc_write_reg(DISPC_OVL_SIZE(plane), val); } +static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) +{ + struct omap_overlay *ovl = omap_dss_get_overlay(plane); + + if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) + return; + + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); +} + +static void dispc_ovl_enable_zorder_planes(void) +{ + int i; + + if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + return; + + for (i = 0; i < dss_feat_get_num_ovls(); i++) + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); +} + static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) { struct omap_overlay *ovl = omap_dss_get_overlay(plane); @@ -1866,6 +1887,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, oi->color_mode); + dispc_ovl_set_zorder(plane, oi->zorder); dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); dispc_ovl_setup_global_alpha(plane, oi->global_alpha); @@ -3317,6 +3339,8 @@ static void _omap_dispc_initial_config(void) dispc_read_plane_fifo_sizes(); dispc_configure_burst_sizes(); + + dispc_ovl_enable_zorder_planes(); } /* DISPC HW IP initialisation */ diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 11d21e3347ad..ab8e40e48759 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -311,6 +311,42 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, return size; } +static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder); +} + +static ssize_t overlay_zorder_store(struct omap_overlay *ovl, + const char *buf, size_t size) +{ + int r; + u8 zorder; + struct omap_overlay_info info; + + if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) + return -ENODEV; + + r = kstrtou8(buf, 0, &zorder); + if (r) + return r; + + ovl->get_overlay_info(ovl, &info); + + info.zorder = zorder; + + r = ovl->set_overlay_info(ovl, &info); + if (r) + return r; + + if (ovl->manager) { + r = ovl->manager->apply(ovl->manager); + if (r) + return r; + } + + return size; +} + struct overlay_attribute { struct attribute attr; ssize_t (*show)(struct omap_overlay *, char *); @@ -337,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, overlay_pre_mult_alpha_show, overlay_pre_mult_alpha_store); +static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, + overlay_zorder_show, overlay_zorder_store); static struct attribute *overlay_sysfs_attrs[] = { &overlay_attr_name.attr, @@ -348,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = { &overlay_attr_enabled.attr, &overlay_attr_global_alpha.attr, &overlay_attr_pre_mult_alpha.attr, + &overlay_attr_zorder.attr, NULL }; @@ -397,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) struct omap_overlay_info *info; u16 outw, outh; u16 dw, dh; + int i; if (!dssdev) return 0; @@ -452,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) return -EINVAL; } + if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) { + if (info->zorder < 0 || info->zorder > 3) { + DSSERR("zorder out of range: %d\n", + info->zorder); + return -EINVAL; + } + /* + * Check that zorder doesn't match with zorder of any other + * overlay which is enabled and is also connected to the same + * manager + */ + for (i = 0; i < omap_dss_get_num_overlays(); i++) { + struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i); + + if (tmp_ovl->id != ovl->id && + tmp_ovl->manager == ovl->manager && + tmp_ovl->info.enabled == true && + tmp_ovl->info.zorder == info->zorder) { + DSSERR("%s and %s have same zorder: %d\n", + ovl->name, tmp_ovl->name, info->zorder); + return -EINVAL; + } + } + } + return 0; } @@ -604,21 +669,28 @@ void dss_init_overlays(struct platform_device *pdev) ovl->name = "gfx"; ovl->id = OMAP_DSS_GFX; ovl->info.global_alpha = 255; + ovl->info.zorder = 0; break; case 1: ovl->name = "vid1"; ovl->id = OMAP_DSS_VIDEO1; ovl->info.global_alpha = 255; + ovl->info.zorder = + dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0; break; case 2: ovl->name = "vid2"; ovl->id = OMAP_DSS_VIDEO2; ovl->info.global_alpha = 255; + ovl->info.zorder = + dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; break; case 3: ovl->name = "vid3"; ovl->id = OMAP_DSS_VIDEO3; ovl->info.global_alpha = 255; + ovl->info.zorder = + dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0; break; } |