staticint skl_plane_max_width(conststruct drm_framebuffer *fb, int color_plane, unsignedint rotation)
{ int cpp = fb->format->cpp[color_plane];
switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: /* * Validated limit is 4k, but has 5k should * work apart from the following features: * - Ytile (already limited to 4k) * - FP16 (already limited to 4k) * - render compression (already limited to 4k) * - KVMR sprite and cursor (don't care) * - horizontal panning (TODO verify this) * - pipe and plane scaling (TODO verify this)
*/ if (cpp == 8) return 4096; else return 5120; 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_Yf_TILED: if (cpp == 8) return 2048; else return 4096; default:
MISSING_CASE(fb->modifier); return 2048;
}
}
staticint glk_plane_max_width(conststruct drm_framebuffer *fb, int color_plane, unsignedint rotation)
{ int cpp = fb->format->cpp[color_plane];
switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: if (cpp == 8) return 4096; else return 5120; 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_Yf_TILED: if (cpp == 8) return 2048; else return 5120; default:
MISSING_CASE(fb->modifier); return 2048;
}
}
staticint icl_plane_min_width(conststruct drm_framebuffer *fb, int color_plane, unsignedint rotation)
{ /* Wa_14011264657, Wa_14011050563: gen11+ */ switch (fb->format->format) { case DRM_FORMAT_C8: return 18; case DRM_FORMAT_RGB565: return 10; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_XVYU2101010: case DRM_FORMAT_Y212: case DRM_FORMAT_Y216: return 6; case DRM_FORMAT_NV12: return 20; case DRM_FORMAT_P010: case DRM_FORMAT_P012: case DRM_FORMAT_P016: return 12; case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ARGB16161616F: case DRM_FORMAT_ABGR16161616F: case DRM_FORMAT_XVYU12_16161616: case DRM_FORMAT_XVYU16161616: return 4; default: return 1;
}
}
staticint xe3_plane_max_width(conststruct drm_framebuffer *fb, int color_plane, unsignedint rotation)
{ if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) return 4096; else return 6144;
}
staticint icl_hdr_plane_max_width(conststruct drm_framebuffer *fb, int color_plane, unsignedint rotation)
{ if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) return 4096; else return 5120;
}
staticbool tgl_plane_can_async_flip(u64 modifier)
{ switch (modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_4_TILED: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: case I915_FORMAT_MOD_4_TILED_BMG_CCS: case I915_FORMAT_MOD_4_TILED_LNL_CCS: returntrue; case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: returnfalse; default: returnfalse;
}
}
staticbool icl_plane_can_async_flip(u64 modifier)
{ switch (modifier) { case DRM_FORMAT_MOD_LINEAR: /* * FIXME: Async on Linear buffer is supported on ICL * but with additional alignment and fbc restrictions * need to be taken care of.
*/ returnfalse; case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: returntrue; default: returnfalse;
}
}
staticbool skl_plane_can_async_flip(u64 modifier)
{ switch (modifier) { case DRM_FORMAT_MOD_LINEAR: returnfalse; case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: returntrue; case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: /* * Display WA #0731: skl * WaDisableRCWithAsyncFlip: skl * "When render decompression is enabled, hardware * internally converts the Async flips to Sync flips." * * Display WA #1159: glk * "Async flip with render compression may result in * intermittent underrun corruption."
*/ returnfalse; default: returnfalse;
}
}
/* AUX_DIST needs only 4K alignment */ if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return mult * 4 * 1024;
/* * FIXME ADL sees GGTT/DMAR faults with async * flips unless we align to 16k at least. * Figure out what's going on here...
*/ if (display->platform.alderlake_p &&
intel_plane_can_async_flip(plane, fb->format->format, fb->modifier)) return mult * 16 * 1024;
switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_4_TILED: return mult * 4 * 1024; case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_BMG_CCS: case I915_FORMAT_MOD_4_TILED_LNL_CCS: /* * Align to at least 4x1 main surface * tiles (16K) to match 64B of AUX.
*/ return max(mult * 4 * 1024, 16 * 1024); default:
MISSING_CASE(fb->modifier); return 0;
}
}
static u32 skl_plane_min_alignment(struct intel_plane *plane, conststruct drm_framebuffer *fb, int color_plane)
{ /* * AUX_DIST needs only 4K alignment, * as does ICL UV PLANE_SURF.
*/ if (color_plane != 0) return 4 * 1024;
/* * VT-d needs at least 256k alignment, * but that's already covered below.
*/ switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: return 256 * 1024; case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: return 1 * 1024 * 1024; default:
MISSING_CASE(fb->modifier); return 0;
}
}
/* Preoffset values for YUV to RGB Conversion */ #define PREOFF_YUV_TO_RGB_HI 0x1800 #define PREOFF_YUV_TO_RGB_ME 0x0000 #define PREOFF_YUV_TO_RGB_LO 0x1800
/* * Programs the input color space conversion stage for ICL HDR planes. * Note that it is assumed that this stage always happens after YUV * range correction. Thus, the input to this stage is assumed to be * in full-range YCbCr.
*/ staticvoid
icl_program_input_csc(struct intel_dsb *dsb, struct intel_plane *plane, conststruct intel_plane_state *plane_state)
{ struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id;
staticconst u16 input_csc_matrix[][9] = { /* * BT.601 full range YCbCr -> full range RGB * The matrix required is : * [1.000, 0.000, 1.371, * 1.000, -0.336, -0.698, * 1.000, 1.732, 0.0000]
*/
[DRM_COLOR_YCBCR_BT601] = {
0x7AF8, 0x7800, 0x0,
0x8B28, 0x7800, 0x9AC0,
0x0, 0x7800, 0x7DD8,
}, /* * BT.709 full range YCbCr -> full range RGB * The matrix required is : * [1.000, 0.000, 1.574, * 1.000, -0.187, -0.468, * 1.000, 1.855, 0.0000]
*/
[DRM_COLOR_YCBCR_BT709] = {
0x7C98, 0x7800, 0x0,
0x9EF8, 0x7800, 0xAC00,
0x0, 0x7800, 0x7ED8,
}, /* * BT.2020 full range YCbCr -> full range RGB * The matrix required is : * [1.000, 0.000, 1.474, * 1.000, -0.1645, -0.5713, * 1.000, 1.8814, 0.0000]
*/
[DRM_COLOR_YCBCR_BT2020] = {
0x7BC8, 0x7800, 0x0,
0x8928, 0x7800, 0xAA88,
0x0, 0x7800, 0x7F10,
},
}; const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
staticunsignedint skl_plane_stride_mult(conststruct drm_framebuffer *fb, int color_plane, unsignedint rotation)
{ /* * The stride is either expressed as a multiple of 64 bytes chunks for * linear buffers or in number of tiles for tiled buffers.
*/ if (is_surface_linear(fb, color_plane)) return 64; elseif (drm_rotation_90_or_270(rotation)) return intel_tile_height(fb, color_plane); else return intel_tile_width_bytes(fb, color_plane);
}
if (*min_ddb)
val |= PLANE_MIN_DBUF_BLOCKS(*min_ddb);
if (*interim_ddb)
val |= PLANE_INTERIM_DBUF_BLOCKS(*interim_ddb);
val |= val ? PLANE_AUTO_MIN_DBUF_EN : 0;
return val;
}
static u32 skl_plane_wm_reg_val(conststruct skl_wm_level *level)
{
u32 val = 0;
if (level->enable)
val |= PLANE_WM_EN; if (level->ignore_lines)
val |= PLANE_WM_IGNORE_LINES; if (level->auto_min_alloc_wm_enable)
val |= PLANE_WM_AUTO_MIN_ALLOC_EN;
val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks);
val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines);
static u32 skl_plane_ctl_format(u32 pixel_format)
{ switch (pixel_format) { case DRM_FORMAT_C8: return PLANE_CTL_FORMAT_INDEXED; case DRM_FORMAT_RGB565: return PLANE_CTL_FORMAT_RGB_565; case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: return PLANE_CTL_FORMAT_XRGB_8888; case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: return PLANE_CTL_FORMAT_XRGB_2101010; case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ABGR16161616F: return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX; case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_ARGB16161616F: return PLANE_CTL_FORMAT_XRGB_16161616F; case DRM_FORMAT_XYUV8888: return PLANE_CTL_FORMAT_XYUV; case DRM_FORMAT_YUYV: return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV; case DRM_FORMAT_YVYU: return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU; case DRM_FORMAT_UYVY: return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY; case DRM_FORMAT_VYUY: return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY; case DRM_FORMAT_NV12: return PLANE_CTL_FORMAT_NV12; case DRM_FORMAT_P010: return PLANE_CTL_FORMAT_P010; case DRM_FORMAT_P012: return PLANE_CTL_FORMAT_P012; case DRM_FORMAT_P016: return PLANE_CTL_FORMAT_P016; case DRM_FORMAT_Y210: return PLANE_CTL_FORMAT_Y210; case DRM_FORMAT_Y212: return PLANE_CTL_FORMAT_Y212; case DRM_FORMAT_Y216: return PLANE_CTL_FORMAT_Y216; case DRM_FORMAT_XVYU2101010: return PLANE_CTL_FORMAT_Y410; case DRM_FORMAT_XVYU12_16161616: return PLANE_CTL_FORMAT_Y412; case DRM_FORMAT_XVYU16161616: return PLANE_CTL_FORMAT_Y416; default:
MISSING_CASE(pixel_format);
}
return 0;
}
static u32 skl_plane_ctl_alpha(conststruct intel_plane_state *plane_state)
{ if (!plane_state->hw.fb->format->has_alpha) return PLANE_CTL_ALPHA_DISABLE;
switch (plane_state->hw.pixel_blend_mode) { case DRM_MODE_BLEND_PIXEL_NONE: return PLANE_CTL_ALPHA_DISABLE; case DRM_MODE_BLEND_PREMULTI: return PLANE_CTL_ALPHA_SW_PREMULTIPLY; case DRM_MODE_BLEND_COVERAGE: return PLANE_CTL_ALPHA_HW_PREMULTIPLY; default:
MISSING_CASE(plane_state->hw.pixel_blend_mode); return PLANE_CTL_ALPHA_DISABLE;
}
}
static u32 glk_plane_color_ctl_alpha(conststruct intel_plane_state *plane_state)
{ if (!plane_state->hw.fb->format->has_alpha) return PLANE_COLOR_ALPHA_DISABLE;
switch (plane_state->hw.pixel_blend_mode) { case DRM_MODE_BLEND_PIXEL_NONE: return PLANE_COLOR_ALPHA_DISABLE; case DRM_MODE_BLEND_PREMULTI: return PLANE_COLOR_ALPHA_SW_PREMULTIPLY; case DRM_MODE_BLEND_COVERAGE: return PLANE_COLOR_ALPHA_HW_PREMULTIPLY; default:
MISSING_CASE(plane_state->hw.pixel_blend_mode); return PLANE_COLOR_ALPHA_DISABLE;
}
}
static u32 skl_plane_ctl_tiling(u64 fb_modifier)
{ switch (fb_modifier) { case DRM_FORMAT_MOD_LINEAR: break; case I915_FORMAT_MOD_X_TILED: return PLANE_CTL_TILED_X; case I915_FORMAT_MOD_Y_TILED: return PLANE_CTL_TILED_Y; case I915_FORMAT_MOD_4_TILED: return PLANE_CTL_TILED_4; case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: return PLANE_CTL_TILED_4 |
PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
PLANE_CTL_CLEAR_COLOR_DISABLE; case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: return PLANE_CTL_TILED_4 |
PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
PLANE_CTL_CLEAR_COLOR_DISABLE; case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: return PLANE_CTL_TILED_4 |
PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
PLANE_CTL_CLEAR_COLOR_DISABLE; case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE; case I915_FORMAT_MOD_4_TILED_BMG_CCS: case I915_FORMAT_MOD_4_TILED_LNL_CCS: return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: return PLANE_CTL_TILED_Y |
PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
PLANE_CTL_CLEAR_COLOR_DISABLE; case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE; case I915_FORMAT_MOD_Yf_TILED: return PLANE_CTL_TILED_YF; case I915_FORMAT_MOD_Yf_TILED_CCS: return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; default:
MISSING_CASE(fb_modifier);
}
return 0;
}
static u32 skl_plane_ctl_rotate(unsignedint rotate)
{ switch (rotate) { case DRM_MODE_ROTATE_0: break; /* * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr * while i915 HW rotation is clockwise, that's why this swapping.
*/ case DRM_MODE_ROTATE_90: return PLANE_CTL_ROTATE_270; case DRM_MODE_ROTATE_180: return PLANE_CTL_ROTATE_180; case DRM_MODE_ROTATE_270: return PLANE_CTL_ROTATE_90; default:
MISSING_CASE(rotate);
}
return 0;
}
static u32 icl_plane_ctl_flip(unsignedint reflect)
{ switch (reflect) { case 0: break; case DRM_MODE_REFLECT_X: return PLANE_CTL_FLIP_HORIZONTAL; case DRM_MODE_REFLECT_Y: default:
MISSING_CASE(reflect);
}
if (DISPLAY_VER(display) >= 10)
intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
plane_color_ctl);
/* * Enable the scaler before the plane so that we don't * get a catastrophic underrun even if the two operations * end up happening in two different frames. * * TODO: split into noarm+arm pair
*/ if (plane_state->scaler_id >= 0)
skl_program_plane_scaler(dsb, plane, crtc_state, plane_state);
/* * The control register self-arms if the plane was previously * disabled. Try to make the plane enable atomic by writing * the control register just before the surface register.
*/
intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
plane_ctl);
intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
skl_plane_surf(plane_state, 0));
}
if (crtc_state->enable_psr2_su_region_et)
y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1); else
y = (clip->y1 + plane_state->uapi.dst.y1);
val = y << 16;
val |= plane_state->uapi.dst.x1;
intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_POS(pipe, plane->id), val);
x = plane_state->view.color_plane[color_plane].x;
/* * From Bspec: UV surface Start Y Position = half of Y plane Y * start position.
*/ if (!color_plane)
y = plane_state->view.color_plane[color_plane].y + clip->y1; else
y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2;
if (fb->format->is_yuv && icl_is_hdr_plane(display, plane_id))
icl_program_input_csc(dsb, plane, plane_state);
skl_write_plane_wm(dsb, plane, crtc_state);
/* * FIXME: pxp session invalidation can hit any time even at time of commit * or after the commit, display content will be garbage.
*/ if (plane_state->force_black)
icl_plane_csc_load_black(dsb, plane, crtc_state);
/* * Enable the scaler before the plane so that we don't * get a catastrophic underrun even if the two operations * end up happening in two different frames. * * TODO: split into noarm+arm pair
*/ if (plane_state->scaler_id >= 0)
skl_program_plane_scaler(dsb, plane, crtc_state, plane_state);
/* * The control register self-arms if the plane was previously * disabled. Try to make the plane enable atomic by writing * the control register just before the surface register.
*/
intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
plane_ctl);
intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
skl_plane_surf(plane_state, color_plane));
}
if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
intel_fb_is_ccs_modifier(fb->modifier)) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] RC support only with 0/180 degree rotation (%x)\n",
plane->base.base.id, plane->base.name, rotation); return -EINVAL;
}
if (rotation & DRM_MODE_REFLECT_X &&
fb->modifier == DRM_FORMAT_MOD_LINEAR) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] horizontal flip is not supported with linear surface formats\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
/* * Display20 onward tile4 hflip is not supported
*/ if (rotation & DRM_MODE_REFLECT_X &&
intel_fb_is_tile4_modifier(fb->modifier) &&
DISPLAY_VER(display) >= 20) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] horizontal flip is not supported with tile4 surface formats\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
if (drm_rotation_90_or_270(rotation)) { if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] Y/Yf tiling required for 90/270!\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
/* * 90/270 is not allowed with RGB64 16:16:16:16 and * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
*/ switch (fb->format->format) { case DRM_FORMAT_RGB565: if (DISPLAY_VER(display) >= 11) break;
fallthrough; case DRM_FORMAT_C8: case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ARGB16161616F: case DRM_FORMAT_ABGR16161616F: case DRM_FORMAT_Y210: case DRM_FORMAT_Y212: case DRM_FORMAT_Y216: case DRM_FORMAT_XVYU12_16161616: case DRM_FORMAT_XVYU16161616:
drm_dbg_kms(display->drm, "[PLANE:%d:%s] unsupported pixel format %p4cc for 90/270!\n",
plane->base.base.id, plane->base.name, &fb->format->format); return -EINVAL; default: break;
}
}
/* Y-tiling is not supported in IF-ID Interlace mode */ if (crtc_state->hw.enable &&
crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
fb->modifier != DRM_FORMAT_MOD_LINEAR &&
fb->modifier != I915_FORMAT_MOD_X_TILED) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] Y/Yf tiling not supported in IF-ID mode\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
/* Wa_1606054188:tgl,adl-s */ if ((display->platform.alderlake_s || display->platform.tigerlake) &&
plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
intel_format_is_p01x(fb->format->format)) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] source color keying not supported with P01x formats\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
return 0;
}
staticint skl_plane_check_dst_coordinates(conststruct intel_crtc_state *crtc_state, conststruct intel_plane_state *plane_state)
{ struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); int crtc_x = plane_state->uapi.dst.x1; int crtc_w = drm_rect_width(&plane_state->uapi.dst); int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
/* * Display WA #1175: glk * Planes other than the cursor may cause FIFO underflow and display * corruption if starting less than 4 pixels from the right edge of * the screen. * Besides the above WA fix the similar problem, where planes other * than the cursor ending less than 4 pixels from the left edge of the * screen may cause FIFO underflow and display corruption.
*/ if (DISPLAY_VER(display) == 10 &&
(crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] requested plane X %s position %d invalid (valid range %d-%d)\n",
plane->base.base.id, plane->base.name,
crtc_x + crtc_w < 4 ? "end" : "start",
crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
4, pipe_src_w - 4); return -ERANGE;
}
/* Display WA #1106 */ if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
src_w & 3 &&
(rotation == DRM_MODE_ROTATE_270 ||
rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] src width must be multiple of 4 for rotated planar YUV\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
return 0;
}
staticint skl_plane_max_scale(struct intel_display *display, conststruct drm_framebuffer *fb)
{ /* * We don't yet know the final source width nor * whether we can use the HQ scaler mode. Assume * the best case. * FIXME need to properly check this later.
*/ if (DISPLAY_VER(display) >= 10 ||
!intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) return 0x30000 - 1; else return 0x20000 - 1;
}
int skl_calc_main_surface_offset(conststruct intel_plane_state *plane_state, int *x, int *y, u32 *offset)
{ struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); conststruct drm_framebuffer *fb = plane_state->hw.fb; int aux_plane = skl_main_to_aux_plane(fb, 0);
u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; unsignedint alignment = plane->min_alignment(plane, fb, 0); int w = drm_rect_width(&plane_state->uapi.src) >> 16;
intel_add_fb_offsets(x, y, plane_state, 0);
*offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0); if (drm_WARN_ON(display->drm, alignment && !is_power_of_2(alignment))) return -EINVAL;
/* * AUX surface offset is specified as the distance from the * main surface offset, and it must be non-negative. Make * sure that is what we will get.
*/ if (aux_plane && *offset > aux_offset)
*offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
*offset,
aux_offset & ~(alignment - 1));
/* * When using an X-tiled surface, the plane blows up * if the x offset + width exceed the stride. * * TODO: linear and Y-tiled seem fine, Yf untested,
*/ if (fb->modifier == I915_FORMAT_MOD_X_TILED) { int cpp = fb->format->cpp[0];
while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) { if (*offset == 0) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n",
plane->base.base.id, plane->base.name); return -EINVAL;
}
staticint skl_check_main_surface(struct intel_plane_state *plane_state)
{ struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); conststruct drm_framebuffer *fb = plane_state->hw.fb; unsignedint rotation = plane_state->hw.rotation; int x = plane_state->uapi.src.x1 >> 16; int y = plane_state->uapi.src.y1 >> 16; int w = drm_rect_width(&plane_state->uapi.src) >> 16; int h = drm_rect_height(&plane_state->uapi.src) >> 16; int min_width = intel_plane_min_width(plane, fb, 0, rotation); int max_width = intel_plane_max_width(plane, fb, 0, rotation); int max_height = intel_plane_max_height(plane, fb, 0, rotation); unsignedint alignment = plane->min_alignment(plane, fb, 0); int aux_plane = skl_main_to_aux_plane(fb, 0);
u32 offset; int ret;
if (w > max_width || w < min_width || h > max_height || h < 1) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
plane->base.base.id, plane->base.name,
w, h, min_width, max_width, max_height); return -EINVAL;
}
ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset); if (ret) return ret;
/* * CCS AUX surface doesn't have its own x/y offsets, we must make sure * they match with the main surface x/y offsets. On DG2 * there's no aux plane on fb so skip this checking.
*/ if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) { while (!skl_check_main_ccs_coordinates(plane_state, x, y,
offset, aux_plane)) { if (offset == 0) break;
/* * Put the final coordinates back so that the src * coordinate checks will see the right values.
*/
drm_rect_translate_to(&plane_state->uapi.src,
x << 16, y << 16);
return 0;
}
staticint skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
{ struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); conststruct drm_framebuffer *fb = plane_state->hw.fb; unsignedint rotation = plane_state->hw.rotation; int uv_plane = 1; int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
skl_main_to_aux_plane(fb, uv_plane) : 0; int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); int x = plane_state->uapi.src.x1 >> 17; int y = plane_state->uapi.src.y1 >> 17; int w = drm_rect_width(&plane_state->uapi.src) >> 17; int h = drm_rect_height(&plane_state->uapi.src) >> 17;
u32 offset;
/* FIXME not quite sure how/if these apply to the chroma plane */ if (w > max_width || h > max_height) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] CbCr source size %dx%d too big (limit %dx%d)\n",
plane->base.base.id, plane->base.name,
w, h, max_width, max_height); return -EINVAL;
}
ret = intel_plane_compute_gtt(plane_state); if (ret) return ret;
if (!plane_state->uapi.visible) return 0;
/* * Handle the AUX surface first since the main surface setup depends on * it.
*/ if (intel_fb_is_ccs_modifier(fb->modifier)) {
ret = skl_check_ccs_aux_surface(plane_state); if (ret) return ret;
}
if (intel_format_info_is_yuv_semiplanar(fb->format,
fb->modifier)) {
ret = skl_check_nv12_aux_surface(plane_state); if (ret) return ret;
}
ret = skl_check_main_surface(plane_state); if (ret) return ret;
switch (fb->format->format) { case DRM_FORMAT_C8: returnfalse; case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_ARGB16161616F: case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ABGR16161616F: return DISPLAY_VER(display) >= 11; default: returntrue;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.