[RFC PATCH 7/8] drm: plane: Add plane options ioctl

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>

Add a new ioctl DRM_IOCTL_MODE_PLANE_OPTS which is used to configure
various settings for the plane.

I left out gamma correction thinking that it could be added using a
separate ioctl, since there's already a gamma ioctl for CRTCs.

Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/drm_crtc.c        |  168 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_crtc_helper.c |   19 ++++
 drivers/gpu/drm/drm_drv.c         |    3 +-
 include/drm/drm.h                 |    2 +
 include/drm/drm_crtc.h            |   60 +++++++++++++
 include/drm/drm_crtc_helper.h     |    1 +
 include/drm/drm_mode.h            |  111 ++++++++++++++++++++++++
 7 files changed, 363 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0d1faa7..9cec7f0 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1772,6 +1772,174 @@ out:
 }
 
 /**
+ * drm_mode_plane_opts - set and get plane options
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_prive: DRM file info
+ *
+ */
+int drm_mode_plane_opts(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_plane_opts_cmd *req = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/*
+	 * First, find the plane object.  If not available,
+	 * we don't bother to call the driver.
+	 */
+	obj = drm_mode_object_find(dev, req->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown plane ID %d\n",
+			      req->plane_id);
+		ret = -ENOENT;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	if (req->flags & ~plane->opts_flags) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	if (req->flags) {
+		/* Start with the current values. */
+		struct drm_plane_opts opts = plane->opts;
+		uint32_t flags = 0;
+
+		/* Overwrite with user provided values. */
+		if (req->flags & DRM_MODE_PLANE_BRIGHTNESS &&
+		    opts.brightness != req->brightness) {
+			flags |= DRM_MODE_PLANE_BRIGHTNESS;
+			opts.brightness = req->brightness;
+		}
+		if (req->flags & DRM_MODE_PLANE_CONTRAST &&
+		    opts.contrast != req->contrast) {
+			flags |= DRM_MODE_PLANE_CONTRAST;
+			opts.contrast = req->contrast;
+		}
+		if (req->flags & DRM_MODE_PLANE_HUE &&
+		    opts.hue != req->hue) {
+			flags |= DRM_MODE_PLANE_HUE;
+			opts.hue = req->hue;
+		}
+		if (req->flags & DRM_MODE_PLANE_SATURATION &&
+		    opts.saturation != req->saturation) {
+			flags |= DRM_MODE_PLANE_SATURATION;
+			opts.saturation = req->saturation;
+		}
+		if (req->flags & DRM_MODE_PLANE_SRC_KEY &&
+		    (opts.src_key_low != req->src_key_low ||
+		     opts.src_key_high != req->src_key_high)) {
+			flags |= DRM_MODE_PLANE_SRC_KEY;
+			opts.src_key_low = req->src_key_low;
+			opts.src_key_high = req->src_key_high;
+		}
+		if (req->flags & DRM_MODE_PLANE_DST_KEY &&
+		    (opts.dst_key_value != req->dst_key_value ||
+		     opts.dst_key_mask != req->dst_key_mask)) {
+			flags |= DRM_MODE_PLANE_DST_KEY;
+			opts.dst_key_value = req->dst_key_value;
+			opts.dst_key_mask = req->dst_key_mask;
+		}
+		if (req->flags & DRM_MODE_PLANE_CONST_ALPHA &&
+		    opts.const_alpha != req->const_alpha) {
+			flags |= DRM_MODE_PLANE_CONST_ALPHA;
+			opts.const_alpha = req->const_alpha;
+		}
+		if (req->flags & DRM_MODE_PLANE_ZORDER &&
+		    opts.zorder != req->zorder) {
+			if (req->zorder == 0) {
+				ret = -EINVAL;
+				goto out;
+			}
+			flags |= DRM_MODE_PLANE_ZORDER;
+			opts.zorder = req->zorder;
+		}
+		if (req->flags & DRM_MODE_PLANE_CSC_MATRIX &&
+		    opts.csc_matrix != req->csc_matrix) {
+			flags |= DRM_MODE_PLANE_CSC_MATRIX;
+			opts.csc_matrix = req->csc_matrix;
+		}
+		if (req->flags & DRM_MODE_PLANE_CSC_RANGE &&
+		    opts.csc_range != req->csc_range) {
+			flags |= DRM_MODE_PLANE_CSC_RANGE;
+			opts.csc_range = req->csc_range;
+		}
+		if (req->flags & DRM_MODE_PLANE_CHROMA_SITING &&
+		    opts.chroma_siting != req->chroma_siting) {
+			flags |= DRM_MODE_PLANE_CHROMA_SITING;
+			opts.chroma_siting = req->chroma_siting;
+		}
+		if (req->flags & DRM_MODE_PLANE_VC1_RANGE_MAPY &&
+		    opts.vc1_range_mapy != req->vc1_range_mapy) {
+			flags |= DRM_MODE_PLANE_VC1_RANGE_MAPY;
+			opts.vc1_range_mapy = req->vc1_range_mapy;
+		}
+		if (req->flags & DRM_MODE_PLANE_VC1_RANGE_MAPUV &&
+		    opts.vc1_range_mapuv != req->vc1_range_mapuv) {
+			flags |= DRM_MODE_PLANE_VC1_RANGE_MAPUV;
+			opts.vc1_range_mapuv = req->vc1_range_mapuv;
+		}
+
+		if (flags) {
+			ret = plane->funcs->set_plane_opts(plane, flags, &opts);
+			if (ret)
+				goto out;
+
+			plane->opts = opts;
+		}
+	}
+
+	/* Copy the current values back to the user. */
+	req->flags = plane->opts_flags;
+
+	if (req->flags & DRM_MODE_PLANE_BRIGHTNESS)
+		req->brightness = plane->opts.brightness;
+	if (req->flags & DRM_MODE_PLANE_CONTRAST)
+		req->contrast = plane->opts.contrast;
+	if (req->flags & DRM_MODE_PLANE_HUE)
+		req->hue = plane->opts.hue;
+	if (req->flags & DRM_MODE_PLANE_SATURATION)
+		req->saturation = plane->opts.saturation;
+	if (req->flags & DRM_MODE_PLANE_SRC_KEY) {
+		req->src_key_low = plane->opts.src_key_low;
+		req->src_key_high = plane->opts.src_key_high;
+	}
+	if (req->flags & DRM_MODE_PLANE_DST_KEY) {
+		req->dst_key_value = plane->opts.dst_key_value;
+		req->dst_key_mask = plane->opts.dst_key_mask;
+	}
+	if (req->flags & DRM_MODE_PLANE_CONST_ALPHA)
+		req->const_alpha = plane->opts.const_alpha;
+	if (req->flags & DRM_MODE_PLANE_ZORDER)
+		req->zorder = plane->opts.zorder;
+	if (req->flags & DRM_MODE_PLANE_CSC_MATRIX)
+		req->csc_matrix = plane->opts.csc_matrix;
+	if (req->flags & DRM_MODE_PLANE_CSC_RANGE)
+		req->csc_range = plane->opts.csc_range;
+	if (req->flags & DRM_MODE_PLANE_CHROMA_SITING)
+		req->chroma_siting = plane->opts.chroma_siting;
+	if (req->flags & DRM_MODE_PLANE_VC1_RANGE_MAPY)
+		req->vc1_range_mapy = plane->opts.vc1_range_mapy;
+	if (req->flags & DRM_MODE_PLANE_VC1_RANGE_MAPUV)
+		req->vc1_range_mapuv = plane->opts.vc1_range_mapuv;
+
+ out:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+/**
  * drm_mode_setcrtc - set CRTC configuration
  * @inode: inode from the ioctl
  * @filp: file * from the ioctl
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5e0b94c..0153187 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -1460,3 +1460,22 @@ int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
 	return vscale;
 }
 EXPORT_SYMBOL(drm_calc_vscale);
+
+/**
+ * drm_plane_opts_defaults - fill the plane opts with default values
+ */
+void drm_plane_opts_defaults(struct drm_plane_opts *opts)
+{
+	memset(opts, 0, sizeof *opts);
+
+	opts->brightness = 0x8000;
+	opts->contrast = 0x8000;
+	opts->hue = 0x8000;
+	opts->saturation = 0x8000;
+
+	/* disable source color keying */
+	opts->src_key_low = ~0ULL;
+
+	opts->const_alpha = 0xffff;
+}
+EXPORT_SYMBOL(drm_plane_opts_defaults);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index eaf25ff..5759baa 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -159,7 +159,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PLANE_OPTS, drm_mode_plane_opts, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 49d94ed..e59ec20 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -718,6 +718,8 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
+#define DRM_IOCTL_MODE_PLANE_OPTS	DRM_IOWR(0xB9, struct drm_mode_plane_opts_cmd)
+
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 2deb6f9..cf99643 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -277,6 +277,56 @@ struct drm_property {
 	struct list_head enum_blob_list;
 };
 
+/**
+ * drm_plane_opts - plane options
+ * @brightness: brightness value
+ * @contrast: contrast value
+ * @hue: hue value
+ * @saturation: saturation value
+ * @src_key_low: minimum source color key value
+ * @src_key_high: maximum source color key value
+ * @dst_key_value: destination color key value
+ * @dst_key_mask: destination color key mask
+ * @const_alpha: constant alpha blending factor
+ * @zorder: plane Z order
+ * @csc_matrix: transfer matrix
+ * @csc_range: Y/Cb/Cb range information
+ * @chroma_siting: chroma siting information
+ * @vc1_range_mapy: VC-1 range mapping for Y
+ * @vc1_range_mapuv: VC-1 range mapping for Cb/Cr
+ *
+ * @brightness, @contrast, @hue and @saturation have a range of 0x0000 to
+ * 0xffff. Values of 0x0000 to 0x7fff indicate a decrease, a value of
+ * 0x8000 indicates a default level, and values from 0x8001 to 0xffff
+ * indicate an increase.
+ *
+ * The actual change in the level per a change in the value is implementation
+ * defined, as is the exact meaning of the default level. The only strict
+ * requirement is that the mapping between the value and the actual level is
+ * a monotonically non-decreasing function.
+ *
+ * It is recommended that the full range of values be utilized eg. by
+ * using coarsers step size, piecewise functions, etc. This helps to
+ * isolate the user from the hardware details as much as possible.
+ */
+struct drm_plane_opts {
+	uint16_t brightness;
+	uint16_t contrast;
+	uint16_t hue;
+	uint16_t saturation;
+	uint64_t src_key_low;
+	uint64_t src_key_high;
+	uint64_t dst_key_value;
+	uint64_t dst_key_mask;
+	uint16_t const_alpha;
+	int8_t zorder;
+	uint8_t csc_matrix;
+	uint8_t csc_range;
+	uint8_t chroma_siting;
+	uint8_t vc1_range_mapy;
+	uint8_t vc1_range_mapuv;
+};
+
 struct drm_crtc;
 struct drm_connector;
 struct drm_encoder;
@@ -595,6 +645,7 @@ struct drm_connector {
  * @update_plane: update the plane configuration
  * @disable_plane: shut down the plane
  * @destroy: clean up plane resources
+ * @set_plane_opts: set plane options
  */
 struct drm_plane_funcs {
 	int (*update_plane)(struct drm_plane *plane,
@@ -605,6 +656,8 @@ struct drm_plane_funcs {
 			    uint32_t src_w, uint32_t src_h);
 	int (*disable_plane)(struct drm_plane *plane);
 	void (*destroy)(struct drm_plane *plane);
+	int (*set_plane_opts)(struct drm_plane *plane, uint32_t flags,
+			      struct drm_plane_opts *opts);
 };
 
 /**
@@ -644,6 +697,9 @@ struct drm_plane {
 
 	const struct drm_plane_funcs *funcs;
 	void *helper_private;
+
+	uint32_t opts_flags;
+	struct drm_plane_opts opts;
 };
 
 /**
@@ -1007,4 +1063,8 @@ extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 
 extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
 				 int *bpp);
+
+extern int drm_mode_plane_opts(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 78e77af..e4946a5 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -179,5 +179,6 @@ extern int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
 			   int min_hscale, int max_hscale);
 extern int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
 			   int min_vscale, int max_vscale);
+extern void drm_plane_opts_defaults(struct drm_plane_opts *opts);
 
 #endif
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 966fe7d..be8a9fd 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -157,6 +157,117 @@ struct drm_mode_get_plane_res {
 	__u32 count_planes;
 };
 
+/* Valid YCbCr range */
+#define DRM_CSC_RANGE_UNKNOWN		0x0 /* not specified, implementation defined result */
+#define DRM_CSC_RANGE_MPEG		0x1 /* "MPEG" range (16-235 for Y, 16-240 for Cb/Cr) */
+#define DRM_CSC_RANGE_JPEG		0x2 /* "JPEG" or full range (0-255 for Y/Cb/Cr) */
+
+/* Color space conversion transfer matrix */
+#define DRM_CSC_MATRIX_UNKNOWN		0x0 /* not specified, implementation defined result */
+#define DRM_CSC_MATRIX_BT601		0x1 /* ITU-R BT.601 */
+#define DRM_CSC_MATRIX_BT709		0x2 /* ITU-R BT.709 */
+
+/* Chroma siting information */
+#define DRM_CHROMA_SITING_UNKNOWN		0x0 /* not specified, implementation defined result */
+#define DRM_CHROMA_SITING_HORZ_LEFT		0x1 /* horizontally co-sited with the first luma sample */
+#define DRM_CHROMA_SITING_HORZ_CENTER		0x2 /* horizontally interstitially sited with luma samples */
+#define DRM_CHROMA_SITING_VERT_TOP		0x4 /* vertically co-sited with the first luma sample */
+#define DRM_CHROMA_SITING_VERT_CENTER		0x8 /* vertically interstitially sited with luma samples */
+#define DRM_CHROMA_SITING_MISALIGNED_PLANES	0x10 /* chroma planes out of phase with each other by 0.5 lines */
+/* Typical chroma siting configurations */
+#define DRM_CHROMA_SITING_MPEG1			(DRM_CHROMA_SITING_HORZ_CENTER |\
+						 DRM_CHROMA_SITING_VERT_CENTER)
+#define DRM_CHROMA_SITING_MPEG2			(DRM_CHROMA_SITING_HORZ_LEFT |\
+						 DRM_CHROMA_SITING_VERT_CENTER)
+#define DRM_CHROMA_SITING_DV			(DRM_CHROMA_SITING_HORZ_LEFT |\
+						 DRM_CHROMA_SITING_VERT_TOP |\
+						 DRM_CHROMA_SITING_MISALIGNED_PLANES)
+
+/*
+ * Plane option flags.
+ * If a flag is set the corresponding value is valid
+ */
+#define DRM_MODE_PLANE_BRIGHTNESS	(1<<0)
+#define DRM_MODE_PLANE_CONTRAST		(1<<1)
+#define DRM_MODE_PLANE_HUE		(1<<2)
+#define DRM_MODE_PLANE_SATURATION	(1<<3)
+#define DRM_MODE_PLANE_SRC_KEY		(1<<4)
+#define DRM_MODE_PLANE_DST_KEY		(1<<5)
+#define DRM_MODE_PLANE_CONST_ALPHA	(1<<6)
+#define DRM_MODE_PLANE_ZORDER		(1<<7)
+#define DRM_MODE_PLANE_CSC_MATRIX	(1<<8)
+#define DRM_MODE_PLANE_CSC_RANGE	(1<<9)
+#define DRM_MODE_PLANE_CHROMA_SITING	(1<<10)
+#define DRM_MODE_PLANE_VC1_RANGE_MAPY	(1<<11)
+#define DRM_MODE_PLANE_VC1_RANGE_MAPUV	(1<<12)
+
+struct drm_mode_plane_opts_cmd {
+	__u32 plane_id;
+
+	__u32 flags;
+
+	/*
+	 * 0x0000 - 0x7fff = decrease
+	 * 0x8000          = no change
+	 * 0x8001 - 0xffff = increase
+	 */
+	__u16 brightness;
+	__u16 contrast;
+	__u16 hue;
+	__u16 saturation;
+
+	/*
+	 * [47:32] R [31:16] G [15:0] B or [47:32] Y [31:16] Cb [15:0] Cr
+	 * The size and color space of the components depends on the
+	 * used pixel format. If the actual component size is less than
+	 * 16 bits, the most significat bits of of each component are
+	 * used.
+	 * The plane is invisible when the following equation evaluates
+	 * to true (for each component):
+	 * src_pixel >= src_key_low && src_pixel <= src_key_high
+	 *
+	 * To disable source color keying set src_key_high < src_key_low
+	 * for each compnent.
+	 */
+	__u64 src_key_low;
+	__u64 src_key_high;
+
+	/* See src_key_low/src_key_high */
+	__u64 dst_key_value;
+	/*
+	 * Layout matches that of dst_key_value. The plane is visible
+	 * if the following equation evaluates to true:
+	 * (dst_pixel & dst_key_mask) == (dst_key_value & dst_key_mask)
+	 *
+	 * To disable destination color keying set dst_key_mask to 0.
+	 */
+	__u64 dst_key_mask;
+
+	/* If the hardware uses less bits, the most significat bits are used. */
+	__u16 const_alpha;
+
+	/*
+	 * CRTC is at 0, < 0 is below it, > 0 is above it
+	 * If two planes are configured with the same zorder
+	 * on the same CRTC, the plane with the lower plane_id
+	 * will be stacked closer to the CRTC.
+	 */
+	__s8 zorder;
+
+	/* DRM_CSC_MATRIX_* */
+	__u8 csc_matrix;
+
+	/* DRM_CSC_RANGE_* */
+	__u8 csc_range;
+
+	/* DRM_CHROMA_SITING_* */
+	__u8 chroma_siting;
+
+	/* as defined by VC-1 */
+	__u8 vc1_range_mapy;
+	__u8 vc1_range_mapuv;
+};
+
 #define DRM_MODE_ENCODER_NONE	0
 #define DRM_MODE_ENCODER_DAC	1
 #define DRM_MODE_ENCODER_TMDS	2
-- 
1.7.3.4

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux