[RFC PATCH 7/8] drm: plane: Add plane options ioctl
ville.syrjala at linux.intel.com
ville.syrjala at linux.intel.com
Mon Dec 19 14:33:30 PST 2011
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
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 at linux.intel.com>
---
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
More information about the dri-devel
mailing list