summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/skl_universal_plane.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/skl_universal_plane.c')
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c193
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");