|
@@ -1994,11 +1994,19 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane)
|
|
return 128;
|
|
return 128;
|
|
else
|
|
else
|
|
return 512;
|
|
return 512;
|
|
|
|
+ case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
|
|
+ if (plane == 1)
|
|
|
|
+ return 128;
|
|
|
|
+ /* fall through */
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
|
|
if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
|
|
return 128;
|
|
return 128;
|
|
else
|
|
else
|
|
return 512;
|
|
return 512;
|
|
|
|
+ case I915_FORMAT_MOD_Yf_TILED_CCS:
|
|
|
|
+ if (plane == 1)
|
|
|
|
+ return 128;
|
|
|
|
+ /* fall through */
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
switch (cpp) {
|
|
switch (cpp) {
|
|
case 1:
|
|
case 1:
|
|
@@ -2105,7 +2113,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
|
|
struct drm_i915_private *dev_priv = to_i915(fb->dev);
|
|
struct drm_i915_private *dev_priv = to_i915(fb->dev);
|
|
|
|
|
|
/* AUX_DIST needs only 4K alignment */
|
|
/* AUX_DIST needs only 4K alignment */
|
|
- if (fb->format->format == DRM_FORMAT_NV12 && plane == 1)
|
|
|
|
|
|
+ if (plane == 1)
|
|
return 4096;
|
|
return 4096;
|
|
|
|
|
|
switch (fb->modifier) {
|
|
switch (fb->modifier) {
|
|
@@ -2115,6 +2123,8 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
|
|
if (INTEL_GEN(dev_priv) >= 9)
|
|
if (INTEL_GEN(dev_priv) >= 9)
|
|
return 256 * 1024;
|
|
return 256 * 1024;
|
|
return 0;
|
|
return 0;
|
|
|
|
+ case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
|
|
+ case I915_FORMAT_MOD_Yf_TILED_CCS:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
return 1 * 1024 * 1024;
|
|
return 1 * 1024 * 1024;
|
|
@@ -2422,6 +2432,7 @@ static unsigned int intel_fb_modifier_to_tiling(uint64_t fb_modifier)
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
return I915_TILING_X;
|
|
return I915_TILING_X;
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
+ case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
return I915_TILING_Y;
|
|
return I915_TILING_Y;
|
|
default:
|
|
default:
|
|
return I915_TILING_NONE;
|
|
return I915_TILING_NONE;
|
|
@@ -2486,6 +2497,36 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
intel_fb_offset_to_xy(&x, &y, fb, i);
|
|
intel_fb_offset_to_xy(&x, &y, fb, i);
|
|
|
|
|
|
|
|
+ if ((fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
|
|
|
|
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) && i == 1) {
|
|
|
|
+ int hsub = fb->format->hsub;
|
|
|
|
+ int vsub = fb->format->vsub;
|
|
|
|
+ int tile_width, tile_height;
|
|
|
|
+ int main_x, main_y;
|
|
|
|
+ int ccs_x, ccs_y;
|
|
|
|
+
|
|
|
|
+ intel_tile_dims(fb, i, &tile_width, &tile_height);
|
|
|
|
+
|
|
|
|
+ ccs_x = (x * hsub) % (tile_width * hsub);
|
|
|
|
+ ccs_y = (y * vsub) % (tile_height * vsub);
|
|
|
|
+ main_x = intel_fb->normal[0].x % (tile_width * hsub);
|
|
|
|
+ main_y = intel_fb->normal[0].y % (tile_height * vsub);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * CCS doesn't have its own x/y offset register, so the intra CCS tile
|
|
|
|
+ * x/y offsets must match between CCS and the main surface.
|
|
|
|
+ */
|
|
|
|
+ if (main_x != ccs_x || main_y != ccs_y) {
|
|
|
|
+ DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n",
|
|
|
|
+ main_x, main_y,
|
|
|
|
+ ccs_x, ccs_y,
|
|
|
|
+ intel_fb->normal[0].x,
|
|
|
|
+ intel_fb->normal[0].y,
|
|
|
|
+ x, y);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* The fence (if used) is aligned to the start of the object
|
|
* The fence (if used) is aligned to the start of the object
|
|
* so having the framebuffer wrap around across the edge of the
|
|
* so having the framebuffer wrap around across the edge of the
|
|
@@ -2846,6 +2887,9 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
+ case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
|
|
+ case I915_FORMAT_MOD_Yf_TILED_CCS:
|
|
|
|
+ /* FIXME AUX plane? */
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
switch (cpp) {
|
|
switch (cpp) {
|
|
@@ -2868,6 +2912,44 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
|
|
return 2048;
|
|
return 2048;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
|
|
|
|
+ int main_x, int main_y, u32 main_offset)
|
|
|
|
+{
|
|
|
|
+ const struct drm_framebuffer *fb = plane_state->base.fb;
|
|
|
|
+ int hsub = fb->format->hsub;
|
|
|
|
+ int vsub = fb->format->vsub;
|
|
|
|
+ int aux_x = plane_state->aux.x;
|
|
|
|
+ int aux_y = plane_state->aux.y;
|
|
|
|
+ u32 aux_offset = plane_state->aux.offset;
|
|
|
|
+ u32 alignment = intel_surf_alignment(fb, 1);
|
|
|
|
+
|
|
|
|
+ while (aux_offset >= main_offset && aux_y <= main_y) {
|
|
|
|
+ int x, y;
|
|
|
|
+
|
|
|
|
+ if (aux_x == main_x && aux_y == main_y)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ if (aux_offset == 0)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ x = aux_x / hsub;
|
|
|
|
+ y = aux_y / vsub;
|
|
|
|
+ aux_offset = intel_adjust_tile_offset(&x, &y, plane_state, 1,
|
|
|
|
+ aux_offset, aux_offset - alignment);
|
|
|
|
+ aux_x = x * hsub + aux_x % hsub;
|
|
|
|
+ aux_y = y * vsub + aux_y % vsub;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (aux_x != main_x || aux_y != main_y)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ plane_state->aux.offset = aux_offset;
|
|
|
|
+ plane_state->aux.x = aux_x;
|
|
|
|
+ plane_state->aux.y = aux_y;
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
|
static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
|
{
|
|
{
|
|
const struct drm_framebuffer *fb = plane_state->base.fb;
|
|
const struct drm_framebuffer *fb = plane_state->base.fb;
|
|
@@ -2910,7 +2992,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
|
|
|
|
|
while ((x + w) * cpp > fb->pitches[0]) {
|
|
while ((x + w) * cpp > fb->pitches[0]) {
|
|
if (offset == 0) {
|
|
if (offset == 0) {
|
|
- DRM_DEBUG_KMS("Unable to find suitable display surface offset\n");
|
|
|
|
|
|
+ DRM_DEBUG_KMS("Unable to find suitable display surface offset due to X-tiling\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2919,6 +3001,26 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * CCS AUX surface doesn't have its own x/y offsets, we must make sure
|
|
|
|
+ * they match with the main surface x/y offsets.
|
|
|
|
+ */
|
|
|
|
+ if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
|
|
|
|
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) {
|
|
|
|
+ while (!skl_check_main_ccs_coordinates(plane_state, x, y, offset)) {
|
|
|
|
+ if (offset == 0)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
|
|
|
|
+ offset, offset - alignment);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (x != plane_state->aux.x || y != plane_state->aux.y) {
|
|
|
|
+ DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
plane_state->main.offset = offset;
|
|
plane_state->main.offset = offset;
|
|
plane_state->main.x = x;
|
|
plane_state->main.x = x;
|
|
plane_state->main.y = y;
|
|
plane_state->main.y = y;
|
|
@@ -2955,6 +3057,49 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
|
|
|
|
+{
|
|
|
|
+ struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
|
|
|
|
+ struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc);
|
|
|
|
+ const struct drm_framebuffer *fb = plane_state->base.fb;
|
|
|
|
+ int src_x = plane_state->base.src.x1 >> 16;
|
|
|
|
+ int src_y = plane_state->base.src.y1 >> 16;
|
|
|
|
+ int hsub = fb->format->hsub;
|
|
|
|
+ int vsub = fb->format->vsub;
|
|
|
|
+ int x = src_x / hsub;
|
|
|
|
+ int y = src_y / vsub;
|
|
|
|
+ u32 offset;
|
|
|
|
+
|
|
|
|
+ switch (plane->id) {
|
|
|
|
+ case PLANE_PRIMARY:
|
|
|
|
+ case PLANE_SPRITE0:
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ DRM_DEBUG_KMS("RC support only on plane 1 and 2\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (crtc->pipe == PIPE_C) {
|
|
|
|
+ DRM_DEBUG_KMS("No RC support on pipe C\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) {
|
|
|
|
+ DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n",
|
|
|
|
+ plane_state->base.rotation);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ intel_add_fb_offsets(&x, &y, plane_state, 1);
|
|
|
|
+ offset = intel_compute_tile_offset(&x, &y, plane_state, 1);
|
|
|
|
+
|
|
|
|
+ plane_state->aux.offset = offset;
|
|
|
|
+ plane_state->aux.x = x * hsub + src_x % hsub;
|
|
|
|
+ plane_state->aux.y = y * vsub + src_y % vsub;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
int skl_check_plane_surface(struct intel_plane_state *plane_state)
|
|
int skl_check_plane_surface(struct intel_plane_state *plane_state)
|
|
{
|
|
{
|
|
const struct drm_framebuffer *fb = plane_state->base.fb;
|
|
const struct drm_framebuffer *fb = plane_state->base.fb;
|
|
@@ -2978,6 +3123,11 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
|
|
ret = skl_check_nv12_aux_surface(plane_state);
|
|
ret = skl_check_nv12_aux_surface(plane_state);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
+ } else if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
|
|
|
|
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) {
|
|
|
|
+ ret = skl_check_ccs_aux_surface(plane_state);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
} else {
|
|
} else {
|
|
plane_state->aux.offset = ~0xfff;
|
|
plane_state->aux.offset = ~0xfff;
|
|
plane_state->aux.x = 0;
|
|
plane_state->aux.x = 0;
|
|
@@ -3284,8 +3434,12 @@ static u32 skl_plane_ctl_tiling(uint64_t fb_modifier)
|
|
return PLANE_CTL_TILED_X;
|
|
return PLANE_CTL_TILED_X;
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
return PLANE_CTL_TILED_Y;
|
|
return PLANE_CTL_TILED_Y;
|
|
|
|
+ case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
|
|
+ return PLANE_CTL_TILED_Y | PLANE_CTL_DECOMPRESSION_ENABLE;
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
return PLANE_CTL_TILED_YF;
|
|
return PLANE_CTL_TILED_YF;
|
|
|
|
+ case I915_FORMAT_MOD_Yf_TILED_CCS:
|
|
|
|
+ return PLANE_CTL_TILED_YF | PLANE_CTL_DECOMPRESSION_ENABLE;
|
|
default:
|
|
default:
|
|
MISSING_CASE(fb_modifier);
|
|
MISSING_CASE(fb_modifier);
|
|
}
|
|
}
|
|
@@ -3358,6 +3512,7 @@ static void skylake_update_primary_plane(struct intel_plane *plane,
|
|
u32 plane_ctl = plane_state->ctl;
|
|
u32 plane_ctl = plane_state->ctl;
|
|
unsigned int rotation = plane_state->base.rotation;
|
|
unsigned int rotation = plane_state->base.rotation;
|
|
u32 stride = skl_plane_stride(fb, 0, rotation);
|
|
u32 stride = skl_plane_stride(fb, 0, rotation);
|
|
|
|
+ u32 aux_stride = skl_plane_stride(fb, 1, rotation);
|
|
u32 surf_addr = plane_state->main.offset;
|
|
u32 surf_addr = plane_state->main.offset;
|
|
int scaler_id = plane_state->scaler_id;
|
|
int scaler_id = plane_state->scaler_id;
|
|
int src_x = plane_state->main.x;
|
|
int src_x = plane_state->main.x;
|
|
@@ -3394,6 +3549,10 @@ static void skylake_update_primary_plane(struct intel_plane *plane,
|
|
I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (src_y << 16) | src_x);
|
|
I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (src_y << 16) | src_x);
|
|
I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
|
|
I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
|
|
I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
|
|
I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
|
|
|
|
+ I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
|
|
|
|
+ (plane_state->aux.offset - surf_addr) | aux_stride);
|
|
|
|
+ I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
|
|
|
|
+ (plane_state->aux.y << 16) | plane_state->aux.x);
|
|
|
|
|
|
if (scaler_id >= 0) {
|
|
if (scaler_id >= 0) {
|
|
uint32_t ps_ctrl = 0;
|
|
uint32_t ps_ctrl = 0;
|
|
@@ -8337,10 +8496,16 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
|
fb->modifier = I915_FORMAT_MOD_X_TILED;
|
|
fb->modifier = I915_FORMAT_MOD_X_TILED;
|
|
break;
|
|
break;
|
|
case PLANE_CTL_TILED_Y:
|
|
case PLANE_CTL_TILED_Y:
|
|
- fb->modifier = I915_FORMAT_MOD_Y_TILED;
|
|
|
|
|
|
+ if (val & PLANE_CTL_DECOMPRESSION_ENABLE)
|
|
|
|
+ fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
|
|
|
|
+ else
|
|
|
|
+ fb->modifier = I915_FORMAT_MOD_Y_TILED;
|
|
break;
|
|
break;
|
|
case PLANE_CTL_TILED_YF:
|
|
case PLANE_CTL_TILED_YF:
|
|
- fb->modifier = I915_FORMAT_MOD_Yf_TILED;
|
|
|
|
|
|
+ if (val & PLANE_CTL_DECOMPRESSION_ENABLE)
|
|
|
|
+ fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
|
|
|
|
+ else
|
|
|
|
+ fb->modifier = I915_FORMAT_MOD_Yf_TILED;
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
MISSING_CASE(tiling);
|
|
MISSING_CASE(tiling);
|
|
@@ -13506,10 +13671,12 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
|
|
struct drm_mode_fb_cmd2 *mode_cmd)
|
|
struct drm_mode_fb_cmd2 *mode_cmd)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
|
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
|
|
|
+ struct drm_framebuffer *fb = &intel_fb->base;
|
|
struct drm_format_name_buf format_name;
|
|
struct drm_format_name_buf format_name;
|
|
- u32 pitch_limit, stride_alignment;
|
|
|
|
|
|
+ u32 pitch_limit;
|
|
unsigned int tiling, stride;
|
|
unsigned int tiling, stride;
|
|
int ret = -EINVAL;
|
|
int ret = -EINVAL;
|
|
|
|
+ int i;
|
|
|
|
|
|
i915_gem_object_lock(obj);
|
|
i915_gem_object_lock(obj);
|
|
obj->framebuffer_references++;
|
|
obj->framebuffer_references++;
|
|
@@ -13538,6 +13705,19 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
|
|
|
|
|
|
/* Passed in modifier sanity checking. */
|
|
/* Passed in modifier sanity checking. */
|
|
switch (mode_cmd->modifier[0]) {
|
|
switch (mode_cmd->modifier[0]) {
|
|
|
|
+ case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
|
|
+ case I915_FORMAT_MOD_Yf_TILED_CCS:
|
|
|
|
+ switch (mode_cmd->pixel_format) {
|
|
|
|
+ case DRM_FORMAT_XBGR8888:
|
|
|
|
+ case DRM_FORMAT_ABGR8888:
|
|
|
|
+ case DRM_FORMAT_XRGB8888:
|
|
|
|
+ case DRM_FORMAT_ARGB8888:
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ DRM_DEBUG_KMS("RC supported only with RGB8888 formats\n");
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+ /* fall through */
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
if (INTEL_GEN(dev_priv) < 9) {
|
|
if (INTEL_GEN(dev_priv) < 9) {
|
|
@@ -13642,25 +13822,46 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
|
|
if (mode_cmd->offsets[0] != 0)
|
|
if (mode_cmd->offsets[0] != 0)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
- drm_helper_mode_fill_fb_struct(&dev_priv->drm,
|
|
|
|
- &intel_fb->base, mode_cmd);
|
|
|
|
|
|
+ drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd);
|
|
|
|
|
|
- stride_alignment = intel_fb_stride_alignment(&intel_fb->base, 0);
|
|
|
|
- if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
|
|
|
|
- DRM_DEBUG_KMS("pitch (%d) must be at least %u byte aligned\n",
|
|
|
|
- mode_cmd->pitches[0], stride_alignment);
|
|
|
|
- goto err;
|
|
|
|
|
|
+ for (i = 0; i < fb->format->num_planes; i++) {
|
|
|
|
+ u32 stride_alignment;
|
|
|
|
+
|
|
|
|
+ if (mode_cmd->handles[i] != mode_cmd->handles[0]) {
|
|
|
|
+ DRM_DEBUG_KMS("bad plane %d handle\n", i);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ stride_alignment = intel_fb_stride_alignment(fb, i);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Display WA #0531: skl,bxt,kbl,glk
|
|
|
|
+ *
|
|
|
|
+ * Render decompression and plane width > 3840
|
|
|
|
+ * combined with horizontal panning requires the
|
|
|
|
+ * plane stride to be a multiple of 4. We'll just
|
|
|
|
+ * require the entire fb to accommodate that to avoid
|
|
|
|
+ * potential runtime errors at plane configuration time.
|
|
|
|
+ */
|
|
|
|
+ if (IS_GEN9(dev_priv) && i == 0 && fb->width > 3840 &&
|
|
|
|
+ (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
|
|
|
|
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS))
|
|
|
|
+ stride_alignment *= 4;
|
|
|
|
+
|
|
|
|
+ if (fb->pitches[i] & (stride_alignment - 1)) {
|
|
|
|
+ DRM_DEBUG_KMS("plane %d pitch (%d) must be at least %u byte aligned\n",
|
|
|
|
+ i, fb->pitches[i], stride_alignment);
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
intel_fb->obj = obj;
|
|
intel_fb->obj = obj;
|
|
|
|
|
|
- ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
|
|
|
|
|
|
+ ret = intel_fill_fb_info(dev_priv, fb);
|
|
if (ret)
|
|
if (ret)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
- ret = drm_framebuffer_init(obj->base.dev,
|
|
|
|
- &intel_fb->base,
|
|
|
|
- &intel_fb_funcs);
|
|
|
|
|
|
+ ret = drm_framebuffer_init(&dev_priv->drm, fb, &intel_fb_funcs);
|
|
if (ret) {
|
|
if (ret) {
|
|
DRM_ERROR("framebuffer init failed %d\n", ret);
|
|
DRM_ERROR("framebuffer init failed %d\n", ret);
|
|
goto err;
|
|
goto err;
|