summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/omap2/dss/dispc.c24
-rw-r--r--drivers/video/omap2/dss/overlay.c72
-rw-r--r--include/video/omapdss.h1
3 files changed, 97 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index fa7aadfec7b..6892cfd2e3b 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 11d21e3347a..ab8e40e4875 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;
}
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 27d9cce2591..b66ebb2032c 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -377,6 +377,7 @@ struct omap_overlay_info {
u16 out_height; /* if 0, out_height == height */
u8 global_alpha;
u8 pre_mult_alpha;
+ u8 zorder;
};
struct omap_overlay {