Skip to content

Commit

Permalink
drm/i915/skl: Allow scanning out Y and Yf fbs
Browse files Browse the repository at this point in the history
Skylake is able to scannout those tiling formats. We need to allow them
in the ADDFB ioctl and tell the harware about it.

v2: Rebased for addfb2 interface. (Tvrtko Ursulin)
v3: Rebased for fb modifier changes. (Tvrtko Ursulin)
v4: Don't allow Y tiled fbs just yet. (Tvrtko Ursulin)
v5: Check for stride alignment and max pitch. (Tvrtko Ursulin)
v6: Simplify maximum pitch check. (Ville Syrjälä)
v7: Drop the gen9 check since requirements are no different. (Ville Syrjälä)
v8: Gen2 has different X tiling stride. (Ville Syrjälä)

Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> (v7)
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Damien Lespiau authored and Daniel Vetter committed Feb 27, 2015
1 parent b5ff6e1 commit b321803
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 40 deletions.
121 changes: 86 additions & 35 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2728,17 +2728,50 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
POSTING_READ(reg);
}

u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
uint32_t pixel_format)
{
u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;

/*
* The stride is either expressed as a multiple of 64 bytes
* chunks for linear buffers or in number of tiles for tiled
* buffers.
*/
switch (fb_modifier) {
case DRM_FORMAT_MOD_NONE:
return 64;
case I915_FORMAT_MOD_X_TILED:
if (INTEL_INFO(dev)->gen == 2)
return 128;
return 512;
case I915_FORMAT_MOD_Y_TILED:
/* No need to check for old gens and Y tiling since this is
* about the display engine and those will be blocked before
* we get here.
*/
return 128;
case I915_FORMAT_MOD_Yf_TILED:
if (bits_per_pixel == 8)
return 64;
else
return 128;
default:
MISSING_CASE(fb_modifier);
return 64;
}
}

static void skylake_update_primary_plane(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int x, int y)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_framebuffer *intel_fb;
struct drm_i915_gem_object *obj;
int pipe = intel_crtc->pipe;
u32 plane_ctl, stride;
u32 plane_ctl, stride_div;

if (!intel_crtc->primary_enabled) {
I915_WRITE(PLANE_CTL(pipe, 0), 0);
Expand Down Expand Up @@ -2773,29 +2806,30 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
BUG();
}

intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;

/*
* The stride is either expressed as a multiple of 64 bytes chunks for
* linear buffers or in number of tiles for tiled buffers.
*/
switch (fb->modifier[0]) {
case DRM_FORMAT_MOD_NONE:
stride = fb->pitches[0] >> 6;
break;
case I915_FORMAT_MOD_X_TILED:
plane_ctl |= PLANE_CTL_TILED_X;
stride = fb->pitches[0] >> 9;
break;
case I915_FORMAT_MOD_Y_TILED:
plane_ctl |= PLANE_CTL_TILED_Y;
break;
case I915_FORMAT_MOD_Yf_TILED:
plane_ctl |= PLANE_CTL_TILED_YF;
break;
default:
BUG();
MISSING_CASE(fb->modifier[0]);
}

plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180))
plane_ctl |= PLANE_CTL_ROTATE_180;

obj = intel_fb_obj(fb);
stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
fb->pixel_format);

I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);

DRM_DEBUG_KMS("Writing base %08lX %d,%d,%d,%d pitch=%d\n",
Expand All @@ -2808,7 +2842,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
I915_WRITE(PLANE_SIZE(pipe, 0),
(intel_crtc->config->pipe_src_h - 1) << 16 |
(intel_crtc->config->pipe_src_w - 1));
I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
I915_WRITE(PLANE_STRIDE(pipe, 0), fb->pitches[0] / stride_div);
I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj));

POSTING_READ(PLANE_SURF(pipe, 0));
Expand Down Expand Up @@ -12666,14 +12700,43 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
.create_handle = intel_user_framebuffer_create_handle,
};

static
u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
uint32_t pixel_format)
{
u32 gen = INTEL_INFO(dev)->gen;

if (gen >= 9) {
/* "The stride in bytes must not exceed the of the size of 8K
* pixels and 32K bytes."
*/
return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
} else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
return 32*1024;
} else if (gen >= 4) {
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
return 16*1024;
else
return 32*1024;
} else if (gen >= 3) {
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
return 8*1024;
else
return 16*1024;
} else {
/* XXX DSPC is limited to 4k tiled */
return 8*1024;
}
}

static int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *intel_fb,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj)
{
int aligned_height;
int pitch_limit;
int ret;
u32 pitch_limit, stride_alignment;

WARN_ON(!mutex_is_locked(&dev->struct_mutex));

Expand All @@ -12699,31 +12762,19 @@ static int intel_framebuffer_init(struct drm_device *dev,
return -EINVAL;
}

if (mode_cmd->pitches[0] & 63) {
DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n",
mode_cmd->pitches[0]);
stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
mode_cmd->pixel_format);
if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
mode_cmd->pitches[0], stride_alignment);
return -EINVAL;
}

if (INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev)) {
pitch_limit = 32*1024;
} else if (INTEL_INFO(dev)->gen >= 4) {
if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)
pitch_limit = 16*1024;
else
pitch_limit = 32*1024;
} else if (INTEL_INFO(dev)->gen >= 3) {
if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)
pitch_limit = 8*1024;
else
pitch_limit = 16*1024;
} else
/* XXX DSPC is limited to 4k tiled */
pitch_limit = 8*1024;

pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0],
mode_cmd->pixel_format);
if (mode_cmd->pitches[0] > pitch_limit) {
DRM_DEBUG("%s pitch (%d) must be at less than %d\n",
mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED ?
DRM_DEBUG("%s pitch (%u) must be at less than %d\n",
mode_cmd->modifier[0] != DRM_FORMAT_MOD_NONE ?
"tiled" : "linear",
mode_cmd->pitches[0], pitch_limit);
return -EINVAL;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ int intel_fb_align_height(struct drm_device *dev, int height,
uint64_t fb_format_modifier);
void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);

u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
uint32_t pixel_format);

/* intel_audio.c */
void intel_init_audio(struct drm_device *dev);
Expand Down
18 changes: 13 additions & 5 deletions drivers/gpu/drm/i915/intel_sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
struct intel_plane *intel_plane = to_intel_plane(drm_plane);
const int pipe = intel_plane->pipe;
const int plane = intel_plane->plane + 1;
u32 plane_ctl, stride;
u32 plane_ctl, stride_div;
int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);

plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
Expand Down Expand Up @@ -247,15 +247,20 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,

switch (fb->modifier[0]) {
case DRM_FORMAT_MOD_NONE:
stride = fb->pitches[0] >> 6;
break;
case I915_FORMAT_MOD_X_TILED:
plane_ctl |= PLANE_CTL_TILED_X;
stride = fb->pitches[0] >> 9;
break;
case I915_FORMAT_MOD_Y_TILED:
plane_ctl |= PLANE_CTL_TILED_Y;
break;
case I915_FORMAT_MOD_Yf_TILED:
plane_ctl |= PLANE_CTL_TILED_YF;
break;
default:
BUG();
MISSING_CASE(fb->modifier[0]);
}

if (drm_plane->state->rotation == BIT(DRM_ROTATE_180))
plane_ctl |= PLANE_CTL_ROTATE_180;

Expand All @@ -266,14 +271,17 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
pixel_size, true,
src_w != crtc_w || src_h != crtc_h);

stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
fb->pixel_format);

/* Sizes are 0 based */
src_w--;
src_h--;
crtc_w--;
crtc_h--;

I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
I915_WRITE(PLANE_STRIDE(pipe, plane), fb->pitches[0] / stride_div);
I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
Expand Down

0 comments on commit b321803

Please sign in to comment.