[Intel-gfx] [RFC 1/1] drm/i915: Added support for setting plane alpha through drm property
Sagar Arun Kamble
sagar.a.kamble at intel.com
Mon Feb 24 16:44:41 CET 2014
Gentle Reminder !!!
Kindly review and provide feedback
thanks,
Sagar
On Wed, 2014-02-19 at 15:38 +0530, sagar.a.kamble at intel.com wrote:
> From: Sagar Kamble <sagar.a.kamble at intel.com>
>
> With this patch two properties are added. One for CRTC+Sprite planes
> and another for Cursor planes. Through these client will be able to
> change the pixel format of the planes w.r.t Alpha channel.
> Number of drm properties are limited so should we restrain from adding this
> as drm property or should we expose this as IOCTL itself.
>
> Signed-off-by: Sagar Kamble <sagar.a.kamble at intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 2 +
> drivers/gpu/drm/i915/i915_reg.h | 6 ++
> drivers/gpu/drm/i915/intel_display.c | 156 +++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_drv.h | 8 +-
> drivers/gpu/drm/i915/intel_sprite.c | 59 +++++++++++--
> 5 files changed, 222 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 8c64831..5ced53d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1560,6 +1560,8 @@ typedef struct drm_i915_private {
>
> struct drm_property *broadcast_rgb_property;
> struct drm_property *force_audio_property;
> + struct drm_property *plane_alpha_property;
> + struct drm_property *cursor_alpha_property;
>
> uint32_t hw_context_size;
> struct list_head context_list;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2f564ce..039270e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3522,7 +3522,11 @@
> /* New style CUR*CNTR flags */
> #define CURSOR_MODE 0x27
> #define CURSOR_MODE_DISABLE 0x00
> +#define CURSOR_MODE_128_32B_AX 0x02
> +#define CURSOR_MODE_256_32B_AX 0x03
> #define CURSOR_MODE_64_32B_AX 0x07
> +#define CURSOR_MODE_128_ARGB_AX ((1 << 5) | CURSOR_MODE_128_32B_AX)
> +#define CURSOR_MODE_256_ARGB_AX ((1 << 5) | CURSOR_MODE_256_32B_AX)
> #define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
> #define MCURSOR_PIPE_SELECT (1 << 28)
> #define MCURSOR_PIPE_A 0x00
> @@ -3569,7 +3573,9 @@
> #define DISPPLANE_RGBX101010 (0x8<<26)
> #define DISPPLANE_RGBA101010 (0x9<<26)
> #define DISPPLANE_BGRX101010 (0xa<<26)
> +#define DISPPLANE_BGRA101010 (0xb<<26)
> #define DISPPLANE_RGBX161616 (0xc<<26)
> +#define DISPPLANE_RGBA161616 (0xd<<26)
> #define DISPPLANE_RGBX888 (0xe<<26)
> #define DISPPLANE_RGBA888 (0xf<<26)
> #define DISPPLANE_STEREO_ENABLE (1<<25)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index f19e6ea..a854bcb 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2047,6 +2047,86 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y,
> }
> }
>
> +u32 control_plane_alpha(u32 pixformat, unsigned int alpha)
> +{
> + switch (pixformat) {
> + case DISPPLANE_RGBX888:
> + case DISPPLANE_RGBA888:
> + if (alpha)
> + pixformat = DISPPLANE_RGBA888;
> + else
> + pixformat = DISPPLANE_RGBX888;
> + break;
> + case DISPPLANE_BGRX888:
> + case DISPPLANE_BGRA888:
> + if (alpha)
> + pixformat = DISPPLANE_BGRA888;
> + else
> + pixformat = DISPPLANE_BGRX888;
> + break;
> + case DISPPLANE_RGBX101010:
> + case DISPPLANE_RGBA101010:
> + if (alpha)
> + pixformat = DISPPLANE_RGBA101010;
> + else
> + pixformat = DISPPLANE_RGBX101010;
> + break;
> + case DISPPLANE_BGRX101010:
> + case DISPPLANE_BGRA101010:
> + if (alpha)
> + pixformat = DISPPLANE_BGRA101010;
> + else
> + pixformat = DISPPLANE_BGRX101010;
> + break;
> + case DISPPLANE_RGBX161616:
> + case DISPPLANE_RGBA161616:
> + if (alpha)
> + pixformat = DISPPLANE_RGBA161616;
> + else
> + pixformat = DISPPLANE_RGBX161616;
> + break;
> + default:
> + if (alpha)
> + DRM_DEBUG_DRIVER("Pixel format 0x%08x does not support Alpha Control\n", pixformat);
> + break;
> + }
> + return pixformat;
> +}
> +
> +u32 control_cursor_alpha(u32 pixformat, unsigned int alpha)
> +{
> + switch (pixformat) {
> + case CURSOR_MODE_128_32B_AX:
> + case CURSOR_MODE_128_ARGB_AX:
> + if (alpha)
> + pixformat = CURSOR_MODE_128_ARGB_AX;
> + else
> + pixformat = CURSOR_MODE_128_32B_AX;
> + break;
> +
> + case CURSOR_MODE_256_ARGB_AX:
> + case CURSOR_MODE_256_32B_AX:
> + if (alpha)
> + pixformat = CURSOR_MODE_256_ARGB_AX;
> + else
> + pixformat = CURSOR_MODE_256_32B_AX;
> + break;
> +
> + case CURSOR_MODE_64_ARGB_AX:
> + case CURSOR_MODE_64_32B_AX:
> + if (alpha)
> + pixformat = CURSOR_MODE_64_ARGB_AX;
> + else
> + pixformat = CURSOR_MODE_64_32B_AX;
> + break;
> + default:
> + if (alpha)
> + DRM_DEBUG_DRIVER("Pixel format 0x%08x does not support Alpha Control\n", pixformat);
> + break;
> + }
> + return pixformat;
> +}
> +
> static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> int x, int y)
> {
> @@ -2107,6 +2187,9 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> BUG();
> }
>
> + dspcntr |= control_plane_alpha(dspcntr & DISPPLANE_PIXFORMAT_MASK,
> + intel_crtc->primary_alpha);
> +
> if (INTEL_INFO(dev)->gen >= 4) {
> if (obj->tiling_mode != I915_TILING_NONE)
> dspcntr |= DISPPLANE_TILED;
> @@ -7415,6 +7498,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
> if (base) {
> cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
> cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
> + cntl |= control_cursor_alpha(cntl & CURSOR_MODE, intel_crtc->cursor_alpha);
> cntl |= pipe << 28; /* Connect to correct pipe */
> } else {
> cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
> @@ -8755,6 +8839,59 @@ free_work:
> return ret;
> }
>
> +static int intel_set_primary_plane_alpha(struct intel_crtc *crtc,
> + unsigned int alpha)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + unsigned int old_alpha;
> + int ret = 0;
> +
> + old_alpha = crtc->primary_alpha;
> + crtc->primary_alpha = alpha;
> +
> + if (!crtc->active)
> + return 0;
> +
> + intel_crtc_wait_for_pending_flips(&crtc->base);
> +
> + ret = dev_priv->display.update_plane(&crtc->base, crtc->base.fb, 0, 0);
> + if (ret)
> + crtc->primary_alpha = old_alpha;
> +
> + return ret;
> +}
> +
> +static void intel_set_cursor_plane_alpha(struct intel_crtc *crtc,
> + unsigned int alpha)
> +{
> + crtc->cursor_alpha = alpha;
> +
> + if (crtc->active)
> + intel_crtc_update_cursor(&crtc->base, true);
> +}
> +
> +static int intel_crtc_set_property(struct drm_crtc *crtc,
> + struct drm_property *prop,
> + uint64_t val)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + uint64_t old_val;
> + int ret = -ENOENT;
> +
> + if (prop == dev_priv->plane_alpha_property) {
> + ret = intel_set_primary_plane_alpha(intel_crtc,
> + intel_crtc->primary_alpha);
> + } else if (prop == dev_priv->cursor_alpha_property) {
> + intel_set_cursor_plane_alpha(intel_crtc, val);
> + return 0;
> + }
> +
> + return ret;
> +}
> +
> static struct drm_crtc_helper_funcs intel_helper_funcs = {
> .mode_set_base_atomic = intel_pipe_set_base_atomic,
> .load_lut = intel_crtc_load_lut,
> @@ -10167,6 +10304,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
> .set_config = intel_crtc_set_config,
> .destroy = intel_crtc_destroy,
> .page_flip = intel_crtc_page_flip,
> + .set_property = intel_crtc_set_property
> };
>
> static void intel_cpu_pll_init(struct drm_device *dev)
> @@ -10305,6 +10443,24 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
> dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
> dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
>
> + if (!dev_priv->plane_alpha_property)
> + dev_priv->plane_alpha_property =
> + drm_property_create_range(dev, 0, "plane-alpha", 0, 1);
> +
> + if (dev_priv->plane_alpha_property)
> + drm_object_attach_property(&intel_crtc->base.base,
> + dev_priv->plane_alpha_property,
> + intel_crtc->primary_alpha);
> +
> + if (!dev_priv->cursor_alpha_property)
> + dev_priv->cursor_alpha_property =
> + drm_property_create_range(dev, 0, "cursor-alpha", 0, 1);
> +
> + if (dev_priv->cursor_alpha_property)
> + drm_object_attach_property(&intel_crtc->base.base,
> + dev_priv->cursor_alpha_property,
> + intel_crtc->cursor_alpha);
> +
> drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
> }
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index a4ffc02..0080d3a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -339,6 +339,9 @@ struct intel_crtc {
> struct drm_crtc base;
> enum pipe pipe;
> enum plane plane;
> + unsigned int primary_alpha; /* primary plane alpha control */
> + unsigned int cursor_alpha; /* cursor plane alpha control */
> +
> u8 lut_r[256], lut_g[256], lut_b[256];
> /*
> * Whether the crtc and the connected output pipeline is active. Implies
> @@ -405,6 +408,7 @@ struct intel_plane {
> unsigned int crtc_w, crtc_h;
> uint32_t src_x, src_y;
> uint32_t src_w, src_h;
> + unsigned int plane_alpha;
>
> /* Since we need to change the watermarks before/after
> * enabling/disabling the planes, we need to store the parameters here
> @@ -676,6 +680,8 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
> enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
> enum pipe pipe);
> void intel_wait_for_vblank(struct drm_device *dev, int pipe);
> +u32 control_plane_alpha(u32 pixformat, unsigned int alpha);
> +u32 control_cursor_alpha(u32 pixformat, unsigned int alpha);
> void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
> int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
> void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
> @@ -906,7 +912,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
> int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
> void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
> enum plane plane);
> -void intel_plane_restore(struct drm_plane *plane);
> +int intel_plane_restore(struct drm_plane *plane);
> void intel_plane_disable(struct drm_plane *plane);
> int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
> struct drm_file *file_priv);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 336ae6c..9f6c91a 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -104,6 +104,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
> break;
> }
>
> + sprctl |= control_plane_alpha(sprctl & SP_PIXFORMAT_MASK,
> + intel_plane->plane_alpha);
> +
> /*
> * Enable gamma to match primary/cursor plane behaviour.
> * FIXME should be user controllable via propertiesa.
> @@ -262,6 +265,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> BUG();
> }
>
> + sprctl |= control_plane_alpha(sprctl & SPRITE_PIXFORMAT_MASK,
> + intel_plane->plane_alpha);
> +
> /*
> * Enable gamma to match primary/cursor plane behaviour.
> * FIXME should be user controllable via propertiesa.
> @@ -446,6 +452,9 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> BUG();
> }
>
> + dvscntr |= control_plane_alpha(dvscntr & DVS_PIXFORMAT_MASK,
> + intel_plane->plane_alpha);
> +
> /*
> * Enable gamma to match primary/cursor plane behaviour.
> * FIXME should be user controllable via propertiesa.
> @@ -1011,18 +1020,38 @@ out_unlock:
> return ret;
> }
>
> -void intel_plane_restore(struct drm_plane *plane)
> +static int intel_plane_set_property(struct drm_plane *plane,
> + struct drm_property *prop,
> + uint64_t val)
> +{
> + struct drm_i915_private *dev_priv = plane->dev->dev_private;
> + struct intel_plane *intel_plane = to_intel_plane(plane);
> + uint64_t old_val;
> + int ret = -ENOENT;
> +
> + if (prop == dev_priv->plane_alpha_property) {
> + old_val = intel_plane->plane_alpha;
> + intel_plane->plane_alpha = val;
> + ret = intel_plane_restore(plane);
> + if (ret)
> + intel_plane->plane_alpha = old_val;
> + }
> +
> + return ret;
> +}
> +
> +int intel_plane_restore(struct drm_plane *plane)
> {
> struct intel_plane *intel_plane = to_intel_plane(plane);
>
> if (!plane->crtc || !plane->fb)
> - return;
> + return 0;
>
> - intel_update_plane(plane, plane->crtc, plane->fb,
> - intel_plane->crtc_x, intel_plane->crtc_y,
> - intel_plane->crtc_w, intel_plane->crtc_h,
> - intel_plane->src_x, intel_plane->src_y,
> - intel_plane->src_w, intel_plane->src_h);
> + return intel_update_plane(plane, plane->crtc, plane->fb,
> + intel_plane->crtc_x, intel_plane->crtc_y,
> + intel_plane->crtc_w, intel_plane->crtc_h,
> + intel_plane->src_x, intel_plane->src_y,
> + intel_plane->src_w, intel_plane->src_h);
> }
>
> void intel_plane_disable(struct drm_plane *plane)
> @@ -1037,6 +1066,7 @@ static const struct drm_plane_funcs intel_plane_funcs = {
> .update_plane = intel_update_plane,
> .disable_plane = intel_disable_plane,
> .destroy = intel_destroy_plane,
> + .set_property = intel_plane_set_property,
> };
>
> static uint32_t ilk_plane_formats[] = {
> @@ -1073,6 +1103,7 @@ static uint32_t vlv_plane_formats[] = {
> int
> intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
> {
> + struct drm_i915_private *dev_priv = dev->dev_private;
> struct intel_plane *intel_plane;
> unsigned long possible_crtcs;
> const uint32_t *plane_formats;
> @@ -1146,8 +1177,20 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
> &intel_plane_funcs,
> plane_formats, num_plane_formats,
> false);
> - if (ret)
> + if (ret) {
> kfree(intel_plane);
> + goto out;
> + }
> +
> + if (!dev_priv->plane_alpha_property)
> + dev_priv->plane_alpha_property =
> + drm_property_create_range(dev, 0, "plane-alpha", 0, 1);
> +
> + if (dev_priv->plane_alpha_property)
> + drm_object_attach_property(&intel_plane->base.base,
> + dev_priv->plane_alpha_property,
> + intel_plane->plane_alpha);
>
> +out:
> return ret;
> }
More information about the Intel-gfx
mailing list