drm/i915: Fix display pixel format handling

Fix support for all RGB/BGR pixel formats (except the 16:16:16:16 float
format).

Fix intel_init_framebuffer() to match hardware and driver limitations:
* RGB332 is not supported at all
* CI8 is supported
* XRGB1555 & co. are supported on Gen3 and earlier
* XRGB210101010 & co. are supported from Gen4 onwards
* BGR formats are supported from Gen4 onwards
* YUV formats are supported from Gen5 onwards (driver limitation)

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Ville Syrjälä 2012-10-31 17:50:14 +02:00 committed by Daniel Vetter
parent e7210c3c4f
commit 57779d0636
2 changed files with 74 additions and 37 deletions

View File

@ -3009,12 +3009,19 @@
#define DISPPLANE_GAMMA_ENABLE (1<<30) #define DISPPLANE_GAMMA_ENABLE (1<<30)
#define DISPPLANE_GAMMA_DISABLE 0 #define DISPPLANE_GAMMA_DISABLE 0
#define DISPPLANE_PIXFORMAT_MASK (0xf<<26) #define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
#define DISPPLANE_YUV422 (0x0<<26)
#define DISPPLANE_8BPP (0x2<<26) #define DISPPLANE_8BPP (0x2<<26)
#define DISPPLANE_15_16BPP (0x4<<26) #define DISPPLANE_BGRA555 (0x3<<26)
#define DISPPLANE_16BPP (0x5<<26) #define DISPPLANE_BGRX555 (0x4<<26)
#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) #define DISPPLANE_BGRX565 (0x5<<26)
#define DISPPLANE_32BPP (0x7<<26) #define DISPPLANE_BGRX888 (0x6<<26)
#define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26) #define DISPPLANE_BGRA888 (0x7<<26)
#define DISPPLANE_RGBX101010 (0x8<<26)
#define DISPPLANE_RGBA101010 (0x9<<26)
#define DISPPLANE_BGRX101010 (0xa<<26)
#define DISPPLANE_RGBX161616 (0xc<<26)
#define DISPPLANE_RGBX888 (0xe<<26)
#define DISPPLANE_RGBA888 (0xf<<26)
#define DISPPLANE_STEREO_ENABLE (1<<25) #define DISPPLANE_STEREO_ENABLE (1<<25)
#define DISPPLANE_STEREO_DISABLE 0 #define DISPPLANE_STEREO_DISABLE 0
#define DISPPLANE_SEL_PIPE_SHIFT 24 #define DISPPLANE_SEL_PIPE_SHIFT 24

View File

@ -2000,24 +2000,38 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
dspcntr = I915_READ(reg); dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */ /* Mask out pixel format bits in case we change it */
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
switch (fb->bits_per_pixel) { switch (fb->pixel_format) {
case 8: case DRM_FORMAT_C8:
dspcntr |= DISPPLANE_8BPP; dspcntr |= DISPPLANE_8BPP;
break; break;
case 16: case DRM_FORMAT_XRGB1555:
if (fb->depth == 15) case DRM_FORMAT_ARGB1555:
dspcntr |= DISPPLANE_15_16BPP; dspcntr |= DISPPLANE_BGRX555;
else
dspcntr |= DISPPLANE_16BPP;
break; break;
case 24: case DRM_FORMAT_RGB565:
case 32: dspcntr |= DISPPLANE_BGRX565;
dspcntr |= DISPPLANE_32BPP_NO_ALPHA; break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
dspcntr |= DISPPLANE_BGRX888;
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
dspcntr |= DISPPLANE_RGBX888;
break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
dspcntr |= DISPPLANE_BGRX101010;
break;
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
dspcntr |= DISPPLANE_RGBX101010;
break; break;
default: default:
DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel); DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
return -EINVAL; return -EINVAL;
} }
if (INTEL_INFO(dev)->gen >= 4) { if (INTEL_INFO(dev)->gen >= 4) {
if (obj->tiling_mode != I915_TILING_NONE) if (obj->tiling_mode != I915_TILING_NONE)
dspcntr |= DISPPLANE_TILED; dspcntr |= DISPPLANE_TILED;
@ -2084,27 +2098,31 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
dspcntr = I915_READ(reg); dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */ /* Mask out pixel format bits in case we change it */
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
switch (fb->bits_per_pixel) { switch (fb->pixel_format) {
case 8: case DRM_FORMAT_C8:
dspcntr |= DISPPLANE_8BPP; dspcntr |= DISPPLANE_8BPP;
break; break;
case 16: case DRM_FORMAT_RGB565:
if (fb->depth != 16) dspcntr |= DISPPLANE_BGRX565;
return -EINVAL;
dspcntr |= DISPPLANE_16BPP;
break; break;
case 24: case DRM_FORMAT_XRGB8888:
case 32: case DRM_FORMAT_ARGB8888:
if (fb->depth == 24) dspcntr |= DISPPLANE_BGRX888;
dspcntr |= DISPPLANE_32BPP_NO_ALPHA; break;
else if (fb->depth == 30) case DRM_FORMAT_XBGR8888:
dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA; case DRM_FORMAT_ABGR8888:
else dspcntr |= DISPPLANE_RGBX888;
return -EINVAL; break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
dspcntr |= DISPPLANE_BGRX101010;
break;
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
dspcntr |= DISPPLANE_RGBX101010;
break; break;
default: default:
DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel); DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
return -EINVAL; return -EINVAL;
} }
@ -8334,24 +8352,36 @@ int intel_framebuffer_init(struct drm_device *dev,
if (mode_cmd->pitches[0] & 63) if (mode_cmd->pitches[0] & 63)
return -EINVAL; return -EINVAL;
/* Reject formats not supported by any plane early. */
switch (mode_cmd->pixel_format) { switch (mode_cmd->pixel_format) {
case DRM_FORMAT_RGB332: case DRM_FORMAT_C8:
case DRM_FORMAT_RGB565: case DRM_FORMAT_RGB565:
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
if (INTEL_INFO(dev)->gen > 3)
return -EINVAL;
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_ARGB2101010:
/* RGB formats are common across chipsets */ case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
if (INTEL_INFO(dev)->gen < 4)
return -EINVAL;
break; break;
case DRM_FORMAT_YUYV: case DRM_FORMAT_YUYV:
case DRM_FORMAT_UYVY: case DRM_FORMAT_UYVY:
case DRM_FORMAT_YVYU: case DRM_FORMAT_YVYU:
case DRM_FORMAT_VYUY: case DRM_FORMAT_VYUY:
if (INTEL_INFO(dev)->gen < 6)
return -EINVAL;
break; break;
default: default:
DRM_DEBUG_KMS("unsupported pixel format %u\n", DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
mode_cmd->pixel_format);
return -EINVAL; return -EINVAL;
} }