diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/skl_universal_plane.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/skl_universal_plane.c | 273 |
1 files changed, 213 insertions, 60 deletions
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 860574d04f88..ba5a628b4757 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -21,6 +21,7 @@ #include "intel_psr_regs.h" #include "skl_scaler.h" #include "skl_universal_plane.h" +#include "skl_universal_plane_regs.h" #include "skl_watermark.h" #include "pxp/intel_pxp.h" @@ -237,9 +238,9 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915) { if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915)) - return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3); + return BIT(PLANE_4) | BIT(PLANE_5); else - return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5); + return BIT(PLANE_6) | BIT(PLANE_7); } bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, @@ -251,7 +252,7 @@ bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, u8 icl_hdr_plane_mask(void) { - return BIT(PLANE_PRIMARY) | BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1); + return BIT(PLANE_1) | BIT(PLANE_2) | BIT(PLANE_3); } bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id) @@ -461,41 +462,117 @@ static int icl_plane_max_height(const struct drm_framebuffer *fb, } static unsigned int +plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation, + unsigned int max_pixels, + unsigned int max_bytes) +{ + const struct drm_format_info *info = drm_format_info(pixel_format); + int cpp = info->cpp[0]; + + if (drm_rotation_90_or_270(rotation)) + return min(max_pixels, max_bytes / cpp); + else + return min(max_pixels * cpp, max_bytes); +} + +static unsigned int +adl_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + unsigned int max_pixels = 65536; /* PLANE_OFFSET limit */ + unsigned int max_bytes = 128 * 1024; + + return plane_max_stride(plane, pixel_format, + modifier, rotation, + max_pixels, max_bytes); +} + +static unsigned int skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation) { + unsigned int max_pixels = 8192; /* PLANE_OFFSET limit */ + unsigned int max_bytes = 32 * 1024; + + return plane_max_stride(plane, pixel_format, + modifier, rotation, + max_pixels, max_bytes); +} + +static u32 tgl_plane_min_alignment(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane) +{ struct drm_i915_private *i915 = to_i915(plane->base.dev); - const struct drm_format_info *info = drm_format_info(pixel_format); - int cpp = info->cpp[0]; - int max_horizontal_pixels = 8192; - int max_stride_bytes; + /* PLANE_SURF GGTT -> DPT alignment */ + int mult = intel_fb_uses_dpt(fb) ? 512 : 1; + + /* AUX_DIST needs only 4K alignment */ + if (intel_fb_is_ccs_aux_plane(fb, color_plane)) + return mult * 4 * 1024; - if (DISPLAY_VER(i915) >= 13) { + 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: /* - * The stride in bytes must not exceed of the size - * of 128K bytes. For pixel formats of 64bpp will allow - * for a 16K pixel surface. + * FIXME ADL sees GGTT/DMAR faults with async + * flips unless we align to 16k at least. + * Figure out what's going on here... */ - max_stride_bytes = 131072; - if (cpp == 8) - max_horizontal_pixels = 16384; - else - max_horizontal_pixels = 65536; - } else { + if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915)) + return mult * 16 * 1024; + return mult * 4 * 1024; + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: /* - * "The stride in bytes must not exceed the - * of the size of 8K pixels and 32K bytes." + * Align to at least 4x1 main surface + * tiles (16K) to match 64B of AUX. */ - max_stride_bytes = 32768; + return max(mult * 4 * 1024, 16 * 1024); + default: + MISSING_CASE(fb->modifier); + return 0; } - - if (drm_rotation_90_or_270(rotation)) - return min(max_horizontal_pixels, max_stride_bytes / cpp); - else - return min(max_horizontal_pixels * cpp, max_stride_bytes); } +static u32 skl_plane_min_alignment(struct intel_plane *plane, + const struct 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; + + 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 @@ -616,6 +693,66 @@ static u32 skl_plane_stride(const struct intel_plane_state *plane_state, return stride / skl_plane_stride_mult(fb, color_plane, rotation); } +static u32 skl_plane_ddb_reg_val(const struct skl_ddb_entry *entry) +{ + if (!entry->end) + return 0; + + return PLANE_BUF_END(entry->end - 1) | + PLANE_BUF_START(entry->start); +} + +static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level) +{ + u32 val = 0; + + if (level->enable) + val |= PLANE_WM_EN; + if (level->ignore_lines) + val |= PLANE_WM_IGNORE_LINES; + val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); + val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); + + return val; +} + +static void skl_write_plane_wm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + const struct skl_ddb_entry *ddb_y = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; + int level; + + for (level = 0; level < i915->display.wm.num_levels; level++) + intel_de_write_fw(i915, PLANE_WM(pipe, plane_id, level), + skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level))); + + intel_de_write_fw(i915, PLANE_WM_TRANS(pipe, plane_id), + skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id))); + + if (HAS_HW_SAGV_WM(i915)) { + const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + + intel_de_write_fw(i915, PLANE_WM_SAGV(pipe, plane_id), + skl_plane_wm_reg_val(&wm->sagv.wm0)); + intel_de_write_fw(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id), + skl_plane_wm_reg_val(&wm->sagv.trans_wm)); + } + + intel_de_write_fw(i915, PLANE_BUF_CFG(pipe, plane_id), + skl_plane_ddb_reg_val(ddb)); + + if (DISPLAY_VER(i915) < 11) + intel_de_write_fw(i915, PLANE_NV12_BUF_CFG(pipe, plane_id), + skl_plane_ddb_reg_val(ddb_y)); +} + static void skl_plane_disable_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) @@ -639,7 +776,7 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_plane *plane, if (!crtc_state->enable_psr2_sel_fetch) return; - intel_de_write_fw(i915, PLANE_SEL_FETCH_CTL(pipe, plane->id), 0); + intel_de_write_fw(i915, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); } static void @@ -1174,6 +1311,11 @@ skl_plane_update_arm(struct intel_plane *plane, plane_ctl = plane_state->ctl | skl_plane_ctl_crtc(crtc_state); + /* see intel_plane_atomic_calc_changes() */ + if (plane->need_async_flip_toggle_wa && + crtc_state->async_flip_planes & BIT(plane->id)) + plane_ctl |= PLANE_CTL_ASYNC_FLIP; + if (DISPLAY_VER(dev_priv) >= 10) plane_color_ctl = plane_state->color_ctl | glk_plane_color_ctl_crtc(crtc_state); @@ -1231,9 +1373,13 @@ static void icl_plane_update_sel_fetch_noarm(struct intel_plane *plane, clip = &plane_state->psr2_sel_fetch_area; - val = (clip->y1 + plane_state->uapi.dst.y1) << 16; + 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_fw(i915, PLANE_SEL_FETCH_POS(pipe, plane->id), val); + intel_de_write_fw(i915, SEL_FETCH_PLANE_POS(pipe, plane->id), val); x = plane_state->view.color_plane[color_plane].x; @@ -1248,13 +1394,13 @@ static void icl_plane_update_sel_fetch_noarm(struct intel_plane *plane, val = y << 16 | x; - intel_de_write_fw(i915, PLANE_SEL_FETCH_OFFSET(pipe, plane->id), + intel_de_write_fw(i915, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val); /* Sizes are 0 based */ val = (drm_rect_height(clip) - 1) << 16; val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1; - intel_de_write_fw(i915, PLANE_SEL_FETCH_SIZE(pipe, plane->id), val); + intel_de_write_fw(i915, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val); } static void @@ -1343,8 +1489,8 @@ static void icl_plane_update_sel_fetch_arm(struct intel_plane *plane, return; if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) - intel_de_write_fw(i915, PLANE_SEL_FETCH_CTL(pipe, plane->id), - PLANE_SEL_FETCH_CTL_ENABLE); + intel_de_write_fw(i915, SEL_FETCH_PLANE_CTL(pipe, plane->id), + SEL_FETCH_PLANE_CTL_ENABLE); else icl_plane_disable_sel_fetch_arm(plane, crtc_state); } @@ -1605,11 +1751,12 @@ skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, int main_x, int main_y, u32 main_offset, int ccs_plane) { + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; int aux_x = plane_state->view.color_plane[ccs_plane].x; int aux_y = plane_state->view.color_plane[ccs_plane].y; u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; - u32 alignment = intel_surf_alignment(fb, ccs_plane); + unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane); int hsub; int vsub; @@ -1629,8 +1776,7 @@ skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, plane_state, ccs_plane, aux_offset, - aux_offset - - alignment); + aux_offset - alignment); aux_x = x * hsub + aux_x % hsub; aux_y = y * vsub + aux_y % vsub; } @@ -1652,10 +1798,10 @@ int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - const int aux_plane = skl_main_to_aux_plane(fb, 0); - const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; - const u32 alignment = intel_surf_alignment(fb, 0); - const int w = drm_rect_width(&plane_state->uapi.src) >> 16; + int aux_plane = skl_main_to_aux_plane(fb, 0); + u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; + unsigned int 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); @@ -1702,16 +1848,16 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - const unsigned int rotation = plane_state->hw.rotation; + unsigned int rotation = plane_state->hw.rotation; int x = plane_state->uapi.src.x1 >> 16; int y = plane_state->uapi.src.y1 >> 16; - const int w = drm_rect_width(&plane_state->uapi.src) >> 16; - const int h = drm_rect_height(&plane_state->uapi.src) >> 16; - const int min_width = intel_plane_min_width(plane, fb, 0, rotation); - const int max_width = intel_plane_max_width(plane, fb, 0, rotation); - const int max_height = intel_plane_max_height(plane, fb, 0, rotation); - const int aux_plane = skl_main_to_aux_plane(fb, 0); - const u32 alignment = intel_surf_alignment(fb, 0); + 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); + unsigned int alignment = plane->min_alignment(plane, fb, 0); + int aux_plane = skl_main_to_aux_plane(fb, 0); u32 offset; int ret; @@ -1799,7 +1945,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) if (ccs_plane) { u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; - u32 alignment = intel_surf_alignment(fb, uv_plane); + unsigned int alignment = plane->min_alignment(plane, fb, uv_plane); if (offset > aux_offset) offset = intel_plane_adjust_aligned_offset(&x, &y, @@ -2029,7 +2175,7 @@ static bool skl_plane_has_fbc(struct drm_i915_private *i915, if (DISPLAY_VER(i915) >= 20) return icl_is_hdr_plane(i915, plane_id); else - return plane_id == PLANE_PRIMARY; + return plane_id == PLANE_1; } static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv, @@ -2053,7 +2199,7 @@ static bool skl_plane_has_planar(struct drm_i915_private *dev_priv, if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C) return false; - if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0) + if (plane_id != PLANE_1 && plane_id != PLANE_2) return false; return true; @@ -2261,8 +2407,7 @@ static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, return pipe != PIPE_C; return pipe != PIPE_C && - (plane_id == PLANE_PRIMARY || - plane_id == PLANE_SPRITE0); + (plane_id == PLANE_1 || plane_id == PLANE_2); } static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, @@ -2280,7 +2425,7 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) return false; - return plane_id < PLANE_SPRITE4; + return plane_id < PLANE_6; } static u8 skl_get_plane_caps(struct drm_i915_private *i915, @@ -2352,7 +2497,16 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->min_cdclk = skl_plane_min_cdclk; } - plane->max_stride = skl_plane_max_stride; + if (DISPLAY_VER(dev_priv) >= 13) + plane->max_stride = adl_plane_max_stride; + else + plane->max_stride = skl_plane_max_stride; + + if (DISPLAY_VER(dev_priv) >= 12) + plane->min_alignment = tgl_plane_min_alignment; + else + plane->min_alignment = skl_plane_min_alignment; + if (DISPLAY_VER(dev_priv) >= 11) { plane->update_noarm = icl_plane_update_noarm; plane->update_arm = icl_plane_update_arm; @@ -2365,9 +2519,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->get_hw_state = skl_plane_get_hw_state; plane->check_plane = skl_plane_check; - if (plane_id == PLANE_PRIMARY) { - plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv, - 9, 10); + if (plane_id == PLANE_1) { + plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(dev_priv, 9, 10); plane->async_flip = skl_plane_async_flip; plane->enable_flip_done = skl_plane_enable_flip_done; plane->disable_flip_done = skl_plane_disable_flip_done; @@ -2388,7 +2541,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, else plane_funcs = &skl_plane_funcs; - if (plane_id == PLANE_PRIMARY) + if (plane_id == PLANE_1) plane_type = DRM_PLANE_TYPE_PRIMARY; else plane_type = DRM_PLANE_TYPE_OVERLAY; @@ -2482,9 +2635,9 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, drm_WARN_ON(dev, pipe != crtc->pipe); - if (crtc_state->bigjoiner_pipes) { + if (crtc_state->joiner_pipes) { drm_dbg_kms(&dev_priv->drm, - "Unsupported bigjoiner configuration for initial FB\n"); + "Unsupported joiner configuration for initial FB\n"); return; } |