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 | 193 |
1 files changed, 109 insertions, 84 deletions
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index e13fb781e7b2..89c8003ccfe7 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -7,15 +7,15 @@ #include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_print.h> #include "pxp/intel_pxp.h" -#include "i915_drv.h" -#include "i915_utils.h" #include "intel_bo.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_regs.h" #include "intel_display_types.h" +#include "intel_display_utils.h" #include "intel_dpt.h" #include "intel_fb.h" #include "intel_fbc.h" @@ -24,6 +24,7 @@ #include "intel_plane.h" #include "intel_psr.h" #include "intel_psr_regs.h" +#include "intel_step.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_universal_plane_regs.h" @@ -389,44 +390,19 @@ static int glk_plane_max_width(const struct drm_framebuffer *fb, } } +static int adl_plane_min_width(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + return 16 / fb->format->cpp[color_plane]; +} + static int icl_plane_min_width(const struct drm_framebuffer *fb, int color_plane, unsigned int 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; - } + return 16 / fb->format->cpp[color_plane] + 2; } static int xe3_plane_max_width(const struct drm_framebuffer *fb, @@ -463,6 +439,23 @@ static int skl_plane_max_height(const struct drm_framebuffer *fb, return 4096; } +static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) +{ + return pipe - PIPE_A + INTEL_FBC_A; +} + +static bool skl_plane_has_fbc(struct intel_display *display, + enum intel_fbc_id fbc_id, enum plane_id plane_id) +{ + if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) + return false; + + if (DISPLAY_VER(display) >= 20) + return icl_is_hdr_plane(display, plane_id); + else + return plane_id == PLANE_1; +} + static int icl_plane_max_height(const struct drm_framebuffer *fb, int color_plane, unsigned int rotation) @@ -472,12 +465,11 @@ 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, + const struct drm_format_info *info, + 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)) @@ -488,26 +480,26 @@ plane_max_stride(struct intel_plane *plane, static unsigned int adl_plane_max_stride(struct intel_plane *plane, - u32 pixel_format, u64 modifier, - unsigned int rotation) + const struct drm_format_info *info, + 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, + return plane_max_stride(plane, info, 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) + const struct drm_format_info *info, + 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, + return plane_max_stride(plane, info, modifier, rotation, max_pixels, max_bytes); } @@ -898,6 +890,25 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb, intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); } +static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb, + struct intel_plane *plane, + bool enable) +{ + struct intel_display *display = to_intel_display(plane); + enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe); + u32 val; + + /* Only HDR planes have pixel normalizer and don't matter if no FBC */ + if (!skl_plane_has_fbc(display, fbc_id, plane->id)) + return; + + val = enable ? PLANE_PIXEL_NORMALIZE_NORM_FACTOR(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0) | + PLANE_PIXEL_NORMALIZE_ENABLE : 0; + + intel_de_write_dsb(display, dsb, + PLANE_PIXEL_NORMALIZE(plane->pipe, plane->id), val); +} + static void icl_plane_disable_arm(struct intel_dsb *dsb, struct intel_plane *plane, @@ -913,6 +924,10 @@ icl_plane_disable_arm(struct intel_dsb *dsb, skl_write_plane_wm(dsb, plane, crtc_state); icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); + + if (DISPLAY_VER(display) >= 35) + x3p_lpd_plane_update_pixel_normalizer(dsb, plane, false); + intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0); intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0); } @@ -1572,7 +1587,7 @@ icl_plane_update_noarm(struct intel_dsb *dsb, } /* FLAT CCS doesn't need to program AUX_DIST */ - if (!HAS_FLAT_CCS(to_i915(display->drm)) && DISPLAY_VER(display) < 20) + if (HAS_AUX_CCS(display)) intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id), skl_plane_aux_dist(plane_state, color_plane)); @@ -1643,6 +1658,14 @@ icl_plane_update_arm(struct intel_dsb *dsb, icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); /* + * In order to have FBC for fp16 formats pixel normalizer block must be + * active. Check if pixel normalizer block need to be enabled for FBC. + * If needed, use normalization factor as 1.0 and enable the block. + */ + if (intel_fbc_is_enable_pixel_normalizer(plane_state)) + x3p_lpd_plane_update_pixel_normalizer(dsb, plane, true); + + /* * 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. @@ -1724,7 +1747,8 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, } if (rotation & DRM_MODE_REFLECT_X && - fb->modifier == DRM_FORMAT_MOD_LINEAR) { + fb->modifier == DRM_FORMAT_MOD_LINEAR && + DISPLAY_VER(display) < 35) { 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); @@ -1780,8 +1804,7 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, } /* 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 && + if (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, @@ -1884,6 +1907,14 @@ static int intel_plane_min_width(struct intel_plane *plane, return 1; } +static int intel_plane_min_height(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + return 1; +} + static int intel_plane_max_width(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane, @@ -2015,6 +2046,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) 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 min_height = intel_plane_min_height(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); @@ -2022,11 +2054,11 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) u32 offset; int ret; - if (w > max_width || w < min_width || h > max_height || h < 1) { + if (w > max_width || w < min_width || h > max_height || h < min_height) { drm_dbg_kms(display->drm, - "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", + "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx%d max: %dx%d)\n", plane->base.base.id, plane->base.name, - w, h, min_width, max_width, max_height); + w, h, min_width, min_height, max_width, max_height); return -EINVAL; } @@ -2086,6 +2118,8 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) int uv_plane = 1; int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ? skl_main_to_aux_plane(fb, uv_plane) : 0; + int min_width = intel_plane_min_width(plane, fb, uv_plane, rotation); + int min_height = intel_plane_min_height(plane, fb, uv_plane, rotation); 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; @@ -2095,11 +2129,11 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) u32 offset; /* FIXME not quite sure how/if these apply to the chroma plane */ - if (w > max_width || h > max_height) { + if (w > max_width || w < min_width || h > max_height || h < min_height) { drm_dbg_kms(display->drm, - "[PLANE:%d:%s] CbCr source size %dx%d too big (limit %dx%d)\n", + "[PLANE:%d:%s] requested CbCr source size %dx%d outside limits (min: %dx%d max: %dx%d)\n", plane->base.base.id, plane->base.name, - w, h, max_width, max_height); + w, h, min_width, min_height, max_width, max_height); return -EINVAL; } @@ -2404,23 +2438,6 @@ void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state, } } -static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) -{ - return pipe - PIPE_A + INTEL_FBC_A; -} - -static bool skl_plane_has_fbc(struct intel_display *display, - enum intel_fbc_id fbc_id, enum plane_id plane_id) -{ - if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) - return false; - - if (DISPLAY_VER(display) >= 20) - return icl_is_hdr_plane(display, plane_id); - else - return plane_id == PLANE_1; -} - static struct intel_fbc *skl_plane_fbc(struct intel_display *display, enum pipe pipe, enum plane_id plane_id) { @@ -2439,13 +2456,10 @@ static bool skl_plane_has_planar(struct intel_display *display, if (display->platform.skylake || display->platform.broxton) return false; - if (DISPLAY_VER(display) == 9 && pipe == PIPE_C) + if (pipe == PIPE_C) return false; - if (plane_id != PLANE_1 && plane_id != PLANE_2) - return false; - - return true; + return plane_id == PLANE_1 || plane_id == PLANE_2; } static const u32 *skl_get_plane_formats(struct intel_display *display, @@ -2461,11 +2475,17 @@ static const u32 *skl_get_plane_formats(struct intel_display *display, } } +static bool glk_plane_has_planar(struct intel_display *display, + enum pipe pipe, enum plane_id plane_id) +{ + return plane_id == PLANE_1 || plane_id == PLANE_2; +} + static const u32 *glk_get_plane_formats(struct intel_display *display, enum pipe pipe, enum plane_id plane_id, int *num_formats) { - if (skl_plane_has_planar(display, pipe, plane_id)) { + if (glk_plane_has_planar(display, pipe, plane_id)) { *num_formats = ARRAY_SIZE(glk_planar_formats); return glk_planar_formats; } else { @@ -2705,8 +2725,10 @@ skl_plane_disable_flip_done(struct intel_plane *plane) static bool skl_plane_has_rc_ccs(struct intel_display *display, enum pipe pipe, enum plane_id plane_id) { - return pipe != PIPE_C && - (plane_id == PLANE_1 || plane_id == PLANE_2); + if (pipe == PIPE_C) + return false; + + return plane_id == PLANE_1 || plane_id == PLANE_2; } static u8 skl_plane_caps(struct intel_display *display, @@ -2834,11 +2856,15 @@ skl_universal_plane_create(struct intel_display *display, intel_fbc_add_plane(skl_plane_fbc(display, pipe, plane_id), plane); if (DISPLAY_VER(display) >= 30) { + plane->min_width = adl_plane_min_width; plane->max_width = xe3_plane_max_width; plane->max_height = icl_plane_max_height; plane->min_cdclk = icl_plane_min_cdclk; } else if (DISPLAY_VER(display) >= 11) { - plane->min_width = icl_plane_min_width; + if (DISPLAY_VER(display) >= 14 || display->platform.alderlake_p) + plane->min_width = adl_plane_min_width; + else + plane->min_width = icl_plane_min_width; if (icl_is_hdr_plane(display, plane_id)) plane->max_width = icl_hdr_plane_max_width; else @@ -2930,7 +2956,7 @@ skl_universal_plane_create(struct intel_display *display, caps = skl_plane_caps(display, pipe, plane_id); /* FIXME: xe has problems with AUX */ - if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(to_i915(display->drm))) + if (!IS_ENABLED(I915) && HAS_AUX_CCS(display)) caps &= ~(INTEL_PLANE_CAP_CCS_RC | INTEL_PLANE_CAP_CCS_RC_CC | INTEL_PLANE_CAP_CCS_MC); @@ -3057,7 +3083,6 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, fourcc = skl_format_to_fourcc(pixel_format, val & PLANE_CTL_ORDER_RGBX, alpha); - fb->format = drm_format_info(fourcc); tiling = val & PLANE_CTL_TILED_MASK; switch (tiling) { @@ -3065,11 +3090,9 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, fb->modifier = DRM_FORMAT_MOD_LINEAR; break; case PLANE_CTL_TILED_X: - plane_config->tiling = I915_TILING_X; fb->modifier = I915_FORMAT_MOD_X_TILED; break; case PLANE_CTL_TILED_Y: - plane_config->tiling = I915_TILING_Y; if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) if (DISPLAY_VER(display) >= 14) fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS; @@ -3110,6 +3133,8 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, goto error; } + fb->format = drm_get_format_info(display->drm, fourcc, fb->modifier); + if (!display->params.enable_dpt && intel_fb_modifier_uses_dpt(display, fb->modifier)) { drm_dbg_kms(display->drm, "DPT disabled, skipping initial FB\n"); |
