No constant alpha yet though, that needs a new ioctl and/or property to get/set. v2: use drm_plane_format_cpp (Ville) fix up vlv_disable_plane, remove IVB bits (Ville) remove error path rework (Ville) fix component order confusion (Ville) clean up platform init (Ville) use compute_offset_xtiled (Ville) Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org> --- drivers/gpu/drm/i915/i915_dma.c | 4 + drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 57 +++++++++ drivers/gpu/drm/i915/intel_display.c | 13 ++- drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/i915/intel_sprite.c | 211 ++++++++++++++++++++++++++++++++-- 6 files changed, 275 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e16099b..2ba68b0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1637,6 +1637,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) else dev_priv->num_pipe = 1; + dev_priv->num_plane = 1; + if (IS_VALLEYVIEW(dev)) + dev_priv->num_plane = 2; + ret = drm_vblank_init(dev, dev_priv->num_pipe); if (ret) goto out_gem_unload; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ca6b215..2b4d9b6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -914,6 +914,7 @@ typedef struct drm_i915_private { int num_pipe; int num_pch_pll; + int num_plane; unsigned long cfb_size; unsigned int cfb_fb; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4cf3ece..669a61c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3258,6 +3258,63 @@ #define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC) #define SPRSURFLIVE(pipe) _PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE) +#define _SPACNTR 0x72180 +#define SP_ENABLE (1<<31) +#define SP_GEAMMA_ENABLE (1<<30) +#define SP_PIXFORMAT_MASK (0xf<<26) +#define SP_FORMAT_YUV422 (0<<26) +#define SP_FORMAT_BGR565 (5<<26) +#define SP_FORMAT_BGRX8888 (6<<26) +#define SP_FORMAT_BGRA8888 (7<<26) +#define SP_FORMAT_RGBX1010102 (8<<26) +#define SP_FORMAT_RGBA1010102 (9<<26) +#define SP_FORMAT_RGBX8888 (0xe<<26) +#define SP_FORMAT_RGBA8888 (0xf<<26) +#define SP_SOURCE_KEY (1<<22) +#define SP_YUV_BYTE_ORDER_MASK (3<<16) +#define SP_YUV_ORDER_YUYV (0<<16) +#define SP_YUV_ORDER_UYVY (1<<16) +#define SP_YUV_ORDER_YVYU (2<<16) +#define SP_YUV_ORDER_VYUY (3<<16) +#define SP_TILED (1<<10) +#define _SPALINOFF 0x72184 +#define _SPASTRIDE 0x72188 +#define _SPAPOS 0x7218c +#define _SPASIZE 0x72190 +#define _SPAKEYMINVAL 0x72194 +#define _SPAKEYMSK 0x72198 +#define _SPASURF 0x7219c +#define _SPAKEYMAXVAL 0x721a0 +#define _SPATILEOFF 0x721a4 +#define _SPACONSTALPHA 0x721a8 +#define _SPAGAMC 0x721f4 + +#define _SPBCNTR 0x72280 +#define _SPBLINOFF 0x72284 +#define _SPBSTRIDE 0x72288 +#define _SPBPOS 0x7228c +#define _SPBSIZE 0x72290 +#define _SPBKEYMINVAL 0x72294 +#define _SPBKEYMSK 0x72298 +#define _SPBSURF 0x7229c +#define _SPBKEYMAXVAL 0x722a0 +#define _SPBTILEOFF 0x722a4 +#define _SPBCONSTALPHA 0x722a8 +#define _SPBGAMC 0x722f4 + +#define SPCNTR(pipe, plane) _PIPE(pipe * 2 + plane, _SPACNTR, _SPBCNTR) +#define SPLINOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPALINOFF, _SPBLINOFF) +#define SPSTRIDE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASTRIDE, _SPBSTRIDE) +#define SPPOS(pipe, plane) _PIPE(pipe * 2 + plane, _SPAPOS, _SPBPOS) +#define SPSIZE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASIZE, _SPBSIZE) +#define SPKEYMINVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMINVAL, _SPBKEYMINVAL) +#define SPKEYMSK(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMSK, _SPBKEYMSK) +#define SPSURF(pipe, plane) _PIPE(pipe * 2 + plane, _SPASURF, _SPBSURF) +#define SPKEYMAXVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMAXVAL, _SPBKEYMAXVAL) +#define SPTILEOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPATILEOFF, _SPBTILEOFF) +#define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA) +#define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC) + /* VBIOS regs */ #define VGACNTRL 0x71400 # define VGA_DISP_DISABLE (1 << 31) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 502cb28..860bf7c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8508,6 +8508,8 @@ int intel_framebuffer_init(struct drm_device *dev, case DRM_FORMAT_C8: case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: case DRM_FORMAT_ARGB8888: break; case DRM_FORMAT_XRGB1555: @@ -8839,7 +8841,7 @@ void intel_modeset_init_hw(struct drm_device *dev) void intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int i, ret; + int i, j, ret; drm_mode_config_init(dev); @@ -8874,9 +8876,12 @@ void intel_modeset_init(struct drm_device *dev) for (i = 0; i < dev_priv->num_pipe; i++) { intel_crtc_init(dev, i); - ret = intel_plane_init(dev, i); - if (ret) - DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret); + for (j = 0; j < dev_priv->num_plane; j++) { + ret = intel_plane_init(dev, i, j); + if (ret) + DRM_DEBUG_KMS("pipe %d plane %d init failed: %d\n", + i, j, ret); + } } intel_cpu_pll_init(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 010e998..494037d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -242,6 +242,7 @@ struct intel_crtc { struct intel_plane { struct drm_plane base; + int plane; enum pipe pipe; struct drm_i915_gem_object *obj; bool can_scale; @@ -488,7 +489,7 @@ extern void intel_edp_link_config(struct intel_encoder *, int *, int *); extern int intel_edp_target_clock(struct intel_encoder *, struct drm_display_mode *mode); extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); -extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); +extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, enum plane plane); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d086e48..26fee2f 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -37,6 +37,172 @@ #include "i915_drv.h" static void +vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t x, uint32_t y, + uint32_t src_w, uint32_t src_h) +{ + struct drm_device *dev = dplane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_plane *intel_plane = to_intel_plane(dplane); + int pipe = intel_plane->pipe; + int plane = intel_plane->plane; + u32 sprctl; + unsigned long sprsurf_offset, linear_offset; + int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + + sprctl = I915_READ(SPCNTR(pipe, plane)); + + /* Mask out pixel format bits in case we change it */ + sprctl &= ~SP_PIXFORMAT_MASK; + sprctl &= ~SP_YUV_BYTE_ORDER_MASK; + sprctl &= ~SP_TILED; + + switch (fb->pixel_format) { + case DRM_FORMAT_YUYV: + sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; + break; + case DRM_FORMAT_YVYU: + sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; + break; + case DRM_FORMAT_UYVY: + sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; + break; + case DRM_FORMAT_VYUY: + sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; + break; + case DRM_FORMAT_BGR565: + sprctl |= SP_FORMAT_BGR565; + break; + case DRM_FORMAT_BGRX8888: + sprctl |= SP_FORMAT_BGRX8888; + break; + case DRM_FORMAT_BGRA8888: + sprctl |= SP_FORMAT_BGRA8888; + break; + case DRM_FORMAT_RGBX1010102: + sprctl |= SP_FORMAT_RGBX1010102; + break; + case DRM_FORMAT_RGBA1010102: + sprctl |= SP_FORMAT_RGBA1010102; + break; + case DRM_FORMAT_RGBX8888: + sprctl |= SP_FORMAT_RGBX8888; + break; + case DRM_FORMAT_RGBA8888: + sprctl |= SP_FORMAT_RGBA8888; + break; + default: + /* + * If we get here one of the upper layers failed to filter + * out the unsupported plane formats + */ + BUG(); + break; + } + + if (obj->tiling_mode != I915_TILING_NONE) + sprctl |= SP_TILED; + + sprctl |= SP_ENABLE; + + /* Sizes are 0 based */ + src_w--; + src_h--; + crtc_w--; + crtc_h--; + + intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); + + I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); + I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); + + linear_offset = y * fb->pitches[0] + x * pixel_size; + sprsurf_offset = intel_gen4_compute_offset_xtiled(&x, &y, pixel_size, + fb->pitches[0]); + linear_offset -= sprsurf_offset; + + if (obj->tiling_mode != I915_TILING_NONE) + I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); + else + I915_WRITE(SPLINOFF(pipe, plane), linear_offset); + + I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); + I915_WRITE(SPCNTR(pipe, plane), sprctl); + I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset + + sprsurf_offset); + POSTING_READ(SPSURF(pipe, plane)); +} + +static void +vlv_disable_plane(struct drm_plane *dplane) +{ + struct drm_device *dev = dplane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_plane *intel_plane = to_intel_plane(dplane); + int pipe = intel_plane->pipe; + int plane = intel_plane->plane; + + I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & + ~SP_ENABLE); + /* Activate double buffered register update */ + I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0); + POSTING_READ(SPSURF(pipe, plane)); +} + +static int +vlv_update_colorkey(struct drm_plane *dplane, + struct drm_intel_sprite_colorkey *key) +{ + struct drm_device *dev = dplane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_plane *intel_plane = to_intel_plane(dplane); + int pipe = intel_plane->pipe; + int plane = intel_plane->plane; + u32 sprctl; + + if (key->flags & I915_SET_COLORKEY_DESTINATION) + return -EINVAL; + + I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); + I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); + I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); + + sprctl = I915_READ(SPCNTR(pipe, plane)); + sprctl &= ~SP_SOURCE_KEY; + if (key->flags & I915_SET_COLORKEY_SOURCE) + sprctl |= SP_SOURCE_KEY; + I915_WRITE(SPCNTR(pipe, plane), sprctl); + + POSTING_READ(SPKEYMSK(pipe, plane)); + + return 0; +} + +static void +vlv_get_colorkey(struct drm_plane *dplane, + struct drm_intel_sprite_colorkey *key) +{ + struct drm_device *dev = dplane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_plane *intel_plane = to_intel_plane(dplane); + int pipe = intel_plane->pipe; + int plane = intel_plane->plane; + u32 sprctl; + + key->min_value = I915_READ(SPKEYMINVAL(pipe, plane)); + key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane)); + key->channel_mask = I915_READ(SPKEYMSK(pipe, plane)); + + sprctl = I915_READ(SPCNTR(pipe, plane)); + if (sprctl & SP_SOURCE_KEY) + key->flags = I915_SET_COLORKEY_SOURCE; + else + key->flags = I915_SET_COLORKEY_NONE; +} + +static void ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, @@ -670,8 +836,22 @@ static uint32_t snb_plane_formats[] = { DRM_FORMAT_VYUY, }; +static uint32_t vlv_plane_formats[] = { + DRM_FORMAT_BGR565, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, +}; + int -intel_plane_init(struct drm_device *dev, enum pipe pipe) +intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) { struct intel_plane *intel_plane; unsigned long possible_crtcs; @@ -710,14 +890,26 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) intel_plane->can_scale = false; else intel_plane->can_scale = true; - intel_plane->max_downscale = 2; - intel_plane->update_plane = ivb_update_plane; - intel_plane->disable_plane = ivb_disable_plane; - intel_plane->update_colorkey = ivb_update_colorkey; - intel_plane->get_colorkey = ivb_get_colorkey; - - plane_formats = snb_plane_formats; - num_plane_formats = ARRAY_SIZE(snb_plane_formats); + + if (IS_VALLEYVIEW(dev)) { + intel_plane->max_downscale = 1; + intel_plane->update_plane = vlv_update_plane; + intel_plane->disable_plane = vlv_disable_plane; + intel_plane->update_colorkey = vlv_update_colorkey; + intel_plane->get_colorkey = vlv_get_colorkey; + + plane_formats = vlv_plane_formats; + num_plane_formats = ARRAY_SIZE(vlv_plane_formats); + } else { + intel_plane->max_downscale = 2; + intel_plane->update_plane = ivb_update_plane; + intel_plane->disable_plane = ivb_disable_plane; + intel_plane->update_colorkey = ivb_update_colorkey; + intel_plane->get_colorkey = ivb_get_colorkey; + + plane_formats = snb_plane_formats; + num_plane_formats = ARRAY_SIZE(snb_plane_formats); + } break; default: @@ -726,6 +918,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) } intel_plane->pipe = pipe; + intel_plane->plane = plane; possible_crtcs = (1 << pipe); ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, -- 1.7.10.4