From 2e70570656adfe1c5d9a29940faa348d5f132199 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 14 Oct 2021 14:19:16 -0700 Subject: [PATCH 001/176] drm/i915: Avoid bitwise vs logical OR warning in snb_wm_latency_quirk() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new warning in clang points out a place in this file where a bitwise OR is being used with boolean types: drivers/gpu/drm/i915/intel_pm.c:3066:12: warning: use of bitwise '|' with boolean operands [-Wbitwise-instead-of-logical] changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This construct is intentional, as it allows every one of the calls to ilk_increase_wm_latency() to occur (instead of short circuiting with logical OR) while still caring about the result of each call. To make this clearer to the compiler, use the '|=' operator to assign the result of each ilk_increase_wm_latency() call to changed, which keeps the meaning of the code the same but makes it obvious that every one of these calls is expected to happen. Link: https://github.com/ClangBuiltLinux/linux/issues/1473 Reported-by: Nick Desaulniers Signed-off-by: Nathan Chancellor Suggested-by: Dávid Bolvanský Reviewed-by: Nick Desaulniers Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211014211916.3550122-1-nathan@kernel.org --- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f90fe39cf8cad..aaa3a0998e4c6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3050,9 +3050,9 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv) * The BIOS provided WM memory latency values are often * inadequate for high resolution displays. Adjust them. */ - changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) | - ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12) | - ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12); + changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12); + changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12); + changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12); if (!changed) return; From f9a7b19c484067fdcc5972c88ab6f06898adc40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Oct 2021 02:57:01 +0300 Subject: [PATCH 002/176] drm/i915: Move the pxp plane state computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No real reason to have this pxp state computation in intel_atomic_check_planes(). Just stuff it into skl_plane_check(). There was also some funny state copying being done from the old plane state to the new plane state when the plane is anyway disabled. The one thing we presumably must remember to do is copy over the decrypt state when assigning a Y plane for planar YCbCr scanout, so that the Y plane's PLANE_SURF will get the appropriate bit set. The force_black thing should not matter as I'm pretty sure all that stuff is ignored for the Y plane. I suppose this was the reason for the odd placement for the state computation, but I see no reason to deviate from the standard way of doing these things. This also guarantees that we don't calculate things differently between the linked UV and Y plane. v2: Only do stuff for icl+ since 'force_black' depends on the plane CSC which is an icl+ feature Cc: Anshuman Gupta Cc: Daniele Ceraolo Spurio Cc: Juston Li Cc: Rodrigo Vivi Cc: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006235704.28894-2-ville.syrjala@linux.intel.com Reviewed-by: Juston Li #v1 --- drivers/gpu/drm/i915/display/intel_display.c | 31 +------------------ .../drm/i915/display/skl_universal_plane.c | 17 ++++++++++ 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ff598b6cd9530..ce5d6633029a2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -70,8 +70,6 @@ #include "gt/gen8_ppgtt.h" -#include "pxp/intel_pxp.h" - #include "g4x_dp.h" #include "g4x_hdmi.h" #include "i915_drv.h" @@ -6238,6 +6236,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) linked_state->ctl = plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE; linked_state->color_ctl = plane_state->color_ctl; linked_state->view = plane_state->view; + linked_state->decrypt = plane_state->decrypt; intel_plane_copy_hw_state(linked_state, plane_state); linked_state->uapi.src = plane_state->uapi.src; @@ -8600,28 +8599,13 @@ static int intel_bigjoiner_add_affected_planes(struct intel_atomic_state *state) return 0; } -static bool bo_has_valid_encryption(struct drm_i915_gem_object *obj) -{ - struct drm_i915_private *i915 = to_i915(obj->base.dev); - - return intel_pxp_key_check(&i915->gt.pxp, obj, false) == 0; -} - -static bool pxp_is_borked(struct drm_i915_gem_object *obj) -{ - return i915_gem_object_is_protected(obj) && !bo_has_valid_encryption(obj); -} - static int intel_atomic_check_planes(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_plane_state *plane_state; struct intel_plane *plane; - struct intel_plane_state *new_plane_state; - struct intel_plane_state *old_plane_state; struct intel_crtc *crtc; - const struct drm_framebuffer *fb; int i, ret; ret = icl_add_linked_planes(state); @@ -8669,19 +8653,6 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state) return ret; } - for_each_new_intel_plane_in_state(state, plane, plane_state, i) { - new_plane_state = intel_atomic_get_new_plane_state(state, plane); - old_plane_state = intel_atomic_get_old_plane_state(state, plane); - fb = new_plane_state->hw.fb; - if (fb) { - new_plane_state->decrypt = bo_has_valid_encryption(intel_fb_obj(fb)); - new_plane_state->force_black = pxp_is_borked(intel_fb_obj(fb)); - } else { - new_plane_state->decrypt = old_plane_state->decrypt; - new_plane_state->force_black = old_plane_state->force_black; - } - } - return 0; } diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index a0e53a3b267aa..3ee403eafd584 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1737,6 +1737,18 @@ static bool skl_fb_scalable(const struct drm_framebuffer *fb) } } +static bool bo_has_valid_encryption(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + + return intel_pxp_key_check(&i915->gt.pxp, obj, false) == 0; +} + +static bool pxp_is_borked(struct drm_i915_gem_object *obj) +{ + return i915_gem_object_is_protected(obj) && !bo_has_valid_encryption(obj); +} + static int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { @@ -1781,6 +1793,11 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, if (ret) return ret; + if (DISPLAY_VER(dev_priv) >= 11) { + plane_state->decrypt = bo_has_valid_encryption(intel_fb_obj(fb)); + plane_state->force_black = pxp_is_borked(intel_fb_obj(fb)); + } + /* HW only has 8 bits pixel precision, disable plane if invisible */ if (!(plane_state->hw.alpha >> 8)) plane_state->uapi.visible = false; From 841f262e74a7c209055152026041bbe486c962b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Oct 2021 02:57:02 +0300 Subject: [PATCH 003/176] drm/i915: Fix up skl_program_plane() pxp stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's lots of expensive stuff inserted between the PLANE_CTL and PLANE_SURF writes even though the comment before the PLANE_CTL write says not to put stuff there. Move it all to a more apporiate place. There's also a weird PLANE_COLOR_CTL RMW in there. I guess because force_black was computed way too late originally, but that is now sorted. Cc: Anshuman Gupta Cc: Daniele Ceraolo Spurio Cc: Juston Li Cc: Rodrigo Vivi Cc: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006235704.28894-3-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- .../drm/i915/display/skl_universal_plane.c | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 3ee403eafd584..87e94e40a8580 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -985,6 +985,9 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; } + if (plane_state->force_black) + plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; + return plane_color_ctl; } @@ -1090,8 +1093,19 @@ skl_program_plane(struct intel_plane *plane, aux_dist |= skl_plane_stride(plane_state, aux_plane); } + plane_surf = intel_plane_ggtt_offset(plane_state) + surf_addr; + if (plane_state->decrypt) + plane_surf |= PLANE_SURF_DECRYPT; + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + /* + * 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) + intel_load_plane_csc_black(plane); + intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride); intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x); @@ -1146,22 +1160,6 @@ skl_program_plane(struct intel_plane *plane, * the control register just before the surface register. */ intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); - plane_surf = intel_plane_ggtt_offset(plane_state) + surf_addr; - plane_color_ctl = intel_de_read_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id)); - - /* - * 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->decrypt) { - plane_surf |= PLANE_SURF_DECRYPT; - } else if (plane_state->force_black) { - intel_load_plane_csc_black(plane); - plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; - } - - intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), - plane_color_ctl); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), plane_surf); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); From 63d7d05678af5cdc616718806971041ecacf4897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Oct 2021 02:57:03 +0300 Subject: [PATCH 004/176] drm/i915: Remove the drm_dbg() from the vblank evade critical section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are inside the vblank evade critical section here, racing against the raster beam. There is no time to print debug messages. Cc: Anshuman Gupta Cc: Daniele Ceraolo Spurio Cc: Juston Li Cc: Rodrigo Vivi Cc: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006235704.28894-4-ville.syrjala@linux.intel.com Reviewed-by: Juston Li --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 87e94e40a8580..9faffa4815ca3 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1018,8 +1018,6 @@ static void intel_load_plane_csc_black(struct intel_plane *intel_plane) enum plane_id plane = intel_plane->id; u16 postoff = 0; - drm_dbg_kms(&dev_priv->drm, "plane color CTM to black %s:%d\n", - intel_plane->base.name, plane); intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), 0); intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), 0); From 17dbbe7b25446f7ce4af4c5186b60427cdd770a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Oct 2021 02:57:04 +0300 Subject: [PATCH 005/176] drm/i915: Rename intel_load_plane_csc_black() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_load_plane_csc_black() is specific to icl+ so deserves a name reflecting that fact. Also rename the variables to standard form so I won't get confused reading the code. v2: icl+ not glk+ Cc: Anshuman Gupta Cc: Daniele Ceraolo Spurio Cc: Juston Li Cc: Rodrigo Vivi Cc: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006235704.28894-5-ville.syrjala@linux.intel.com Reviewed-by: Juston Li --- .../drm/i915/display/skl_universal_plane.c | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 9faffa4815ca3..7444b88829ea7 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1011,29 +1011,28 @@ static u32 skl_surf_address(const struct intel_plane_state *plane_state, } } -static void intel_load_plane_csc_black(struct intel_plane *intel_plane) +static void icl_plane_csc_load_black(struct intel_plane *plane) { - struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); - enum pipe pipe = intel_plane->pipe; - enum plane_id plane = intel_plane->id; - u16 postoff = 0; + struct drm_i915_private *i915 = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; - intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), 0); + intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 0), 0); + intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 1), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), 0); + intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 2), 0); + intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 3), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), 0); + intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 4), 0); + intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 5), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 1), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 2), 0); + intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0); + intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0); + intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0); - intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 0), postoff); - intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 1), postoff); - intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 2), postoff); + intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0); + intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0); + intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0); } static void @@ -1102,7 +1101,7 @@ skl_program_plane(struct intel_plane *plane, * or after the commit, display content will be garbage. */ if (plane_state->force_black) - intel_load_plane_csc_black(plane); + icl_plane_csc_load_black(plane); intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride); intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), From 2c85034db194ead0595445cbdd70414d3634fcea Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 15 Oct 2021 05:11:29 -0400 Subject: [PATCH 006/176] drm/i915: Clean-up bonding debug message. We should stop using the gen name and the "+" to reference the newer platforms. And on this case specifically we can simplify the debug message even further. Cc: Jani Nikula Cc: Matthew Brost Signed-off-by: Rodrigo Vivi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211015091129.83226-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d225d3dd0b40e..30759b6511808 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -479,7 +479,7 @@ set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data) if (GRAPHICS_VER(i915) >= 12 && !IS_TIGERLAKE(i915) && !IS_ROCKETLAKE(i915) && !IS_ALDERLAKE_S(i915)) { drm_dbg(&i915->drm, - "Bonding on gen12+ aside from TGL, RKL, and ADL_S not supported\n"); + "Bonding not supported on this platform\n"); return -ENODEV; } From 7a279c14df56c741b99085108a643f2dae078773 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 15 Oct 2021 05:16:50 -0400 Subject: [PATCH 007/176] drm/i915: Don't propagate the gen split confusion further There's no such thing as gen13. It is either display 13 or graphics 13. Don't propagate the gen12 confusion further. Cc: Joonas Lahtinen Cc: Jani Nikula Signed-off-by: Rodrigo Vivi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211015091650.87270-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index da9055c3ebf0f..1e221fbe37fd5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8263,7 +8263,7 @@ enum { /* * The below are numbered starting from "S1" on gen11/gen12, but starting - * with gen13 display, the bspec switches to a 0-based numbering scheme + * with display 13, the bspec switches to a 0-based numbering scheme * (although the addresses stay the same so new S0 = old S1, new S1 = old S2). * We'll just use the 0-based numbering here for all platforms since it's the * way things will be named by the hardware team going forward, plus it's more From ae880cd02c547cf474cca976c39c76b629921b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:17 +0300 Subject: [PATCH 008/176] drm/i915: Move PCH refclock stuff into its own file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the PCH refclk stuff (including all the LPT/WPT iCLKIP/CLKOUT_DP things) to its own file. We also suck in the mPHY programming from intel_fdi.c since we're the only caller. Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-2-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_crt.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 537 +-------------- drivers/gpu/drm/i915/display/intel_display.h | 4 - .../drm/i915/display/intel_display_power.c | 1 + drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + drivers/gpu/drm/i915/display/intel_fdi.c | 99 --- drivers/gpu/drm/i915/display/intel_fdi.h | 1 - .../gpu/drm/i915/display/intel_pch_refclk.c | 648 ++++++++++++++++++ .../gpu/drm/i915/display/intel_pch_refclk.h | 21 + drivers/gpu/drm/i915/i915_drv.c | 1 + 11 files changed, 675 insertions(+), 640 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_pch_refclk.c create mode 100644 drivers/gpu/drm/i915/display/intel_pch_refclk.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 660bb03de6fc1..96f3b8f6c50d7 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -226,6 +226,7 @@ i915-y += \ display/intel_hotplug.o \ display/intel_lpe_audio.o \ display/intel_overlay.o \ + display/intel_pch_refclk.o \ display/intel_plane_initial.o \ display/intel_psr.o \ display/intel_quirks.o \ diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 1c161eeed82fb..bf03bd0ecd430 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -45,6 +45,7 @@ #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug.h" +#include "intel_pch_refclk.h" /* Here's the desired hotplug mode */ #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ce5d6633029a2..71d0336de762f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -94,6 +94,7 @@ #include "intel_hotplug.h" #include "intel_overlay.h" #include "intel_panel.h" +#include "intel_pch_refclk.h" #include "intel_pcode.h" #include "intel_pipe_crc.h" #include "intel_plane_initial.h" @@ -101,7 +102,6 @@ #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" -#include "intel_sbi.h" #include "intel_sprite.h" #include "intel_tc.h" #include "intel_vga.h" @@ -1386,133 +1386,6 @@ bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv) return false; } -void lpt_disable_iclkip(struct drm_i915_private *dev_priv) -{ - u32 temp; - - intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_GATE); - - mutex_lock(&dev_priv->sb_lock); - - temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); - temp |= SBI_SSCCTL_DISABLE; - intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); - - mutex_unlock(&dev_priv->sb_lock); -} - -/* Program iCLKIP clock to the desired frequency */ -static void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int clock = crtc_state->hw.adjusted_mode.crtc_clock; - u32 divsel, phaseinc, auxdiv, phasedir = 0; - u32 temp; - - lpt_disable_iclkip(dev_priv); - - /* The iCLK virtual clock root frequency is in MHz, - * but the adjusted_mode->crtc_clock in in KHz. To get the - * divisors, it is necessary to divide one by another, so we - * convert the virtual clock precision to KHz here for higher - * precision. - */ - for (auxdiv = 0; auxdiv < 2; auxdiv++) { - u32 iclk_virtual_root_freq = 172800 * 1000; - u32 iclk_pi_range = 64; - u32 desired_divisor; - - desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, - clock << auxdiv); - divsel = (desired_divisor / iclk_pi_range) - 2; - phaseinc = desired_divisor % iclk_pi_range; - - /* - * Near 20MHz is a corner case which is - * out of range for the 7-bit divisor - */ - if (divsel <= 0x7f) - break; - } - - /* This should not happen with any sane values */ - drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIVSEL(divsel) & - ~SBI_SSCDIVINTPHASE_DIVSEL_MASK); - drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIR(phasedir) & - ~SBI_SSCDIVINTPHASE_INCVAL_MASK); - - drm_dbg_kms(&dev_priv->drm, - "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", - clock, auxdiv, divsel, phasedir, phaseinc); - - mutex_lock(&dev_priv->sb_lock); - - /* Program SSCDIVINTPHASE6 */ - temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); - temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; - temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel); - temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK; - temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc); - temp |= SBI_SSCDIVINTPHASE_DIR(phasedir); - temp |= SBI_SSCDIVINTPHASE_PROPAGATE; - intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); - - /* Program SSCAUXDIV */ - temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); - temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1); - temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv); - intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK); - - /* Enable modulator and associated divider */ - temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); - temp &= ~SBI_SSCCTL_DISABLE; - intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); - - mutex_unlock(&dev_priv->sb_lock); - - /* Wait for initialization time */ - udelay(24); - - intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_UNGATE); -} - -int lpt_get_iclkip(struct drm_i915_private *dev_priv) -{ - u32 divsel, phaseinc, auxdiv; - u32 iclk_virtual_root_freq = 172800 * 1000; - u32 iclk_pi_range = 64; - u32 desired_divisor; - u32 temp; - - if ((intel_de_read(dev_priv, PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0) - return 0; - - mutex_lock(&dev_priv->sb_lock); - - temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); - if (temp & SBI_SSCCTL_DISABLE) { - mutex_unlock(&dev_priv->sb_lock); - return 0; - } - - temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); - divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> - SBI_SSCDIVINTPHASE_DIVSEL_SHIFT; - phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> - SBI_SSCDIVINTPHASE_INCVAL_SHIFT; - - temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); - auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> - SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT; - - mutex_unlock(&dev_priv->sb_lock); - - desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc; - - return DIV_ROUND_CLOSEST(iclk_virtual_root_freq, - desired_divisor << auxdiv); -} static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, enum pipe pch_transcoder) @@ -4297,414 +4170,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, return ret; } -static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) -{ - struct intel_encoder *encoder; - int i; - u32 val, final; - bool has_lvds = false; - bool has_cpu_edp = false; - bool has_panel = false; - bool has_ck505 = false; - bool can_ssc = false; - bool using_ssc_source = false; - - /* We need to take the global config into account */ - for_each_intel_encoder(&dev_priv->drm, encoder) { - switch (encoder->type) { - case INTEL_OUTPUT_LVDS: - has_panel = true; - has_lvds = true; - break; - case INTEL_OUTPUT_EDP: - has_panel = true; - if (encoder->port == PORT_A) - has_cpu_edp = true; - break; - default: - break; - } - } - - if (HAS_PCH_IBX(dev_priv)) { - has_ck505 = dev_priv->vbt.display_clock_mode; - can_ssc = has_ck505; - } else { - has_ck505 = false; - can_ssc = true; - } - - /* Check if any DPLLs are using the SSC source */ - for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) { - u32 temp = intel_de_read(dev_priv, PCH_DPLL(i)); - - if (!(temp & DPLL_VCO_ENABLE)) - continue; - - if ((temp & PLL_REF_INPUT_MASK) == - PLLB_REF_INPUT_SPREADSPECTRUMIN) { - using_ssc_source = true; - break; - } - } - - drm_dbg_kms(&dev_priv->drm, - "has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n", - has_panel, has_lvds, has_ck505, using_ssc_source); - - /* Ironlake: try to setup display ref clock before DPLL - * enabling. This is only under driver's control after - * PCH B stepping, previous chipset stepping should be - * ignoring this setting. - */ - val = intel_de_read(dev_priv, PCH_DREF_CONTROL); - - /* As we must carefully and slowly disable/enable each source in turn, - * compute the final state we want first and check if we need to - * make any changes at all. - */ - final = val; - final &= ~DREF_NONSPREAD_SOURCE_MASK; - if (has_ck505) - final |= DREF_NONSPREAD_CK505_ENABLE; - else - final |= DREF_NONSPREAD_SOURCE_ENABLE; - - final &= ~DREF_SSC_SOURCE_MASK; - final &= ~DREF_CPU_SOURCE_OUTPUT_MASK; - final &= ~DREF_SSC1_ENABLE; - - if (has_panel) { - final |= DREF_SSC_SOURCE_ENABLE; - - if (intel_panel_use_ssc(dev_priv) && can_ssc) - final |= DREF_SSC1_ENABLE; - - if (has_cpu_edp) { - if (intel_panel_use_ssc(dev_priv) && can_ssc) - final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; - else - final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else - final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; - } else if (using_ssc_source) { - final |= DREF_SSC_SOURCE_ENABLE; - final |= DREF_SSC1_ENABLE; - } - - if (final == val) - return; - - /* Always enable nonspread source */ - val &= ~DREF_NONSPREAD_SOURCE_MASK; - - if (has_ck505) - val |= DREF_NONSPREAD_CK505_ENABLE; - else - val |= DREF_NONSPREAD_SOURCE_ENABLE; - - if (has_panel) { - val &= ~DREF_SSC_SOURCE_MASK; - val |= DREF_SSC_SOURCE_ENABLE; - - /* SSC must be turned on before enabling the CPU output */ - if (intel_panel_use_ssc(dev_priv) && can_ssc) { - drm_dbg_kms(&dev_priv->drm, "Using SSC on panel\n"); - val |= DREF_SSC1_ENABLE; - } else - val &= ~DREF_SSC1_ENABLE; - - /* Get SSC going before enabling the outputs */ - intel_de_write(dev_priv, PCH_DREF_CONTROL, val); - intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); - udelay(200); - - val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; - - /* Enable CPU source on CPU attached eDP */ - if (has_cpu_edp) { - if (intel_panel_use_ssc(dev_priv) && can_ssc) { - drm_dbg_kms(&dev_priv->drm, - "Using SSC on eDP\n"); - val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; - } else - val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else - val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; - - intel_de_write(dev_priv, PCH_DREF_CONTROL, val); - intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); - udelay(200); - } else { - drm_dbg_kms(&dev_priv->drm, "Disabling CPU source output\n"); - - val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; - - /* Turn off CPU output */ - val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; - - intel_de_write(dev_priv, PCH_DREF_CONTROL, val); - intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); - udelay(200); - - if (!using_ssc_source) { - drm_dbg_kms(&dev_priv->drm, "Disabling SSC source\n"); - - /* Turn off the SSC source */ - val &= ~DREF_SSC_SOURCE_MASK; - val |= DREF_SSC_SOURCE_DISABLE; - - /* Turn off SSC1 */ - val &= ~DREF_SSC1_ENABLE; - - intel_de_write(dev_priv, PCH_DREF_CONTROL, val); - intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); - udelay(200); - } - } - - BUG_ON(val != final); -} - -/* Implements 3 different sequences from BSpec chapter "Display iCLK - * Programming" based on the parameters passed: - * - Sequence to enable CLKOUT_DP - * - Sequence to enable CLKOUT_DP without spread - * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O - */ -static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv, - bool with_spread, bool with_fdi) -{ - u32 reg, tmp; - - if (drm_WARN(&dev_priv->drm, with_fdi && !with_spread, - "FDI requires downspread\n")) - with_spread = true; - if (drm_WARN(&dev_priv->drm, HAS_PCH_LPT_LP(dev_priv) && - with_fdi, "LP PCH doesn't have FDI\n")) - with_fdi = false; - - mutex_lock(&dev_priv->sb_lock); - - tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); - tmp &= ~SBI_SSCCTL_DISABLE; - tmp |= SBI_SSCCTL_PATHALT; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); - - udelay(24); - - if (with_spread) { - tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); - tmp &= ~SBI_SSCCTL_PATHALT; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); - - if (with_fdi) - lpt_fdi_program_mphy(dev_priv); - } - - reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; - tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); - tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; - intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); - - mutex_unlock(&dev_priv->sb_lock); -} - -/* Sequence to disable CLKOUT_DP */ -void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv) -{ - u32 reg, tmp; - - mutex_lock(&dev_priv->sb_lock); - - reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; - tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); - tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; - intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); - - tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); - if (!(tmp & SBI_SSCCTL_DISABLE)) { - if (!(tmp & SBI_SSCCTL_PATHALT)) { - tmp |= SBI_SSCCTL_PATHALT; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); - udelay(32); - } - tmp |= SBI_SSCCTL_DISABLE; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); - } - - mutex_unlock(&dev_priv->sb_lock); -} - -#define BEND_IDX(steps) ((50 + (steps)) / 5) - -static const u16 sscdivintphase[] = { - [BEND_IDX( 50)] = 0x3B23, - [BEND_IDX( 45)] = 0x3B23, - [BEND_IDX( 40)] = 0x3C23, - [BEND_IDX( 35)] = 0x3C23, - [BEND_IDX( 30)] = 0x3D23, - [BEND_IDX( 25)] = 0x3D23, - [BEND_IDX( 20)] = 0x3E23, - [BEND_IDX( 15)] = 0x3E23, - [BEND_IDX( 10)] = 0x3F23, - [BEND_IDX( 5)] = 0x3F23, - [BEND_IDX( 0)] = 0x0025, - [BEND_IDX( -5)] = 0x0025, - [BEND_IDX(-10)] = 0x0125, - [BEND_IDX(-15)] = 0x0125, - [BEND_IDX(-20)] = 0x0225, - [BEND_IDX(-25)] = 0x0225, - [BEND_IDX(-30)] = 0x0325, - [BEND_IDX(-35)] = 0x0325, - [BEND_IDX(-40)] = 0x0425, - [BEND_IDX(-45)] = 0x0425, - [BEND_IDX(-50)] = 0x0525, -}; - -/* - * Bend CLKOUT_DP - * steps -50 to 50 inclusive, in steps of 5 - * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz) - * change in clock period = -(steps / 10) * 5.787 ps - */ -static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps) -{ - u32 tmp; - int idx = BEND_IDX(steps); - - if (drm_WARN_ON(&dev_priv->drm, steps % 5 != 0)) - return; - - if (drm_WARN_ON(&dev_priv->drm, idx >= ARRAY_SIZE(sscdivintphase))) - return; - - mutex_lock(&dev_priv->sb_lock); - - if (steps % 10 != 0) - tmp = 0xAAAAAAAB; - else - tmp = 0x00000000; - intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK); - - tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK); - tmp &= 0xffff0000; - tmp |= sscdivintphase[idx]; - intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK); - - mutex_unlock(&dev_priv->sb_lock); -} - -#undef BEND_IDX - -static bool spll_uses_pch_ssc(struct drm_i915_private *dev_priv) -{ - u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP); - u32 ctl = intel_de_read(dev_priv, SPLL_CTL); - - if ((ctl & SPLL_PLL_ENABLE) == 0) - return false; - - if ((ctl & SPLL_REF_MASK) == SPLL_REF_MUXED_SSC && - (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) - return true; - - if (IS_BROADWELL(dev_priv) && - (ctl & SPLL_REF_MASK) == SPLL_REF_PCH_SSC_BDW) - return true; - - return false; -} - -static bool wrpll_uses_pch_ssc(struct drm_i915_private *dev_priv, - enum intel_dpll_id id) -{ - u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP); - u32 ctl = intel_de_read(dev_priv, WRPLL_CTL(id)); - - if ((ctl & WRPLL_PLL_ENABLE) == 0) - return false; - - if ((ctl & WRPLL_REF_MASK) == WRPLL_REF_PCH_SSC) - return true; - - if ((IS_BROADWELL(dev_priv) || IS_HSW_ULT(dev_priv)) && - (ctl & WRPLL_REF_MASK) == WRPLL_REF_MUXED_SSC_BDW && - (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) - return true; - - return false; -} - -static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) -{ - struct intel_encoder *encoder; - bool has_fdi = false; - - for_each_intel_encoder(&dev_priv->drm, encoder) { - switch (encoder->type) { - case INTEL_OUTPUT_ANALOG: - has_fdi = true; - break; - default: - break; - } - } - - /* - * The BIOS may have decided to use the PCH SSC - * reference so we must not disable it until the - * relevant PLLs have stopped relying on it. We'll - * just leave the PCH SSC reference enabled in case - * any active PLL is using it. It will get disabled - * after runtime suspend if we don't have FDI. - * - * TODO: Move the whole reference clock handling - * to the modeset sequence proper so that we can - * actually enable/disable/reconfigure these things - * safely. To do that we need to introduce a real - * clock hierarchy. That would also allow us to do - * clock bending finally. - */ - dev_priv->pch_ssc_use = 0; - - if (spll_uses_pch_ssc(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL); - } - - if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) { - drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1); - } - - if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) { - drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2); - } - - if (dev_priv->pch_ssc_use) - return; - - if (has_fdi) { - lpt_bend_clkout_dp(dev_priv, 0); - lpt_enable_clkout_dp(dev_priv, true, true); - } else { - lpt_disable_clkout_dp(dev_priv); - } -} - -/* - * Initialize reference clocks when the driver loads - */ -void intel_init_pch_refclk(struct drm_i915_private *dev_priv) -{ - if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) - ilk_init_pch_refclk(dev_priv); - else if (HAS_PCH_LPT(dev_priv)) - lpt_init_pch_refclk(dev_priv); -} - static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 0c76bf57f86b5..39c18b8807f9c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -521,7 +521,6 @@ void intel_link_compute_m_n(u16 bpp, int nlanes, int pixel_clock, int link_clock, struct intel_link_m_n *m_n, bool constant_n, bool fec_enable); -void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv); u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, u32 pixel_format, u64 modifier); enum drm_mode_status @@ -544,7 +543,6 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, const char *name, u32 reg); void lpt_pch_enable(const struct intel_crtc_state *crtc_state); void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); -void lpt_disable_iclkip(struct drm_i915_private *dev_priv); void intel_init_display_hooks(struct drm_i915_private *dev_priv); unsigned int intel_fb_xy_to_linear(int x, int y, const struct intel_plane_state *state, @@ -583,7 +581,6 @@ intel_framebuffer_create(struct drm_i915_gem_object *obj, void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe); -int lpt_get_iclkip(struct drm_i915_private *dev_priv); bool intel_fuzzy_clock_check(int clock1, int clock2); void intel_display_prepare_reset(struct drm_i915_private *dev_priv); @@ -632,7 +629,6 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915); void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915); void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915); void intel_display_resume(struct drm_device *dev); -void intel_init_pch_refclk(struct drm_i915_private *dev_priv); int intel_modeset_all_pipes(struct intel_atomic_state *state); /* modesetting asserts */ diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 1672604f9ef74..d88da0d0f05ac 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -15,6 +15,7 @@ #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_hotplug.h" +#include "intel_pch_refclk.h" #include "intel_pcode.h" #include "intel_pm.h" #include "intel_pps.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 0a7e04db04be4..ca69b67bbc231 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -26,6 +26,7 @@ #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_dpll_mgr.h" +#include "intel_pch_refclk.h" #include "intel_tc.h" /** diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index dd2cf0c59921d..d1c1600c66cbc 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -8,7 +8,6 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_fdi.h" -#include "intel_sbi.h" static void assert_fdi_tx(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) @@ -1006,104 +1005,6 @@ void ilk_fdi_disable(struct intel_crtc *crtc) udelay(100); } -static void lpt_fdi_reset_mphy(struct drm_i915_private *dev_priv) -{ - u32 tmp; - - tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2); - tmp |= FDI_MPHY_IOSFSB_RESET_CTL; - intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp); - - if (wait_for_us(intel_de_read(dev_priv, SOUTH_CHICKEN2) & - FDI_MPHY_IOSFSB_RESET_STATUS, 100)) - drm_err(&dev_priv->drm, "FDI mPHY reset assert timeout\n"); - - tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2); - tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; - intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp); - - if (wait_for_us((intel_de_read(dev_priv, SOUTH_CHICKEN2) & - FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100)) - drm_err(&dev_priv->drm, "FDI mPHY reset de-assert timeout\n"); -} - -/* WaMPhyProgramming:hsw */ -void lpt_fdi_program_mphy(struct drm_i915_private *dev_priv) -{ - u32 tmp; - - lpt_fdi_reset_mphy(dev_priv); - - tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY); - tmp &= ~(0xFF << 24); - tmp |= (0x12 << 24); - intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY); - tmp |= (1 << 11); - intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY); - tmp |= (1 << 11); - intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY); - tmp |= (1 << 24) | (1 << 21) | (1 << 18); - intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY); - tmp |= (1 << 24) | (1 << 21) | (1 << 18); - intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY); - tmp &= ~(7 << 13); - tmp |= (5 << 13); - intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY); - tmp &= ~(7 << 13); - tmp |= (5 << 13); - intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY); - tmp &= ~0xFF; - tmp |= 0x1C; - intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY); - tmp &= ~0xFF; - tmp |= 0x1C; - intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY); - tmp &= ~(0xFF << 16); - tmp |= (0x1C << 16); - intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY); - tmp &= ~(0xFF << 16); - tmp |= (0x1C << 16); - intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY); - tmp |= (1 << 27); - intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY); - tmp |= (1 << 27); - intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY); - tmp &= ~(0xF << 28); - tmp |= (4 << 28); - intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY); - - tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY); - tmp &= ~(0xF << 28); - tmp |= (4 << 28); - intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY); -} - static const struct intel_fdi_funcs ilk_funcs = { .fdi_link_train = ilk_fdi_link_train, }; diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h index 640d6585c1375..5a361730f80a0 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.h +++ b/drivers/gpu/drm/i915/display/intel_fdi.h @@ -24,7 +24,6 @@ void intel_fdi_init_hook(struct drm_i915_private *dev_priv); void hsw_fdi_link_train(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_fdi_pll_freq_update(struct drm_i915_private *i915); -void lpt_fdi_program_mphy(struct drm_i915_private *i915); void intel_fdi_link_train(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c new file mode 100644 index 0000000000000..b688fd87e3dab --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#include "intel_de.h" +#include "intel_display_types.h" +#include "intel_panel.h" +#include "intel_pch_refclk.h" +#include "intel_sbi.h" + +static void lpt_fdi_reset_mphy(struct drm_i915_private *dev_priv) +{ + u32 tmp; + + tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2); + tmp |= FDI_MPHY_IOSFSB_RESET_CTL; + intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp); + + if (wait_for_us(intel_de_read(dev_priv, SOUTH_CHICKEN2) & + FDI_MPHY_IOSFSB_RESET_STATUS, 100)) + drm_err(&dev_priv->drm, "FDI mPHY reset assert timeout\n"); + + tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2); + tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; + intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp); + + if (wait_for_us((intel_de_read(dev_priv, SOUTH_CHICKEN2) & + FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100)) + drm_err(&dev_priv->drm, "FDI mPHY reset de-assert timeout\n"); +} + +/* WaMPhyProgramming:hsw */ +static void lpt_fdi_program_mphy(struct drm_i915_private *dev_priv) +{ + u32 tmp; + + lpt_fdi_reset_mphy(dev_priv); + + tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY); + tmp &= ~(0xFF << 24); + tmp |= (0x12 << 24); + intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY); + tmp |= (1 << 11); + intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY); + tmp |= (1 << 11); + intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY); + tmp |= (1 << 24) | (1 << 21) | (1 << 18); + intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY); + tmp |= (1 << 24) | (1 << 21) | (1 << 18); + intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY); + tmp &= ~(7 << 13); + tmp |= (5 << 13); + intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY); + tmp &= ~(7 << 13); + tmp |= (5 << 13); + intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY); + tmp &= ~0xFF; + tmp |= 0x1C; + intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY); + tmp &= ~0xFF; + tmp |= 0x1C; + intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY); + tmp &= ~(0xFF << 16); + tmp |= (0x1C << 16); + intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY); + tmp &= ~(0xFF << 16); + tmp |= (0x1C << 16); + intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY); + tmp |= (1 << 27); + intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY); + tmp |= (1 << 27); + intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY); + tmp &= ~(0xF << 28); + tmp |= (4 << 28); + intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY); + tmp &= ~(0xF << 28); + tmp |= (4 << 28); + intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY); +} + +void lpt_disable_iclkip(struct drm_i915_private *dev_priv) +{ + u32 temp; + + intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_GATE); + + mutex_lock(&dev_priv->sb_lock); + + temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + temp |= SBI_SSCCTL_DISABLE; + intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); + + mutex_unlock(&dev_priv->sb_lock); +} + +/* Program iCLKIP clock to the desired frequency */ +void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int clock = crtc_state->hw.adjusted_mode.crtc_clock; + u32 divsel, phaseinc, auxdiv, phasedir = 0; + u32 temp; + + lpt_disable_iclkip(dev_priv); + + /* The iCLK virtual clock root frequency is in MHz, + * but the adjusted_mode->crtc_clock in KHz. To get the + * divisors, it is necessary to divide one by another, so we + * convert the virtual clock precision to KHz here for higher + * precision. + */ + for (auxdiv = 0; auxdiv < 2; auxdiv++) { + u32 iclk_virtual_root_freq = 172800 * 1000; + u32 iclk_pi_range = 64; + u32 desired_divisor; + + desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, + clock << auxdiv); + divsel = (desired_divisor / iclk_pi_range) - 2; + phaseinc = desired_divisor % iclk_pi_range; + + /* + * Near 20MHz is a corner case which is + * out of range for the 7-bit divisor + */ + if (divsel <= 0x7f) + break; + } + + /* This should not happen with any sane values */ + drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIVSEL(divsel) & + ~SBI_SSCDIVINTPHASE_DIVSEL_MASK); + drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIR(phasedir) & + ~SBI_SSCDIVINTPHASE_INCVAL_MASK); + + drm_dbg_kms(&dev_priv->drm, + "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", + clock, auxdiv, divsel, phasedir, phaseinc); + + mutex_lock(&dev_priv->sb_lock); + + /* Program SSCDIVINTPHASE6 */ + temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); + temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; + temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel); + temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK; + temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc); + temp |= SBI_SSCDIVINTPHASE_DIR(phasedir); + temp |= SBI_SSCDIVINTPHASE_PROPAGATE; + intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); + + /* Program SSCAUXDIV */ + temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); + temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1); + temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv); + intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK); + + /* Enable modulator and associated divider */ + temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + temp &= ~SBI_SSCCTL_DISABLE; + intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); + + mutex_unlock(&dev_priv->sb_lock); + + /* Wait for initialization time */ + udelay(24); + + intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_UNGATE); +} + +int lpt_get_iclkip(struct drm_i915_private *dev_priv) +{ + u32 divsel, phaseinc, auxdiv; + u32 iclk_virtual_root_freq = 172800 * 1000; + u32 iclk_pi_range = 64; + u32 desired_divisor; + u32 temp; + + if ((intel_de_read(dev_priv, PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0) + return 0; + + mutex_lock(&dev_priv->sb_lock); + + temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + if (temp & SBI_SSCCTL_DISABLE) { + mutex_unlock(&dev_priv->sb_lock); + return 0; + } + + temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); + divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> + SBI_SSCDIVINTPHASE_DIVSEL_SHIFT; + phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> + SBI_SSCDIVINTPHASE_INCVAL_SHIFT; + + temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); + auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> + SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT; + + mutex_unlock(&dev_priv->sb_lock); + + desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc; + + return DIV_ROUND_CLOSEST(iclk_virtual_root_freq, + desired_divisor << auxdiv); +} + +/* Implements 3 different sequences from BSpec chapter "Display iCLK + * Programming" based on the parameters passed: + * - Sequence to enable CLKOUT_DP + * - Sequence to enable CLKOUT_DP without spread + * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O + */ +static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv, + bool with_spread, bool with_fdi) +{ + u32 reg, tmp; + + if (drm_WARN(&dev_priv->drm, with_fdi && !with_spread, + "FDI requires downspread\n")) + with_spread = true; + if (drm_WARN(&dev_priv->drm, HAS_PCH_LPT_LP(dev_priv) && + with_fdi, "LP PCH doesn't have FDI\n")) + with_fdi = false; + + mutex_lock(&dev_priv->sb_lock); + + tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp &= ~SBI_SSCCTL_DISABLE; + tmp |= SBI_SSCCTL_PATHALT; + intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + + udelay(24); + + if (with_spread) { + tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp &= ~SBI_SSCCTL_PATHALT; + intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + + if (with_fdi) + lpt_fdi_program_mphy(dev_priv); + } + + reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; + tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); + tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; + intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); + + mutex_unlock(&dev_priv->sb_lock); +} + +/* Sequence to disable CLKOUT_DP */ +void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv) +{ + u32 reg, tmp; + + mutex_lock(&dev_priv->sb_lock); + + reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; + tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); + tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; + intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); + + tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + if (!(tmp & SBI_SSCCTL_DISABLE)) { + if (!(tmp & SBI_SSCCTL_PATHALT)) { + tmp |= SBI_SSCCTL_PATHALT; + intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + udelay(32); + } + tmp |= SBI_SSCCTL_DISABLE; + intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + } + + mutex_unlock(&dev_priv->sb_lock); +} + +#define BEND_IDX(steps) ((50 + (steps)) / 5) + +static const u16 sscdivintphase[] = { + [BEND_IDX( 50)] = 0x3B23, + [BEND_IDX( 45)] = 0x3B23, + [BEND_IDX( 40)] = 0x3C23, + [BEND_IDX( 35)] = 0x3C23, + [BEND_IDX( 30)] = 0x3D23, + [BEND_IDX( 25)] = 0x3D23, + [BEND_IDX( 20)] = 0x3E23, + [BEND_IDX( 15)] = 0x3E23, + [BEND_IDX( 10)] = 0x3F23, + [BEND_IDX( 5)] = 0x3F23, + [BEND_IDX( 0)] = 0x0025, + [BEND_IDX( -5)] = 0x0025, + [BEND_IDX(-10)] = 0x0125, + [BEND_IDX(-15)] = 0x0125, + [BEND_IDX(-20)] = 0x0225, + [BEND_IDX(-25)] = 0x0225, + [BEND_IDX(-30)] = 0x0325, + [BEND_IDX(-35)] = 0x0325, + [BEND_IDX(-40)] = 0x0425, + [BEND_IDX(-45)] = 0x0425, + [BEND_IDX(-50)] = 0x0525, +}; + +/* + * Bend CLKOUT_DP + * steps -50 to 50 inclusive, in steps of 5 + * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz) + * change in clock period = -(steps / 10) * 5.787 ps + */ +static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps) +{ + u32 tmp; + int idx = BEND_IDX(steps); + + if (drm_WARN_ON(&dev_priv->drm, steps % 5 != 0)) + return; + + if (drm_WARN_ON(&dev_priv->drm, idx >= ARRAY_SIZE(sscdivintphase))) + return; + + mutex_lock(&dev_priv->sb_lock); + + if (steps % 10 != 0) + tmp = 0xAAAAAAAB; + else + tmp = 0x00000000; + intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK); + + tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK); + tmp &= 0xffff0000; + tmp |= sscdivintphase[idx]; + intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK); + + mutex_unlock(&dev_priv->sb_lock); +} + +#undef BEND_IDX + +static bool spll_uses_pch_ssc(struct drm_i915_private *dev_priv) +{ + u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP); + u32 ctl = intel_de_read(dev_priv, SPLL_CTL); + + if ((ctl & SPLL_PLL_ENABLE) == 0) + return false; + + if ((ctl & SPLL_REF_MASK) == SPLL_REF_MUXED_SSC && + (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) + return true; + + if (IS_BROADWELL(dev_priv) && + (ctl & SPLL_REF_MASK) == SPLL_REF_PCH_SSC_BDW) + return true; + + return false; +} + +static bool wrpll_uses_pch_ssc(struct drm_i915_private *dev_priv, + enum intel_dpll_id id) +{ + u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP); + u32 ctl = intel_de_read(dev_priv, WRPLL_CTL(id)); + + if ((ctl & WRPLL_PLL_ENABLE) == 0) + return false; + + if ((ctl & WRPLL_REF_MASK) == WRPLL_REF_PCH_SSC) + return true; + + if ((IS_BROADWELL(dev_priv) || IS_HSW_ULT(dev_priv)) && + (ctl & WRPLL_REF_MASK) == WRPLL_REF_MUXED_SSC_BDW && + (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) + return true; + + return false; +} + +static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) +{ + struct intel_encoder *encoder; + bool has_fdi = false; + + for_each_intel_encoder(&dev_priv->drm, encoder) { + switch (encoder->type) { + case INTEL_OUTPUT_ANALOG: + has_fdi = true; + break; + default: + break; + } + } + + /* + * The BIOS may have decided to use the PCH SSC + * reference so we must not disable it until the + * relevant PLLs have stopped relying on it. We'll + * just leave the PCH SSC reference enabled in case + * any active PLL is using it. It will get disabled + * after runtime suspend if we don't have FDI. + * + * TODO: Move the whole reference clock handling + * to the modeset sequence proper so that we can + * actually enable/disable/reconfigure these things + * safely. To do that we need to introduce a real + * clock hierarchy. That would also allow us to do + * clock bending finally. + */ + dev_priv->pch_ssc_use = 0; + + if (spll_uses_pch_ssc(dev_priv)) { + drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n"); + dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL); + } + + if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) { + drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n"); + dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1); + } + + if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) { + drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n"); + dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2); + } + + if (dev_priv->pch_ssc_use) + return; + + if (has_fdi) { + lpt_bend_clkout_dp(dev_priv, 0); + lpt_enable_clkout_dp(dev_priv, true, true); + } else { + lpt_disable_clkout_dp(dev_priv); + } +} + +static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) +{ + struct intel_encoder *encoder; + int i; + u32 val, final; + bool has_lvds = false; + bool has_cpu_edp = false; + bool has_panel = false; + bool has_ck505 = false; + bool can_ssc = false; + bool using_ssc_source = false; + + /* We need to take the global config into account */ + for_each_intel_encoder(&dev_priv->drm, encoder) { + switch (encoder->type) { + case INTEL_OUTPUT_LVDS: + has_panel = true; + has_lvds = true; + break; + case INTEL_OUTPUT_EDP: + has_panel = true; + if (encoder->port == PORT_A) + has_cpu_edp = true; + break; + default: + break; + } + } + + if (HAS_PCH_IBX(dev_priv)) { + has_ck505 = dev_priv->vbt.display_clock_mode; + can_ssc = has_ck505; + } else { + has_ck505 = false; + can_ssc = true; + } + + /* Check if any DPLLs are using the SSC source */ + for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) { + u32 temp = intel_de_read(dev_priv, PCH_DPLL(i)); + + if (!(temp & DPLL_VCO_ENABLE)) + continue; + + if ((temp & PLL_REF_INPUT_MASK) == + PLLB_REF_INPUT_SPREADSPECTRUMIN) { + using_ssc_source = true; + break; + } + } + + drm_dbg_kms(&dev_priv->drm, + "has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n", + has_panel, has_lvds, has_ck505, using_ssc_source); + + /* Ironlake: try to setup display ref clock before DPLL + * enabling. This is only under driver's control after + * PCH B stepping, previous chipset stepping should be + * ignoring this setting. + */ + val = intel_de_read(dev_priv, PCH_DREF_CONTROL); + + /* As we must carefully and slowly disable/enable each source in turn, + * compute the final state we want first and check if we need to + * make any changes at all. + */ + final = val; + final &= ~DREF_NONSPREAD_SOURCE_MASK; + if (has_ck505) + final |= DREF_NONSPREAD_CK505_ENABLE; + else + final |= DREF_NONSPREAD_SOURCE_ENABLE; + + final &= ~DREF_SSC_SOURCE_MASK; + final &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + final &= ~DREF_SSC1_ENABLE; + + if (has_panel) { + final |= DREF_SSC_SOURCE_ENABLE; + + if (intel_panel_use_ssc(dev_priv) && can_ssc) + final |= DREF_SSC1_ENABLE; + + if (has_cpu_edp) { + if (intel_panel_use_ssc(dev_priv) && can_ssc) + final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + else + final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; + } else { + final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; + } + } else if (using_ssc_source) { + final |= DREF_SSC_SOURCE_ENABLE; + final |= DREF_SSC1_ENABLE; + } + + if (final == val) + return; + + /* Always enable nonspread source */ + val &= ~DREF_NONSPREAD_SOURCE_MASK; + + if (has_ck505) + val |= DREF_NONSPREAD_CK505_ENABLE; + else + val |= DREF_NONSPREAD_SOURCE_ENABLE; + + if (has_panel) { + val &= ~DREF_SSC_SOURCE_MASK; + val |= DREF_SSC_SOURCE_ENABLE; + + /* SSC must be turned on before enabling the CPU output */ + if (intel_panel_use_ssc(dev_priv) && can_ssc) { + drm_dbg_kms(&dev_priv->drm, "Using SSC on panel\n"); + val |= DREF_SSC1_ENABLE; + } else { + val &= ~DREF_SSC1_ENABLE; + } + + /* Get SSC going before enabling the outputs */ + intel_de_write(dev_priv, PCH_DREF_CONTROL, val); + intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); + udelay(200); + + val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + + /* Enable CPU source on CPU attached eDP */ + if (has_cpu_edp) { + if (intel_panel_use_ssc(dev_priv) && can_ssc) { + drm_dbg_kms(&dev_priv->drm, + "Using SSC on eDP\n"); + val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + } else { + val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; + } + } else { + val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; + } + + intel_de_write(dev_priv, PCH_DREF_CONTROL, val); + intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); + udelay(200); + } else { + drm_dbg_kms(&dev_priv->drm, "Disabling CPU source output\n"); + + val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + + /* Turn off CPU output */ + val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; + + intel_de_write(dev_priv, PCH_DREF_CONTROL, val); + intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); + udelay(200); + + if (!using_ssc_source) { + drm_dbg_kms(&dev_priv->drm, "Disabling SSC source\n"); + + /* Turn off the SSC source */ + val &= ~DREF_SSC_SOURCE_MASK; + val |= DREF_SSC_SOURCE_DISABLE; + + /* Turn off SSC1 */ + val &= ~DREF_SSC1_ENABLE; + + intel_de_write(dev_priv, PCH_DREF_CONTROL, val); + intel_de_posting_read(dev_priv, PCH_DREF_CONTROL); + udelay(200); + } + } + + BUG_ON(val != final); +} + +/* + * Initialize reference clocks when the driver loads + */ +void intel_init_pch_refclk(struct drm_i915_private *dev_priv) +{ + if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) + ilk_init_pch_refclk(dev_priv); + else if (HAS_PCH_LPT(dev_priv)) + lpt_init_pch_refclk(dev_priv); +} diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.h b/drivers/gpu/drm/i915/display/intel_pch_refclk.h new file mode 100644 index 0000000000000..12ab2c75a800a --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef _INTEL_PCH_REFCLK_H_ +#define _INTEL_PCH_REFCLK_H_ + +#include + +struct drm_i915_private; +struct intel_crtc_state; + +void lpt_program_iclkip(const struct intel_crtc_state *crtc_state); +void lpt_disable_iclkip(struct drm_i915_private *dev_priv); +int lpt_get_iclkip(struct drm_i915_private *dev_priv); + +void intel_init_pch_refclk(struct drm_i915_private *dev_priv); +void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv); + +#endif diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b18a250e5d2e7..1e5b75ae99329 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -54,6 +54,7 @@ #include "display/intel_fbdev.h" #include "display/intel_hotplug.h" #include "display/intel_overlay.h" +#include "display/intel_pch_refclk.h" #include "display/intel_pipe_crc.h" #include "display/intel_pps.h" #include "display/intel_sprite.h" From b2de2d006dfa6bf48b141a2a51ca078ed1047b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:18 +0300 Subject: [PATCH 009/176] drm/i915: Move PCH modeset code to its own file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Start moving the code for PCH modeset sequence/etc. to its own file. Still not sure about the file name though... Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-3-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_crt.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 348 +---------------- drivers/gpu/drm/i915/display/intel_display.h | 5 - .../gpu/drm/i915/display/intel_pch_display.c | 365 ++++++++++++++++++ .../gpu/drm/i915/display/intel_pch_display.h | 22 ++ 6 files changed, 390 insertions(+), 352 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_pch_display.c create mode 100644 drivers/gpu/drm/i915/display/intel_pch_display.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 96f3b8f6c50d7..467872cca027f 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -226,6 +226,7 @@ i915-y += \ display/intel_hotplug.o \ display/intel_lpe_audio.o \ display/intel_overlay.o \ + display/intel_pch_display.o \ display/intel_pch_refclk.o \ display/intel_plane_initial.o \ display/intel_psr.o \ diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index bf03bd0ecd430..54540138bd1dd 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -45,6 +45,7 @@ #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug.h" +#include "intel_pch_display.h" #include "intel_pch_refclk.h" /* Here's the desired hotplug mode */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 71d0336de762f..e7ba5603275af 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -94,6 +94,7 @@ #include "intel_hotplug.h" #include "intel_overlay.h" #include "intel_panel.h" +#include "intel_pch_display.h" #include "intel_pch_refclk.h" #include "intel_pcode.h" #include "intel_pipe_crc.h" @@ -452,80 +453,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc) assert_plane_disabled(plane); } -void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - u32 val; - bool enabled; - - val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe)); - enabled = !!(val & TRANS_ENABLE); - I915_STATE_WARN(enabled, - "transcoder assertion failed, should be off on pipe %c but is still active\n", - pipe_name(pipe)); -} - -static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe, enum port port, - i915_reg_t dp_reg) -{ - enum pipe port_pipe; - bool state; - - state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe); - - I915_STATE_WARN(state && port_pipe == pipe, - "PCH DP %c enabled on transcoder %c, should be disabled\n", - port_name(port), pipe_name(pipe)); - - I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, - "IBX PCH DP %c still using transcoder B\n", - port_name(port)); -} - -static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe, enum port port, - i915_reg_t hdmi_reg) -{ - enum pipe port_pipe; - bool state; - - state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe); - - I915_STATE_WARN(state && port_pipe == pipe, - "PCH HDMI %c enabled on transcoder %c, should be disabled\n", - port_name(port), pipe_name(pipe)); - - I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, - "IBX PCH HDMI %c still using transcoder B\n", - port_name(port)); -} - -static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - enum pipe port_pipe; - - assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B); - assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C); - assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D); - - I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && - port_pipe == pipe, - "PCH VGA enabled on transcoder %c, should be disabled\n", - pipe_name(pipe)); - - I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && - port_pipe == pipe, - "PCH LVDS enabled on transcoder %c, should be disabled\n", - pipe_name(pipe)); - - /* PCH SDVOB multiplex with HDMIB */ - assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB); - assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC); - assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID); -} - void vlv_wait_port_ready(struct drm_i915_private *dev_priv, struct intel_digital_port *dig_port, unsigned int expected_mask) @@ -560,154 +487,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, expected_mask); } -static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - i915_reg_t reg; - u32 val, pipeconf_val; - - /* Make sure PCH DPLL is enabled */ - assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll); - - /* FDI must be feeding us bits for PCH ports */ - assert_fdi_tx_enabled(dev_priv, pipe); - assert_fdi_rx_enabled(dev_priv, pipe); - - if (HAS_PCH_CPT(dev_priv)) { - reg = TRANS_CHICKEN2(pipe); - val = intel_de_read(dev_priv, reg); - /* - * Workaround: Set the timing override bit - * before enabling the pch transcoder. - */ - val |= TRANS_CHICKEN2_TIMING_OVERRIDE; - /* Configure frame start delay to match the CPU */ - val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; - val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); - intel_de_write(dev_priv, reg, val); - } - - reg = PCH_TRANSCONF(pipe); - val = intel_de_read(dev_priv, reg); - pipeconf_val = intel_de_read(dev_priv, PIPECONF(pipe)); - - if (HAS_PCH_IBX(dev_priv)) { - /* Configure frame start delay to match the CPU */ - val &= ~TRANS_FRAME_START_DELAY_MASK; - val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1); - - /* - * Make the BPC in transcoder be consistent with - * that in pipeconf reg. For HDMI we must use 8bpc - * here for both 8bpc and 12bpc. - */ - val &= ~PIPECONF_BPC_MASK; - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - val |= PIPECONF_8BPC; - else - val |= pipeconf_val & PIPECONF_BPC_MASK; - } - - val &= ~TRANS_INTERLACE_MASK; - if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) { - if (HAS_PCH_IBX(dev_priv) && - intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO)) - val |= TRANS_LEGACY_INTERLACED_ILK; - else - val |= TRANS_INTERLACED; - } else { - val |= TRANS_PROGRESSIVE; - } - - intel_de_write(dev_priv, reg, val | TRANS_ENABLE); - if (intel_de_wait_for_set(dev_priv, reg, TRANS_STATE_ENABLE, 100)) - drm_err(&dev_priv->drm, "failed to enable transcoder %c\n", - pipe_name(pipe)); -} - -static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, - enum transcoder cpu_transcoder) -{ - u32 val, pipeconf_val; - - /* FDI must be feeding us bits for PCH ports */ - assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder); - assert_fdi_rx_enabled(dev_priv, PIPE_A); - - val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A)); - /* Workaround: set timing override bit. */ - val |= TRANS_CHICKEN2_TIMING_OVERRIDE; - /* Configure frame start delay to match the CPU */ - val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; - val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); - intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); - - val = TRANS_ENABLE; - pipeconf_val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder)); - - if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) == - PIPECONF_INTERLACED_ILK) - val |= TRANS_INTERLACED; - else - val |= TRANS_PROGRESSIVE; - - intel_de_write(dev_priv, LPT_TRANSCONF, val); - if (intel_de_wait_for_set(dev_priv, LPT_TRANSCONF, - TRANS_STATE_ENABLE, 100)) - drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n"); -} - -static void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t reg; - u32 val; - - /* FDI relies on the transcoder */ - assert_fdi_tx_disabled(dev_priv, pipe); - assert_fdi_rx_disabled(dev_priv, pipe); - - /* Ports must be off as well */ - assert_pch_ports_disabled(dev_priv, pipe); - - reg = PCH_TRANSCONF(pipe); - val = intel_de_read(dev_priv, reg); - val &= ~TRANS_ENABLE; - intel_de_write(dev_priv, reg, val); - /* wait for PCH transcoder off, transcoder state */ - if (intel_de_wait_for_clear(dev_priv, reg, TRANS_STATE_ENABLE, 50)) - drm_err(&dev_priv->drm, "failed to disable transcoder %c\n", - pipe_name(pipe)); - - if (HAS_PCH_CPT(dev_priv)) { - /* Workaround: Clear the timing override chicken bit again. */ - reg = TRANS_CHICKEN2(pipe); - val = intel_de_read(dev_priv, reg); - val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE; - intel_de_write(dev_priv, reg, val); - } -} - -void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) -{ - u32 val; - - val = intel_de_read(dev_priv, LPT_TRANSCONF); - val &= ~TRANS_ENABLE; - intel_de_write(dev_priv, LPT_TRANSCONF, val); - /* wait for PCH transcoder off, transcoder state */ - if (intel_de_wait_for_clear(dev_priv, LPT_TRANSCONF, - TRANS_STATE_ENABLE, 50)) - drm_err(&dev_priv->drm, "Failed to disable PCH transcoder\n"); - - /* Workaround: clear timing override bit. */ - val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A)); - val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE; - intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); -} - enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -1386,31 +1165,6 @@ bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv) return false; } - -static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, - enum pipe pch_transcoder) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - - intel_de_write(dev_priv, PCH_TRANS_HTOTAL(pch_transcoder), - intel_de_read(dev_priv, HTOTAL(cpu_transcoder))); - intel_de_write(dev_priv, PCH_TRANS_HBLANK(pch_transcoder), - intel_de_read(dev_priv, HBLANK(cpu_transcoder))); - intel_de_write(dev_priv, PCH_TRANS_HSYNC(pch_transcoder), - intel_de_read(dev_priv, HSYNC(cpu_transcoder))); - - intel_de_write(dev_priv, PCH_TRANS_VTOTAL(pch_transcoder), - intel_de_read(dev_priv, VTOTAL(cpu_transcoder))); - intel_de_write(dev_priv, PCH_TRANS_VBLANK(pch_transcoder), - intel_de_read(dev_priv, VBLANK(cpu_transcoder))); - intel_de_write(dev_priv, PCH_TRANS_VSYNC(pch_transcoder), - intel_de_read(dev_priv, VSYNC(cpu_transcoder))); - intel_de_write(dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder), - intel_de_read(dev_priv, VSYNCSHIFT(cpu_transcoder))); -} - /* * Finds the encoder associated with the given CRTC. This can only be * used when we know that the CRTC isn't feeding multiple encoders! @@ -1441,106 +1195,6 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, return encoder; } -/* - * Enable PCH resources required for PCH ports: - * - PCH PLLs - * - FDI training & RX/TX - * - update transcoder timings - * - DP transcoding bits - * - transcoder - */ -static void ilk_pch_enable(const struct intel_atomic_state *state, - const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - enum pipe pipe = crtc->pipe; - u32 temp; - - assert_pch_transcoder_disabled(dev_priv, pipe); - - /* For PCH output, training FDI link */ - intel_fdi_link_train(crtc, crtc_state); - - /* We need to program the right clock selection before writing the pixel - * mutliplier into the DPLL. */ - if (HAS_PCH_CPT(dev_priv)) { - u32 sel; - - temp = intel_de_read(dev_priv, PCH_DPLL_SEL); - temp |= TRANS_DPLL_ENABLE(pipe); - sel = TRANS_DPLLB_SEL(pipe); - if (crtc_state->shared_dpll == - intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B)) - temp |= sel; - else - temp &= ~sel; - intel_de_write(dev_priv, PCH_DPLL_SEL, temp); - } - - /* XXX: pch pll's can be enabled any time before we enable the PCH - * transcoder, and we actually should do this to not upset any PCH - * transcoder that already use the clock when we share it. - * - * Note that enable_shared_dpll tries to do the right thing, but - * get_shared_dpll unconditionally resets the pll - we need that to have - * the right LVDS enable sequence. */ - intel_enable_shared_dpll(crtc_state); - - /* set transcoder timing, panel must allow it */ - assert_pps_unlocked(dev_priv, pipe); - ilk_pch_transcoder_set_timings(crtc_state, pipe); - - intel_fdi_normal_train(crtc); - - /* For PCH DP, enable TRANS_DP_CTL */ - if (HAS_PCH_CPT(dev_priv) && - intel_crtc_has_dp_encoder(crtc_state)) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - u32 bpc = (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; - i915_reg_t reg = TRANS_DP_CTL(pipe); - enum port port; - - temp = intel_de_read(dev_priv, reg); - temp &= ~(TRANS_DP_PORT_SEL_MASK | - TRANS_DP_SYNC_MASK | - TRANS_DP_BPC_MASK); - temp |= TRANS_DP_OUTPUT_ENABLE; - temp |= bpc << 9; /* same format but at 11:9 */ - - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; - - port = intel_get_crtc_new_encoder(state, crtc_state)->port; - drm_WARN_ON(dev, port < PORT_B || port > PORT_D); - temp |= TRANS_DP_PORT_SEL(port); - - intel_de_write(dev_priv, reg, temp); - } - - ilk_enable_pch_transcoder(crtc_state); -} - -void lpt_pch_enable(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - - assert_pch_transcoder_disabled(dev_priv, PIPE_A); - - lpt_program_iclkip(crtc_state); - - /* Set transcoder timing. */ - ilk_pch_transcoder_set_timings(crtc_state, PIPE_A); - - lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); -} - static void cpt_verify_modeset(struct drm_i915_private *dev_priv, enum pipe pipe) { diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 39c18b8807f9c..93c84f2174b56 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -541,8 +541,6 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv, const char *name, u32 reg, int ref_freq); int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, const char *name, u32 reg); -void lpt_pch_enable(const struct intel_crtc_state *crtc_state); -void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); void intel_init_display_hooks(struct drm_i915_private *dev_priv); unsigned int intel_fb_xy_to_linear(int x, int y, const struct intel_plane_state *state, @@ -578,9 +576,6 @@ struct drm_framebuffer * intel_framebuffer_create(struct drm_i915_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd); -void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe); - bool intel_fuzzy_clock_check(int clock1, int clock2); void intel_display_prepare_reset(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c new file mode 100644 index 0000000000000..0056c2fe49ecc --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#include "g4x_dp.h" +#include "intel_crt.h" +#include "intel_de.h" +#include "intel_display_types.h" +#include "intel_fdi.h" +#include "intel_lvds.h" +#include "intel_pch_display.h" +#include "intel_pch_refclk.h" +#include "intel_pps.h" +#include "intel_sdvo.h" + +static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port, + i915_reg_t dp_reg) +{ + enum pipe port_pipe; + bool state; + + state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe); + + I915_STATE_WARN(state && port_pipe == pipe, + "PCH DP %c enabled on transcoder %c, should be disabled\n", + port_name(port), pipe_name(pipe)); + + I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, + "IBX PCH DP %c still using transcoder B\n", + port_name(port)); +} + +static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port, + i915_reg_t hdmi_reg) +{ + enum pipe port_pipe; + bool state; + + state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe); + + I915_STATE_WARN(state && port_pipe == pipe, + "PCH HDMI %c enabled on transcoder %c, should be disabled\n", + port_name(port), pipe_name(pipe)); + + I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, + "IBX PCH HDMI %c still using transcoder B\n", + port_name(port)); +} + +static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + enum pipe port_pipe; + + assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B); + assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C); + assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D); + + I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && + port_pipe == pipe, + "PCH VGA enabled on transcoder %c, should be disabled\n", + pipe_name(pipe)); + + I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && + port_pipe == pipe, + "PCH LVDS enabled on transcoder %c, should be disabled\n", + pipe_name(pipe)); + + /* PCH SDVOB multiplex with HDMIB */ + assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB); + assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC); + assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID); +} + +static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + u32 val; + bool enabled; + + val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe)); + enabled = !!(val & TRANS_ENABLE); + I915_STATE_WARN(enabled, + "transcoder assertion failed, should be off on pipe %c but is still active\n", + pipe_name(pipe)); +} + +static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, + enum pipe pch_transcoder) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + intel_de_write(dev_priv, PCH_TRANS_HTOTAL(pch_transcoder), + intel_de_read(dev_priv, HTOTAL(cpu_transcoder))); + intel_de_write(dev_priv, PCH_TRANS_HBLANK(pch_transcoder), + intel_de_read(dev_priv, HBLANK(cpu_transcoder))); + intel_de_write(dev_priv, PCH_TRANS_HSYNC(pch_transcoder), + intel_de_read(dev_priv, HSYNC(cpu_transcoder))); + + intel_de_write(dev_priv, PCH_TRANS_VTOTAL(pch_transcoder), + intel_de_read(dev_priv, VTOTAL(cpu_transcoder))); + intel_de_write(dev_priv, PCH_TRANS_VBLANK(pch_transcoder), + intel_de_read(dev_priv, VBLANK(cpu_transcoder))); + intel_de_write(dev_priv, PCH_TRANS_VSYNC(pch_transcoder), + intel_de_read(dev_priv, VSYNC(cpu_transcoder))); + intel_de_write(dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder), + intel_de_read(dev_priv, VSYNCSHIFT(cpu_transcoder))); +} + +static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + i915_reg_t reg; + u32 val, pipeconf_val; + + /* Make sure PCH DPLL is enabled */ + assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll); + + /* FDI must be feeding us bits for PCH ports */ + assert_fdi_tx_enabled(dev_priv, pipe); + assert_fdi_rx_enabled(dev_priv, pipe); + + if (HAS_PCH_CPT(dev_priv)) { + reg = TRANS_CHICKEN2(pipe); + val = intel_de_read(dev_priv, reg); + /* + * Workaround: Set the timing override bit + * before enabling the pch transcoder. + */ + val |= TRANS_CHICKEN2_TIMING_OVERRIDE; + /* Configure frame start delay to match the CPU */ + val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; + val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + intel_de_write(dev_priv, reg, val); + } + + reg = PCH_TRANSCONF(pipe); + val = intel_de_read(dev_priv, reg); + pipeconf_val = intel_de_read(dev_priv, PIPECONF(pipe)); + + if (HAS_PCH_IBX(dev_priv)) { + /* Configure frame start delay to match the CPU */ + val &= ~TRANS_FRAME_START_DELAY_MASK; + val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + + /* + * Make the BPC in transcoder be consistent with + * that in pipeconf reg. For HDMI we must use 8bpc + * here for both 8bpc and 12bpc. + */ + val &= ~PIPECONF_BPC_MASK; + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + val |= PIPECONF_8BPC; + else + val |= pipeconf_val & PIPECONF_BPC_MASK; + } + + val &= ~TRANS_INTERLACE_MASK; + if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) { + if (HAS_PCH_IBX(dev_priv) && + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO)) + val |= TRANS_LEGACY_INTERLACED_ILK; + else + val |= TRANS_INTERLACED; + } else { + val |= TRANS_PROGRESSIVE; + } + + intel_de_write(dev_priv, reg, val | TRANS_ENABLE); + if (intel_de_wait_for_set(dev_priv, reg, TRANS_STATE_ENABLE, 100)) + drm_err(&dev_priv->drm, "failed to enable transcoder %c\n", + pipe_name(pipe)); +} + +void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + i915_reg_t reg; + u32 val; + + /* FDI relies on the transcoder */ + assert_fdi_tx_disabled(dev_priv, pipe); + assert_fdi_rx_disabled(dev_priv, pipe); + + /* Ports must be off as well */ + assert_pch_ports_disabled(dev_priv, pipe); + + reg = PCH_TRANSCONF(pipe); + val = intel_de_read(dev_priv, reg); + val &= ~TRANS_ENABLE; + intel_de_write(dev_priv, reg, val); + /* wait for PCH transcoder off, transcoder state */ + if (intel_de_wait_for_clear(dev_priv, reg, TRANS_STATE_ENABLE, 50)) + drm_err(&dev_priv->drm, "failed to disable transcoder %c\n", + pipe_name(pipe)); + + if (HAS_PCH_CPT(dev_priv)) { + /* Workaround: Clear the timing override chicken bit again. */ + reg = TRANS_CHICKEN2(pipe); + val = intel_de_read(dev_priv, reg); + val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE; + intel_de_write(dev_priv, reg, val); + } +} + +/* + * Enable PCH resources required for PCH ports: + * - PCH PLLs + * - FDI training & RX/TX + * - update transcoder timings + * - DP transcoding bits + * - transcoder + */ +void ilk_pch_enable(const struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + enum pipe pipe = crtc->pipe; + u32 temp; + + assert_pch_transcoder_disabled(dev_priv, pipe); + + /* For PCH output, training FDI link */ + intel_fdi_link_train(crtc, crtc_state); + + /* + * We need to program the right clock selection + * before writing the pixel multiplier into the DPLL. + */ + if (HAS_PCH_CPT(dev_priv)) { + u32 sel; + + temp = intel_de_read(dev_priv, PCH_DPLL_SEL); + temp |= TRANS_DPLL_ENABLE(pipe); + sel = TRANS_DPLLB_SEL(pipe); + if (crtc_state->shared_dpll == + intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B)) + temp |= sel; + else + temp &= ~sel; + intel_de_write(dev_priv, PCH_DPLL_SEL, temp); + } + + /* + * XXX: pch pll's can be enabled any time before we enable the PCH + * transcoder, and we actually should do this to not upset any PCH + * transcoder that already use the clock when we share it. + * + * Note that enable_shared_dpll tries to do the right thing, but + * get_shared_dpll unconditionally resets the pll - we need that + * to have the right LVDS enable sequence. + */ + intel_enable_shared_dpll(crtc_state); + + /* set transcoder timing, panel must allow it */ + assert_pps_unlocked(dev_priv, pipe); + ilk_pch_transcoder_set_timings(crtc_state, pipe); + + intel_fdi_normal_train(crtc); + + /* For PCH DP, enable TRANS_DP_CTL */ + if (HAS_PCH_CPT(dev_priv) && + intel_crtc_has_dp_encoder(crtc_state)) { + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + u32 bpc = (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; + i915_reg_t reg = TRANS_DP_CTL(pipe); + enum port port; + + temp = intel_de_read(dev_priv, reg); + temp &= ~(TRANS_DP_PORT_SEL_MASK | + TRANS_DP_SYNC_MASK | + TRANS_DP_BPC_MASK); + temp |= TRANS_DP_OUTPUT_ENABLE; + temp |= bpc << 9; /* same format but at 11:9 */ + + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; + + port = intel_get_crtc_new_encoder(state, crtc_state)->port; + drm_WARN_ON(dev, port < PORT_B || port > PORT_D); + temp |= TRANS_DP_PORT_SEL(port); + + intel_de_write(dev_priv, reg, temp); + } + + ilk_enable_pch_transcoder(crtc_state); +} + +static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + u32 val, pipeconf_val; + + /* FDI must be feeding us bits for PCH ports */ + assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder); + assert_fdi_rx_enabled(dev_priv, PIPE_A); + + val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A)); + /* Workaround: set timing override bit. */ + val |= TRANS_CHICKEN2_TIMING_OVERRIDE; + /* Configure frame start delay to match the CPU */ + val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; + val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); + + val = TRANS_ENABLE; + pipeconf_val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder)); + + if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) == + PIPECONF_INTERLACED_ILK) + val |= TRANS_INTERLACED; + else + val |= TRANS_PROGRESSIVE; + + intel_de_write(dev_priv, LPT_TRANSCONF, val); + if (intel_de_wait_for_set(dev_priv, LPT_TRANSCONF, + TRANS_STATE_ENABLE, 100)) + drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n"); +} + +void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) +{ + u32 val; + + val = intel_de_read(dev_priv, LPT_TRANSCONF); + val &= ~TRANS_ENABLE; + intel_de_write(dev_priv, LPT_TRANSCONF, val); + /* wait for PCH transcoder off, transcoder state */ + if (intel_de_wait_for_clear(dev_priv, LPT_TRANSCONF, + TRANS_STATE_ENABLE, 50)) + drm_err(&dev_priv->drm, "Failed to disable PCH transcoder\n"); + + /* Workaround: clear timing override bit. */ + val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A)); + val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE; + intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); +} + +void lpt_pch_enable(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + assert_pch_transcoder_disabled(dev_priv, PIPE_A); + + lpt_program_iclkip(crtc_state); + + /* Set transcoder timing. */ + ilk_pch_transcoder_set_timings(crtc_state, PIPE_A); + + lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); +} diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h new file mode 100644 index 0000000000000..6eba1fd667ea5 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef _INTEL_PCH_DISPLAY_H_ +#define _INTEL_PCH_DISPLAY_H_ + +enum pipe; +struct drm_i915_private; +struct intel_atomic_state; +struct intel_crtc_state; + +void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, + enum pipe pipe); +void ilk_pch_enable(const struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state); + +void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); +void lpt_pch_enable(const struct intel_crtc_state *crtc_state); + +#endif From ccebd0e4021084361d1549f4e83688b1fae89c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:19 +0300 Subject: [PATCH 010/176] drm/i915: Clean up the {ilk,lpt}_pch_enable() calling convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the clean "atomic_state+crtc" approach of passing arguments to the top level PCH modeset code. And while at it we can also just pass the whole crtc to ilk_disable_pch_transcoder(). v2: Elimiate double space between function args (Dave) Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-4-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_crt.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- .../gpu/drm/i915/display/intel_pch_display.c | 23 +++++++++++-------- .../gpu/drm/i915/display/intel_pch_display.h | 12 +++++----- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 54540138bd1dd..4038ae342ea16 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -318,7 +318,7 @@ static void hsw_enable_crt(struct intel_atomic_state *state, intel_enable_transcoder(crtc_state); - lpt_pch_enable(crtc_state); + lpt_pch_enable(state, crtc); intel_crtc_vblank_on(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e7ba5603275af..31f51d056d55e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2018,7 +2018,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_enable_transcoder(new_crtc_state); if (new_crtc_state->has_pch_encoder) - ilk_pch_enable(state, new_crtc_state); + ilk_pch_enable(state, crtc); intel_crtc_vblank_on(new_crtc_state); @@ -2297,7 +2297,7 @@ static void ilk_crtc_disable(struct intel_atomic_state *state, intel_encoders_post_disable(state, crtc); if (old_crtc_state->has_pch_encoder) { - ilk_disable_pch_transcoder(dev_priv, pipe); + ilk_disable_pch_transcoder(crtc); if (HAS_PCH_CPT(dev_priv)) { i915_reg_t reg; diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 0056c2fe49ecc..22dbd94cc5fd5 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -179,9 +179,10 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) pipe_name(pipe)); } -void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, - enum pipe pipe) +void ilk_disable_pch_transcoder(struct intel_crtc *crtc) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; i915_reg_t reg; u32 val; @@ -218,12 +219,12 @@ void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, * - DP transcoding bits * - transcoder */ -void ilk_pch_enable(const struct intel_atomic_state *state, - const struct intel_crtc_state *crtc_state) +void ilk_pch_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; u32 temp; @@ -289,7 +290,7 @@ void ilk_pch_enable(const struct intel_atomic_state *state, temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; port = intel_get_crtc_new_encoder(state, crtc_state)->port; - drm_WARN_ON(dev, port < PORT_B || port > PORT_D); + drm_WARN_ON(&dev_priv->drm, port < PORT_B || port > PORT_D); temp |= TRANS_DP_PORT_SEL(port); intel_de_write(dev_priv, reg, temp); @@ -348,10 +349,12 @@ void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); } -void lpt_pch_enable(const struct intel_crtc_state *crtc_state) +void lpt_pch_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; assert_pch_transcoder_disabled(dev_priv, PIPE_A); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index 6eba1fd667ea5..7f9df2c13cf3d 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -6,17 +6,17 @@ #ifndef _INTEL_PCH_DISPLAY_H_ #define _INTEL_PCH_DISPLAY_H_ -enum pipe; struct drm_i915_private; struct intel_atomic_state; +struct intel_crtc; struct intel_crtc_state; -void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, - enum pipe pipe); -void ilk_pch_enable(const struct intel_atomic_state *state, - const struct intel_crtc_state *crtc_state); +void ilk_disable_pch_transcoder(struct intel_crtc *crtc); +void ilk_pch_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc); void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); -void lpt_pch_enable(const struct intel_crtc_state *crtc_state); +void lpt_pch_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc); #endif From f45d2252ee10b036d539d93a752a2434a54a0d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 18:35:25 +0300 Subject: [PATCH 011/176] drm/i915: Move LPT PCH readout code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuke the hsw_get_ddi_port_state() eyesore by putting the readout code into intel_pch_display.c, and calling it directly from hsw_crt_get_config(). Note that the nuked TRANS_DDI_FUNC_CTL readout from hsw_get_ddi_port_state() is now etirely redundant since we get called from the encoder->get_config() so we already know we're dealing with the correct DDI port. Previously the code was called from a place where that wasn't known so it had to checked manually. v2: Clarify the TRANS_DDI_FUNC_CTL change (Dave) Nuke the now unused *TRANS_DDI_FUNC_CTL_VAL_TO_PORT() (Dave) Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018153525.21597-1-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_crt.c | 2 + drivers/gpu/drm/i915/display/intel_display.c | 46 ++----------------- drivers/gpu/drm/i915/display/intel_display.h | 2 + .../gpu/drm/i915/display/intel_pch_display.c | 18 ++++++++ .../gpu/drm/i915/display/intel_pch_display.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 2 - 6 files changed, 26 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 4038ae342ea16..03cfae46f92f6 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -147,6 +147,8 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + lpt_pch_get_config(pipe_config); + hsw_ddi_get_config(encoder, pipe_config); pipe_config->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 31f51d056d55e..482498188c6cc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4088,8 +4088,8 @@ void intel_dp_get_m_n(struct intel_crtc *crtc, &pipe_config->dp_m2_n2); } -static void ilk_get_fdi_m_n_config(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +void ilk_get_fdi_m_n_config(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config) { intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, &pipe_config->fdi_m_n, NULL); @@ -4484,45 +4484,6 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, return transcoder_is_dsi(pipe_config->cpu_transcoder); } -static void hsw_get_ddi_port_state(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; - enum port port; - u32 tmp; - - if (transcoder_is_dsi(cpu_transcoder)) { - port = (cpu_transcoder == TRANSCODER_DSI_A) ? - PORT_A : PORT_B; - } else { - tmp = intel_de_read(dev_priv, - TRANS_DDI_FUNC_CTL(cpu_transcoder)); - if (!(tmp & TRANS_DDI_FUNC_ENABLE)) - return; - if (DISPLAY_VER(dev_priv) >= 12) - port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); - else - port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); - } - - /* - * Haswell has only FDI/PCH transcoder A. It is which is connected to - * DDI E. So just check whether this pipe is wired to DDI E and whether - * the PCH transcoder is on. - */ - if (DISPLAY_VER(dev_priv) < 9 && - (port == PORT_E) && intel_de_read(dev_priv, LPT_TRANSCONF) & TRANS_ENABLE) { - pipe_config->has_pch_encoder = true; - - tmp = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); - pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> - FDI_DP_PORT_WIDTH_SHIFT) + 1; - - ilk_get_fdi_m_n_config(crtc, pipe_config); - } -} - static bool hsw_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -4560,8 +4521,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, /* we cannot read out most state, so don't bother.. */ pipe_config->quirks |= PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE; } else if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || - DISPLAY_VER(dev_priv) >= 11) { - hsw_get_ddi_port_state(crtc, pipe_config); + DISPLAY_VER(dev_priv) >= 11) { intel_get_transcoder_timings(crtc, pipe_config); } diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 93c84f2174b56..5bc8d89131785 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -584,6 +584,8 @@ void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, enum link_m_n_set m_n); +void ilk_get_fdi_m_n_config(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config); int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 22dbd94cc5fd5..b4c6557ba8b93 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -366,3 +366,21 @@ void lpt_pch_enable(struct intel_atomic_state *state, lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); } + +void lpt_pch_get_config(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + u32 tmp; + + if ((intel_de_read(dev_priv, LPT_TRANSCONF) & TRANS_ENABLE) == 0) + return; + + crtc_state->has_pch_encoder = true; + + tmp = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); + crtc_state->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> + FDI_DP_PORT_WIDTH_SHIFT) + 1; + + ilk_get_fdi_m_n_config(crtc, crtc_state); +} diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index 7f9df2c13cf3d..e0ff331c0bc6d 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -18,5 +18,6 @@ void ilk_pch_enable(struct intel_atomic_state *state, void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); void lpt_pch_enable(struct intel_atomic_state *state, struct intel_crtc *crtc); +void lpt_pch_get_config(struct intel_crtc_state *crtc_state); #endif diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1e221fbe37fd5..d9f7a729333fa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10212,8 +10212,6 @@ enum skl_power_gate { #define TGL_TRANS_DDI_PORT_MASK (0xf << TGL_TRANS_DDI_PORT_SHIFT) #define TRANS_DDI_SELECT_PORT(x) ((x) << TRANS_DDI_PORT_SHIFT) #define TGL_TRANS_DDI_SELECT_PORT(x) (((x) + 1) << TGL_TRANS_DDI_PORT_SHIFT) -#define TRANS_DDI_FUNC_CTL_VAL_TO_PORT(val) (((val) & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT) -#define TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(val) ((((val) & TGL_TRANS_DDI_PORT_MASK) >> TGL_TRANS_DDI_PORT_SHIFT) - 1) #define TRANS_DDI_MODE_SELECT_MASK (7 << 24) #define TRANS_DDI_MODE_SELECT_HDMI (0 << 24) #define TRANS_DDI_MODE_SELECT_DVI (1 << 24) From 7d9ae6332e77c1dd57cd5679a27d6690d2e8215d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:21 +0300 Subject: [PATCH 012/176] drm/i915: Extract ilk_pch_get_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the ilk+ PCH state readout into its own function and relocate to the appropriate file. The clock readout parts are perhaps a bit iffy since we depend on the gmch DPLL readout code. But we can think about the clock readout big picture later. Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-6-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_display.c | 72 ++----------------- drivers/gpu/drm/i915/display/intel_display.h | 3 +- .../gpu/drm/i915/display/intel_pch_display.c | 68 ++++++++++++++++++ .../gpu/drm/i915/display/intel_pch_display.h | 1 + 4 files changed, 75 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 482498188c6cc..9bac7418fe3fc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -111,11 +111,6 @@ #include "skl_universal_plane.h" #include "vlv_sideband.h" -static void i9xx_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config); -static void ilk_pch_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config); - static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state, @@ -4226,50 +4221,9 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, i9xx_get_pipe_color_config(pipe_config); intel_color_get_config(pipe_config); - if (intel_de_read(dev_priv, PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { - struct intel_shared_dpll *pll; - enum intel_dpll_id pll_id; - bool pll_active; - - pipe_config->has_pch_encoder = true; - - tmp = intel_de_read(dev_priv, FDI_RX_CTL(crtc->pipe)); - pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> - FDI_DP_PORT_WIDTH_SHIFT) + 1; - - ilk_get_fdi_m_n_config(crtc, pipe_config); - - if (HAS_PCH_IBX(dev_priv)) { - /* - * The pipe->pch transcoder and pch transcoder->pll - * mapping is fixed. - */ - pll_id = (enum intel_dpll_id) crtc->pipe; - } else { - tmp = intel_de_read(dev_priv, PCH_DPLL_SEL); - if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) - pll_id = DPLL_ID_PCH_PLL_B; - else - pll_id= DPLL_ID_PCH_PLL_A; - } - - pipe_config->shared_dpll = - intel_get_shared_dpll_by_id(dev_priv, pll_id); - pll = pipe_config->shared_dpll; - - pll_active = intel_dpll_get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state); - drm_WARN_ON(dev, !pll_active); - - tmp = pipe_config->dpll_hw_state.dpll; - pipe_config->pixel_multiplier = - ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) - >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; + pipe_config->pixel_multiplier = 1; - ilk_pch_clock_get(crtc, pipe_config); - } else { - pipe_config->pixel_multiplier = 1; - } + ilk_pch_get_config(pipe_config); intel_get_transcoder_timings(crtc, pipe_config); intel_get_pipe_src_size(crtc, pipe_config); @@ -4852,8 +4806,8 @@ static int i9xx_pll_refclk(struct drm_device *dev, } /* Returns the clock of the currently programmed mode of the given pipe. */ -static void i9xx_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +void i9xx_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -4963,24 +4917,6 @@ int intel_dotclock_calculate(int link_freq, return div_u64(mul_u32_u32(m_n->link_m, link_freq), m_n->link_n); } -static void ilk_pch_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - /* read out port_clock from the DPLL */ - i9xx_crtc_clock_get(crtc, pipe_config); - - /* - * In case there is an active pipe without active ports, - * we may need some idea for the dotclock anyway. - * Calculate one based on the FDI configuration. - */ - pipe_config->hw.adjusted_mode.crtc_clock = - intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), - &pipe_config->fdi_m_n); -} - /* Returns the currently programmed mode of the given encoder. */ struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 5bc8d89131785..c2efba7c6c172 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -586,8 +586,9 @@ void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, enum link_m_n_set m_n); void ilk_get_fdi_m_n_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); +void i9xx_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config); int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); - bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state); void hsw_enable_ips(const struct intel_crtc_state *crtc_state); void hsw_disable_ips(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index b4c6557ba8b93..13685c1929322 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -299,6 +299,74 @@ void ilk_pch_enable(struct intel_atomic_state *state, ilk_enable_pch_transcoder(crtc_state); } +static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + /* read out port_clock from the DPLL */ + i9xx_crtc_clock_get(crtc, crtc_state); + + /* + * In case there is an active pipe without active ports, + * we may need some idea for the dotclock anyway. + * Calculate one based on the FDI configuration. + */ + crtc_state->hw.adjusted_mode.crtc_clock = + intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, crtc_state), + &crtc_state->fdi_m_n); +} + +void ilk_pch_get_config(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_shared_dpll *pll; + enum pipe pipe = crtc->pipe; + enum intel_dpll_id pll_id; + bool pll_active; + u32 tmp; + + if ((intel_de_read(dev_priv, PCH_TRANSCONF(pipe)) & TRANS_ENABLE) == 0) + return; + + crtc_state->has_pch_encoder = true; + + tmp = intel_de_read(dev_priv, FDI_RX_CTL(pipe)); + crtc_state->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> + FDI_DP_PORT_WIDTH_SHIFT) + 1; + + ilk_get_fdi_m_n_config(crtc, crtc_state); + + if (HAS_PCH_IBX(dev_priv)) { + /* + * The pipe->pch transcoder and pch transcoder->pll + * mapping is fixed. + */ + pll_id = (enum intel_dpll_id) pipe; + } else { + tmp = intel_de_read(dev_priv, PCH_DPLL_SEL); + if (tmp & TRANS_DPLLB_SEL(pipe)) + pll_id = DPLL_ID_PCH_PLL_B; + else + pll_id = DPLL_ID_PCH_PLL_A; + } + + crtc_state->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, pll_id); + pll = crtc_state->shared_dpll; + + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &crtc_state->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); + + tmp = crtc_state->dpll_hw_state.dpll; + crtc_state->pixel_multiplier = + ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) + >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; + + ilk_pch_clock_get(crtc_state); +} + static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index e0ff331c0bc6d..6e834fbebd64a 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -14,6 +14,7 @@ struct intel_crtc_state; void ilk_disable_pch_transcoder(struct intel_crtc *crtc); void ilk_pch_enable(struct intel_atomic_state *state, struct intel_crtc *crtc); +void ilk_pch_get_config(struct intel_crtc_state *crtc_state); void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); void lpt_pch_enable(struct intel_atomic_state *state, From 9e68fa88b85910091be186f9022b36f4fa83b31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:22 +0300 Subject: [PATCH 013/176] drm/i915: Move iCLKIP readout to the pch code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the lpt_get_iclkip() call from hsw_crt_get_config() since that's where we have the lpt_program_iclkip() call as well. Tehcnically this isn't perhaps quite right since iCLKIP is providing the CRT dotclock. So one can argue all of it should be directly in intel_crt.c. But since the CRT port is the only one on the PCH sticking it all into the PCH code seems OK. Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-7-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_crt.c | 4 ---- drivers/gpu/drm/i915/display/intel_ddi.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_pch_display.c | 2 ++ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 03cfae46f92f6..fe807c8e793dd 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -145,8 +145,6 @@ static void intel_crt_get_config(struct intel_encoder *encoder, static void hsw_crt_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - lpt_pch_get_config(pipe_config); hsw_ddi_get_config(encoder, pipe_config); @@ -156,8 +154,6 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC); pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder); - - pipe_config->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); } /* Note: The caller is required to filter out dpms modes not supported by the diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1dcfe31e6c6f5..8bbbeec016075 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -321,10 +321,11 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) { int dotclock; + /* CRT dotclock is determined via other means */ if (pipe_config->has_pch_encoder) - dotclock = intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->fdi_m_n); - else if (intel_crtc_has_dp_encoder(pipe_config)) + return; + + if (intel_crtc_has_dp_encoder(pipe_config)) dotclock = intel_dotclock_calculate(pipe_config->port_clock, &pipe_config->dp_m_n); else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp > 24) diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 13685c1929322..98b7b2c050cf8 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -451,4 +451,6 @@ void lpt_pch_get_config(struct intel_crtc_state *crtc_state) FDI_DP_PORT_WIDTH_SHIFT) + 1; ilk_get_fdi_m_n_config(crtc, crtc_state); + + crtc_state->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); } From 976c68f46d7cba02ccc80fbd67a4e9731e23e8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:23 +0300 Subject: [PATCH 014/176] drm/i915: Introduce ilk_pch_disable() and ilk_pch_post_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hoover the remaining open coded PCH modeset sequence bits out from ilk_crtc_disable(). Somewhat annoyingly the enable vs. disable is a bit asymmetric so we need two functions for the disable case. Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-8-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_display.c | 27 ++------------ .../gpu/drm/i915/display/intel_pch_display.c | 37 ++++++++++++++++++- .../gpu/drm/i915/display/intel_pch_display.h | 5 ++- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9bac7418fe3fc..79a7552af7b5e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2287,33 +2287,12 @@ static void ilk_crtc_disable(struct intel_atomic_state *state, ilk_pfit_disable(old_crtc_state); if (old_crtc_state->has_pch_encoder) - ilk_fdi_disable(crtc); + ilk_pch_disable(state, crtc); intel_encoders_post_disable(state, crtc); - if (old_crtc_state->has_pch_encoder) { - ilk_disable_pch_transcoder(crtc); - - if (HAS_PCH_CPT(dev_priv)) { - i915_reg_t reg; - u32 temp; - - /* disable TRANS_DP_CTL */ - reg = TRANS_DP_CTL(pipe); - temp = intel_de_read(dev_priv, reg); - temp &= ~(TRANS_DP_OUTPUT_ENABLE | - TRANS_DP_PORT_SEL_MASK); - temp |= TRANS_DP_PORT_SEL_NONE; - intel_de_write(dev_priv, reg, temp); - - /* disable DPLL_SEL */ - temp = intel_de_read(dev_priv, PCH_DPLL_SEL); - temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); - intel_de_write(dev_priv, PCH_DPLL_SEL, temp); - } - - ilk_fdi_pll_disable(crtc); - } + if (old_crtc_state->has_pch_encoder) + ilk_pch_post_disable(state, crtc); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 98b7b2c050cf8..a4939ac65dfb8 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -179,7 +179,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) pipe_name(pipe)); } -void ilk_disable_pch_transcoder(struct intel_crtc *crtc) +static void ilk_disable_pch_transcoder(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -299,6 +299,41 @@ void ilk_pch_enable(struct intel_atomic_state *state, ilk_enable_pch_transcoder(crtc_state); } +void ilk_pch_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + ilk_fdi_disable(crtc); +} + +void ilk_pch_post_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + + ilk_disable_pch_transcoder(crtc); + + if (HAS_PCH_CPT(dev_priv)) { + i915_reg_t reg; + u32 temp; + + /* disable TRANS_DP_CTL */ + reg = TRANS_DP_CTL(pipe); + temp = intel_de_read(dev_priv, reg); + temp &= ~(TRANS_DP_OUTPUT_ENABLE | + TRANS_DP_PORT_SEL_MASK); + temp |= TRANS_DP_PORT_SEL_NONE; + intel_de_write(dev_priv, reg, temp); + + /* disable DPLL_SEL */ + temp = intel_de_read(dev_priv, PCH_DPLL_SEL); + temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); + intel_de_write(dev_priv, PCH_DPLL_SEL, temp); + } + + ilk_fdi_pll_disable(crtc); +} + static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index 6e834fbebd64a..a983f4d5a3b6c 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -11,9 +11,12 @@ struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; -void ilk_disable_pch_transcoder(struct intel_crtc *crtc); void ilk_pch_enable(struct intel_atomic_state *state, struct intel_crtc *crtc); +void ilk_pch_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void ilk_pch_post_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc); void ilk_pch_get_config(struct intel_crtc_state *crtc_state); void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); From d39ef5d5c076377d41c65b69f8452eada2db724d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:24 +0300 Subject: [PATCH 015/176] drm/i915: Move intel_ddi_fdi_post_disable() to fdi code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reanme intel_ddi_fdi_post_disable() to hsw_fdi_disable() and relocate it next to all the other code dealing with FDI_RX. intel_ddi.c has now been cleansed of FDI_RX. In order to avoid exposing intel_disable_ddi_buf() outside intel_ddi.c we can just open code the DDI_BUF_CTL write. The enable side already has all that stuff open coded so this actually is more symmetric. But we do need to remeber to bring the intel_wait_ddi_buf_idle() call over from inside intel_disable_ddi_buf(). Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-9-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_crt.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 37 +----------------------- drivers/gpu/drm/i915/display/intel_ddi.h | 1 + drivers/gpu/drm/i915/display/intel_fdi.c | 37 ++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fdi.h | 1 + 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index fe807c8e793dd..db27ae2a84063 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -264,7 +264,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state, lpt_disable_pch_transcoder(dev_priv); lpt_disable_iclkip(dev_priv); - intel_ddi_fdi_post_disable(state, encoder, old_crtc_state, old_conn_state); + hsw_fdi_disable(encoder); drm_WARN_ON(&dev_priv->drm, !old_crtc_state->has_pch_encoder); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 8bbbeec016075..ab52eab346fe9 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1939,7 +1939,7 @@ void intel_ddi_enable_clock(struct intel_encoder *encoder, encoder->enable_clock(encoder, crtc_state); } -static void intel_ddi_disable_clock(struct intel_encoder *encoder) +void intel_ddi_disable_clock(struct intel_encoder *encoder) { if (encoder->disable_clock) encoder->disable_clock(encoder); @@ -2867,41 +2867,6 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, intel_tc_port_put_link(dig_port); } -void intel_ddi_fdi_post_disable(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 val; - - /* - * Bspec lists this as both step 13 (before DDI_BUF_CTL disable) - * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN, - * step 13 is the correct place for it. Step 18 is where it was - * originally before the BUN. - */ - val = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); - val &= ~FDI_RX_ENABLE; - intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), val); - - intel_disable_ddi_buf(encoder, old_crtc_state); - intel_ddi_disable_clock(encoder); - - val = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A)); - val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); - val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); - intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), val); - - val = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); - val &= ~FDI_PCDCLK; - intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), val); - - val = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); - val &= ~FDI_RX_PLL_ENABLE; - intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), val); -} - static void trans_port_sync_stop_link_train(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index d6971717ef9c1..6f4551c9d5b7d 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -30,6 +30,7 @@ void intel_ddi_fdi_post_disable(struct intel_atomic_state *state, const struct drm_connector_state *old_conn_state); void intel_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); +void intel_ddi_disable_clock(struct intel_encoder *encoder); void intel_ddi_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct intel_shared_dpll *pll); diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index d1c1600c66cbc..2b5f80f3b4e0c 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -886,6 +886,43 @@ void hsw_fdi_link_train(struct intel_encoder *encoder, DP_TP_CTL_ENABLE); } +void hsw_fdi_disable(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + u32 val; + + /* + * Bspec lists this as both step 13 (before DDI_BUF_CTL disable) + * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN, + * step 13 is the correct place for it. Step 18 is where it was + * originally before the BUN. + */ + val = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); + val &= ~FDI_RX_ENABLE; + intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), val); + + val = intel_de_read(dev_priv, DDI_BUF_CTL(PORT_E)); + val &= ~DDI_BUF_CTL_ENABLE; + intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E), val); + + intel_wait_ddi_buf_idle(dev_priv, PORT_E); + + intel_ddi_disable_clock(encoder); + + val = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A)); + val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); + val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); + intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), val); + + val = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); + val &= ~FDI_PCDCLK; + intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), val); + + val = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A)); + val &= ~FDI_RX_PLL_ENABLE; + intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), val); +} + void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h index 5a361730f80a0..1cdb86172702f 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.h +++ b/drivers/gpu/drm/i915/display/intel_fdi.h @@ -23,6 +23,7 @@ void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state); void intel_fdi_init_hook(struct drm_i915_private *dev_priv); void hsw_fdi_link_train(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); +void hsw_fdi_disable(struct intel_encoder *encoder); void intel_fdi_pll_freq_update(struct drm_i915_private *i915); void intel_fdi_link_train(struct intel_crtc *crtc, From 718cc87e1669dafe65ddd3720a5526c6d7e1705a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 10:16:25 +0300 Subject: [PATCH 016/176] drm/i915: Introduce lpt_pch_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's add lpt_pch_disable() as the counterpart to lpt_pch_enable(). Note that unlike the ilk+ code the fdi_link_train() and fdi_disable() calls are still left directly in intel_crt.c. If we wanted to move those we'd need to add lpt_pch_pre_enable(). But the two fdi direct fdi calls are pretry symmetric so it doesn't seem too bad to just keep them as is. v2: Make lpt_disable_pch_transcoder() static (lkp@intel.com) Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015071625.593-10-ville.syrjala@linux.intel.com Reviewed-by: Dave Airlie --- drivers/gpu/drm/i915/display/intel_crt.c | 5 ++--- drivers/gpu/drm/i915/display/intel_pch_display.c | 12 +++++++++++- drivers/gpu/drm/i915/display/intel_pch_display.h | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index db27ae2a84063..f0f28572dfdc3 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -46,7 +46,6 @@ #include "intel_gmbus.h" #include "intel_hotplug.h" #include "intel_pch_display.h" -#include "intel_pch_refclk.h" /* Here's the desired hotplug mode */ #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \ @@ -247,6 +246,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); intel_crtc_vblank_off(old_crtc_state); @@ -261,8 +261,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state, pch_post_disable_crt(state, encoder, old_crtc_state, old_conn_state); - lpt_disable_pch_transcoder(dev_priv); - lpt_disable_iclkip(dev_priv); + lpt_pch_disable(state, crtc); hsw_fdi_disable(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index a4939ac65dfb8..a55c4bfacd0df 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -434,7 +434,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n"); } -void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) +static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) { u32 val; @@ -470,6 +470,16 @@ void lpt_pch_enable(struct intel_atomic_state *state, lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); } +void lpt_pch_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + lpt_disable_pch_transcoder(dev_priv); + + lpt_disable_iclkip(dev_priv); +} + void lpt_pch_get_config(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index a983f4d5a3b6c..2c387fe3a467c 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -6,7 +6,6 @@ #ifndef _INTEL_PCH_DISPLAY_H_ #define _INTEL_PCH_DISPLAY_H_ -struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; @@ -19,9 +18,10 @@ void ilk_pch_post_disable(struct intel_atomic_state *state, struct intel_crtc *crtc); void ilk_pch_get_config(struct intel_crtc_state *crtc_state); -void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); void lpt_pch_enable(struct intel_atomic_state *state, struct intel_crtc *crtc); +void lpt_pch_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc); void lpt_pch_get_config(struct intel_crtc_state *crtc_state); #endif From b7d5abda8e64fb9cbbd219e667ccb34e4761ce2f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 14 Oct 2021 18:00:59 +0300 Subject: [PATCH 017/176] drm/i915/dp: use new link training delay helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new link training delay helpers, fixing the delays for 128b/132b. For existing 8b/10b functionality, this will cause additional 1-byte DPCD reads for LTTPR delays instead of using the cached values. It's just too complicated to combine generic helpers with local caching in a sensible way. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211014150059.28957-3-jani.nikula@intel.com --- .../drm/i915/display/intel_dp_link_training.c | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 85676c953e0ad..a72f2dc937182 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -683,15 +683,6 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp, return true; } -static void intel_dp_link_training_clock_recovery_delay(struct intel_dp *intel_dp, - enum drm_dp_phy dp_phy) -{ - if (dp_phy == DP_PHY_DPRX) - drm_dp_link_train_clock_recovery_delay(&intel_dp->aux, intel_dp->dpcd); - else - drm_dp_lttpr_link_train_clock_recovery_delay(); -} - static bool intel_dp_adjust_request_changed(const struct intel_crtc_state *crtc_state, const u8 old_link_status[DP_LINK_STATUS_SIZE], const u8 new_link_status[DP_LINK_STATUS_SIZE]) @@ -750,6 +741,11 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE]; bool max_vswing_reached = false; char phy_name[10]; + int delay_us; + + delay_us = drm_dp_read_clock_recovery_delay(&intel_dp->aux, + intel_dp->dpcd, dp_phy, + intel_dp_is_uhbr(crtc_state)); intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name)); @@ -777,7 +773,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp, voltage_tries = 1; for (cr_tries = 0; cr_tries < max_cr_tries; ++cr_tries) { - intel_dp_link_training_clock_recovery_delay(intel_dp, dp_phy); + usleep_range(delay_us, 2 * delay_us); if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy, link_status) < 0) { @@ -895,19 +891,6 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp, return DP_TRAINING_PATTERN_2; } -static void -intel_dp_link_training_channel_equalization_delay(struct intel_dp *intel_dp, - enum drm_dp_phy dp_phy) -{ - if (dp_phy == DP_PHY_DPRX) { - drm_dp_link_train_channel_eq_delay(&intel_dp->aux, intel_dp->dpcd); - } else { - const u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy); - - drm_dp_lttpr_link_train_channel_eq_delay(&intel_dp->aux, phy_caps); - } -} - /* * Perform the link training channel equalization phase on the given DP PHY * using one of training pattern 2, 3 or 4 depending on the source and @@ -925,6 +908,11 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE]; bool channel_eq = false; char phy_name[10]; + int delay_us; + + delay_us = drm_dp_read_channel_eq_delay(&intel_dp->aux, + intel_dp->dpcd, dp_phy, + intel_dp_is_uhbr(crtc_state)); intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name)); @@ -944,8 +932,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp, } for (tries = 0; tries < 5; tries++) { - intel_dp_link_training_channel_equalization_delay(intel_dp, - dp_phy); + usleep_range(delay_us, 2 * delay_us); + if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy, link_status) < 0) { drm_err(&i915->drm, From 4ec5ffc341cecbea060739aea1d53398ac2ec3f8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 12:41:49 +0300 Subject: [PATCH 018/176] drm/i915/dp: Skip the HW readout of DPCD on disabled encoders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reading out the DP encoders' DPCD during booting or resume is only required for enabled encoders: such encoders may be modesetted during the initial commit and the link training this involves depends on an initialized DPCD. For DDI encoders reading out the DPCD is skipped, do the same on pre-DDI platforms. Atm, the first DPCD readout without a sink connected - which is a likely scneario if the encoder is disabled - leaves intel_dp->num_common_rates at 0, which resulted in intel_dp_sync_state()->intel_dp_max_common_rate() in a intel_dp->common_rates[-1] access. This by definition results in an undefined behaviour, though to my best knowledge in all HW/compiler configurations it actually results in accessing the array item type value preceding the array. In this case the preceding value happens to be intel_dp->num_common_rates, which is 0, so this issue - by luck - didn't cause a user visible problem. Nevertheless it's still an undefined behaviour and in CONFIG_UBSAN builds leads to a kernel BUG() (which revealed this problem for us), hence CC:stable. A related problem in case the encoder is enabled but the sink is not connected or the DPCD readout fails is fixed by the next patch. v2: Amend the commit message describing the root cause of the CONFIG_UBSAN BUG(). Fixes: a532cde31de3 ("drm/i915/tc: Fix TypeC port init/resume time sanitization") References: https://gitlab.freedesktop.org/drm/intel/-/issues/4297 Reported-and-tested-by: Mat Jonczyk Cc: Mat Jonczyk Cc: José Roberto de Souza Cc: Jani Nikula Cc: Ville Syrjälä Cc: Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018094154.1407705-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9d8132dd4cc5a..23de500d56b52 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2007,6 +2007,9 @@ void intel_dp_sync_state(struct intel_encoder *encoder, { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + if (!crtc_state) + return; + /* * Don't clobber DPCD if it's been already read out during output * setup (eDP) or detect. From 3f61ef9777c0ab0f03f4af0ed6fd3e5250537a8d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 17:34:17 +0300 Subject: [PATCH 019/176] drm/i915/dp: Ensure sink rate values are always valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atm, there are no sink rate values set for DP (vs. eDP) sinks until the DPCD capabilities are successfully read from the sink. During this time intel_dp->num_common_rates is 0 which can lead to a intel_dp->common_rates[-1] (*) access, which is an undefined behaviour, in the following cases: - In intel_dp_sync_state(), if the encoder is enabled without a sink connected to the encoder's connector (BIOS enabled a monitor, but the user unplugged the monitor until the driver loaded). - In intel_dp_sync_state() if the encoder is enabled with a sink connected, but for some reason the DPCD read has failed. - In intel_dp_compute_link_config() if modesetting a connector without a sink connected on it. - In intel_dp_compute_link_config() if modesetting a connector with a a sink connected on it, but before probing the connector first. To avoid the (*) access in all the above cases, make sure that the sink rate table - and hence the common rate table - is always valid, by setting a default minimum sink rate when registering the connector before anything could use it. I also considered setting all the DP link rates by default, so that modesetting with higher resolution modes also succeeds in the last two cases above. However in case a sink is not connected that would stop working after the first modeset, due to the LT fallback logic. So this would need more work, beyond the scope of this fix. As I mentioned in the previous patch, I don't think the issue this patch fixes is user visible, however it is an undefined behaviour by definition and triggers a BUG() in CONFIG_UBSAN builds, hence CC:stable. v2: Clear the default sink rates, before initializing these for eDP. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4297 References: https://gitlab.freedesktop.org/drm/intel/-/issues/4298 Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018143417.1452632-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 23de500d56b52..9cbe85746fc41 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -120,6 +120,12 @@ bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state) return crtc_state->port_clock >= 1000000; } +static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp) +{ + intel_dp->sink_rates[0] = 162000; + intel_dp->num_sink_rates = 1; +} + /* update sink rates from dpcd */ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) { @@ -2556,6 +2562,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) */ intel_psr_init_dpcd(intel_dp); + /* Clear the default sink rates */ + intel_dp->num_sink_rates = 0; + /* Read the eDP 1.4+ supported link rates. */ if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { __le16 sink_rates[DP_MAX_SUPPORTED_RATES]; @@ -5003,6 +5012,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, } intel_dp_set_source_rates(intel_dp); + intel_dp_set_default_sink_rates(intel_dp); + intel_dp_set_common_rates(intel_dp); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); From 9ad87de4735620ffc555592e8c5f580478fa3ed0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 12:41:51 +0300 Subject: [PATCH 020/176] drm/i915/dp: Ensure max link params are always valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atm until the DPCD for a connector is read the max link rate and lane count params are invalid. If the connector is modeset, in intel_dp_compute_config(), intel_dp_common_len_rate_limit(max_link_rate) will return 0, leading to a intel_dp->common_rates[-1] access. Fix the above by making sure the max link params are always valid. The above access leads to an undefined behaviour by definition, though not causing a user visible problem to my best knowledge, see the previous patch why. Nevertheless it is an undefined behaviour and it triggers a BUG() in CONFIG_UBSAN builds, hence CC:stable. Cc: Ville Syrjälä Cc: Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018094154.1407705-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9cbe85746fc41..0a92c9f4b09e7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1864,6 +1864,12 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, intel_dp->lane_count = lane_count; } +static void intel_dp_reset_max_link_params(struct intel_dp *intel_dp) +{ + intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); + intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); +} + /* Enable backlight PWM and backlight PP control. */ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -2023,8 +2029,7 @@ void intel_dp_sync_state(struct intel_encoder *encoder, if (intel_dp->dpcd[DP_DPCD_REV] == 0) intel_dp_get_dpcd(intel_dp); - intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); - intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); + intel_dp_reset_max_link_params(intel_dp); } bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, @@ -2600,6 +2605,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_sink_rates(intel_dp); intel_dp_set_common_rates(intel_dp); + intel_dp_reset_max_link_params(intel_dp); /* Read the eDP DSC DPCD registers */ if (DISPLAY_VER(dev_priv) >= 10) @@ -4341,12 +4347,7 @@ intel_dp_detect(struct drm_connector *connector, * supports link training fallback params. */ if (intel_dp->reset_link_params || intel_dp->is_mst) { - /* Initial max link lane count */ - intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); - - /* Initial max link rate */ - intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); - + intel_dp_reset_max_link_params(intel_dp); intel_dp->reset_link_params = false; } @@ -5014,6 +5015,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp_set_source_rates(intel_dp); intel_dp_set_default_sink_rates(intel_dp); intel_dp_set_common_rates(intel_dp); + intel_dp_reset_max_link_params(intel_dp); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); From bedcaddadd22da82fc2590569ff81a31045176b1 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 12:41:52 +0300 Subject: [PATCH 021/176] drm/i915/dp: Ensure sink/link max lane count values are always valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print an error if the DPCD sink max lane count is invalid and fix it up. While at it also add an assert that the link max lane count (derived from intel_dp_max_common_lane_count(), potentially reduced by the LT fallback logic) value is also valid. Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018094154.1407705-5-imre.deak@intel.com --- .../drm/i915/display/intel_display_types.h | 2 + drivers/gpu/drm/i915/display/intel_dp.c | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 39e11eaec1a3f..1e42bf901263c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1563,6 +1563,8 @@ struct intel_dp { int num_sink_rates; int sink_rates[DP_MAX_SUPPORTED_RATES]; bool use_rate_select; + /* Max sink lane count as reported by DP_MAX_LANE_COUNT */ + int max_sink_lane_count; /* intersection of source and sink rates */ int num_common_rates; int common_rates[DP_MAX_SUPPORTED_RATES]; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0a92c9f4b09e7..31d23d74157de 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -197,6 +197,35 @@ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) intel_dp->num_sink_rates = i; } +static void intel_dp_set_default_max_sink_lane_count(struct intel_dp *intel_dp) +{ + intel_dp->max_sink_lane_count = 1; +} + +static void intel_dp_set_max_sink_lane_count(struct intel_dp *intel_dp) +{ + struct intel_connector *connector = intel_dp->attached_connector; + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + + intel_dp->max_sink_lane_count = drm_dp_max_lane_count(intel_dp->dpcd); + + switch (intel_dp->max_sink_lane_count) { + case 1: + case 2: + case 4: + return; + } + + drm_err(&dp_to_i915(intel_dp)->drm, + "[CONNECTOR:%d:%s][ENCODER:%d:%s] Invalid DPCD max lane count (%d), using default\n", + connector->base.base.id, connector->base.name, + encoder->base.base.id, encoder->base.name, + intel_dp->max_sink_lane_count); + + intel_dp_set_default_max_sink_lane_count(intel_dp); +} + /* Get length of rates array potentially limited by max_rate. */ static int intel_dp_rate_limit_len(const int *rates, int len, int max_rate) { @@ -230,7 +259,7 @@ static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); int source_max = dig_port->max_lanes; - int sink_max = drm_dp_max_lane_count(intel_dp->dpcd); + int sink_max = intel_dp->max_sink_lane_count; int fia_max = intel_tc_port_fia_max_lane_count(dig_port); int lttpr_max = drm_dp_lttpr_max_lane_count(intel_dp->lttpr_common_caps); @@ -242,7 +271,15 @@ static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp) int intel_dp_max_lane_count(struct intel_dp *intel_dp) { - return intel_dp->max_link_lane_count; + switch (intel_dp->max_link_lane_count) { + case 1: + case 2: + case 4: + return intel_dp->max_link_lane_count; + default: + MISSING_CASE(intel_dp->max_link_lane_count); + return 1; + } } /* @@ -2603,6 +2640,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp->use_rate_select = true; else intel_dp_set_sink_rates(intel_dp); + intel_dp_set_max_sink_lane_count(intel_dp); intel_dp_set_common_rates(intel_dp); intel_dp_reset_max_link_params(intel_dp); @@ -2648,6 +2686,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) drm_dp_is_branch(intel_dp->dpcd)); intel_dp_set_sink_rates(intel_dp); + intel_dp_set_max_sink_lane_count(intel_dp); intel_dp_set_common_rates(intel_dp); } @@ -5014,6 +5053,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp_set_source_rates(intel_dp); intel_dp_set_default_sink_rates(intel_dp); + intel_dp_set_default_max_sink_lane_count(intel_dp); intel_dp_set_common_rates(intel_dp); intel_dp_reset_max_link_params(intel_dp); From caae4fb537d8437b9290d8a1010adfaf174b29e6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 12:41:53 +0300 Subject: [PATCH 022/176] drm/i915/dp: Sanitize sink rate DPCD register values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the DPCD sink rate values read from the sink are invalid, the driver will sanitize this in intel_dp_set_common_rates(), by setting a default 162000 link rate in common rates and printing a WARN(). WARN()s should only be triggered by bugs in the code and not by external factors like the above (an invalid DPCD injected maliciously or read from a buggy monitor). So fixup the invalid DPCD sink rate values already and print an error in this case (since it's still a user visible problem). Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018094154.1407705-6-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 31d23d74157de..647d9dd46684b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -127,7 +127,7 @@ static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp) } /* update sink rates from dpcd */ -static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) +static void intel_dp_set_dpcd_sink_rates(struct intel_dp *intel_dp) { static const int dp_rates[] = { 162000, 270000, 540000, 810000 @@ -197,6 +197,25 @@ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) intel_dp->num_sink_rates = i; } +static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) +{ + struct intel_connector *connector = intel_dp->attached_connector; + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + + intel_dp_set_dpcd_sink_rates(intel_dp); + + if (intel_dp->num_sink_rates) + return; + + drm_err(&dp_to_i915(intel_dp)->drm, + "[CONNECTOR:%d:%s][ENCODER:%d:%s] Invalid DPCD with no link rates, using defaults\n", + connector->base.base.id, connector->base.name, + encoder->base.base.id, encoder->base.name); + + intel_dp_set_default_sink_rates(intel_dp); +} + static void intel_dp_set_default_max_sink_lane_count(struct intel_dp *intel_dp) { intel_dp->max_sink_lane_count = 1; From ce679dea955e1b6670a8d92b8ac4c17b22db3fa0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 12:41:54 +0300 Subject: [PATCH 023/176] drm/i915/dp: Sanitize link common rate array lookups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an assert that lookups from the intel_dp->common_rates[] array are always valid. Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018094154.1407705-7-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 33 ++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 647d9dd46684b..f5dc2126d1400 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -267,10 +267,19 @@ static int intel_dp_common_len_rate_limit(const struct intel_dp *intel_dp, intel_dp->num_common_rates, max_rate); } +static int intel_dp_common_rate(struct intel_dp *intel_dp, int index) +{ + if (drm_WARN_ON(&dp_to_i915(intel_dp)->drm, + index < 0 || index >= intel_dp->num_common_rates)) + return 162000; + + return intel_dp->common_rates[index]; +} + /* Theoretical max between source and sink */ static int intel_dp_max_common_rate(struct intel_dp *intel_dp) { - return intel_dp->common_rates[intel_dp->num_common_rates - 1]; + return intel_dp_common_rate(intel_dp, intel_dp->num_common_rates - 1); } /* Theoretical max between source and sink */ @@ -610,13 +619,13 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, if (index > 0) { if (intel_dp_is_edp(intel_dp) && !intel_dp_can_link_train_fallback_for_edp(intel_dp, - intel_dp->common_rates[index - 1], + intel_dp_common_rate(intel_dp, index - 1), lane_count)) { drm_dbg_kms(&i915->drm, "Retrying Link training for eDP with same parameters\n"); return 0; } - intel_dp->max_link_rate = intel_dp->common_rates[index - 1]; + intel_dp->max_link_rate = intel_dp_common_rate(intel_dp, index - 1); intel_dp->max_link_lane_count = lane_count; } else if (lane_count > 1) { if (intel_dp_is_edp(intel_dp) && @@ -1056,14 +1065,11 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) int intel_dp_max_link_rate(struct intel_dp *intel_dp) { - struct drm_i915_private *i915 = dp_to_i915(intel_dp); int len; len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->max_link_rate); - if (drm_WARN_ON(&i915->drm, len <= 0)) - return 162000; - return intel_dp->common_rates[len - 1]; + return intel_dp_common_rate(intel_dp, len - 1); } int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) @@ -1260,7 +1266,7 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp, output_bpp); for (i = 0; i < intel_dp->num_common_rates; i++) { - link_rate = intel_dp->common_rates[i]; + link_rate = intel_dp_common_rate(intel_dp, i); if (link_rate < limits->min_rate || link_rate > limits->max_rate) continue; @@ -1508,17 +1514,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct link_config_limits limits; - int common_len; int ret; - common_len = intel_dp_common_len_rate_limit(intel_dp, - intel_dp->max_link_rate); - - /* No common link rates between source and sink */ - drm_WARN_ON(encoder->base.dev, common_len <= 0); - - limits.min_rate = intel_dp->common_rates[0]; - limits.max_rate = intel_dp->common_rates[common_len - 1]; + limits.min_rate = intel_dp_common_rate(intel_dp, 0); + limits.max_rate = intel_dp_max_link_rate(intel_dp); limits.min_lane_count = 1; limits.max_lane_count = intel_dp_max_lane_count(intel_dp); From 808b79eb8165d4dbd5e731f98a4f5f4a0817ee4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Tue, 19 Oct 2021 17:35:57 -0700 Subject: [PATCH 024/176] drm/i915/display: Rename POWER_DOMAIN_DPLL_DC_OFF to POWER_DOMAIN_DC_OFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This power domain to disable DC states will be used in places outside of DPLL, so making the name more generic. Cc: Radhakrishna Sripada Cc: Imre Deak Signed-off-by: José Roberto de Souza Reviewed-by: Caz Yokoyama Link: https://patchwork.freedesktop.org/patch/msgid/20211020003558.222198-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 6 +++--- drivers/gpu/drm/i915/display/intel_display_power.h | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index d88da0d0f05ac..6637760d24e0c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -155,8 +155,8 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) return "MODESET"; case POWER_DOMAIN_GT_IRQ: return "GT_IRQ"; - case POWER_DOMAIN_DPLL_DC_OFF: - return "DPLL_DC_OFF"; + case POWER_DOMAIN_DC_OFF: + return "DC_OFF"; case POWER_DOMAIN_TC_COLD_OFF: return "TC_COLD_OFF"; default: @@ -2803,7 +2803,7 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915, ICL_PW_2_POWER_DOMAINS | \ BIT_ULL(POWER_DOMAIN_MODESET) | \ BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_DPLL_DC_OFF) | \ + BIT_ULL(POWER_DOMAIN_DC_OFF) | \ BIT_ULL(POWER_DOMAIN_INIT)) #define ICL_DDI_IO_A_POWER_DOMAINS ( \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 0612e4b6e3c81..d54b7574ed373 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -117,7 +117,7 @@ enum intel_display_power_domain { POWER_DOMAIN_GMBUS, POWER_DOMAIN_MODESET, POWER_DOMAIN_GT_IRQ, - POWER_DOMAIN_DPLL_DC_OFF, + POWER_DOMAIN_DC_OFF, POWER_DOMAIN_TC_COLD_OFF, POWER_DOMAIN_INIT, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index ca69b67bbc231..fc8fda77483ab 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3741,7 +3741,7 @@ static void combo_pll_enable(struct drm_i915_private *dev_priv, * domain. */ pll->wakeref = intel_display_power_get(dev_priv, - POWER_DOMAIN_DPLL_DC_OFF); + POWER_DOMAIN_DC_OFF); } icl_pll_power_enable(dev_priv, pll, enable_reg); @@ -3848,7 +3848,7 @@ static void combo_pll_disable(struct drm_i915_private *dev_priv, if (IS_JSL_EHL(dev_priv) && pll->info->id == DPLL_ID_EHL_DPLL4) - intel_display_power_put(dev_priv, POWER_DOMAIN_DPLL_DC_OFF, + intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, pll->wakeref); } @@ -4232,7 +4232,7 @@ static void readout_dpll_hw_state(struct drm_i915_private *i915, if (IS_JSL_EHL(i915) && pll->on && pll->info->id == DPLL_ID_EHL_DPLL4) { pll->wakeref = intel_display_power_get(i915, - POWER_DOMAIN_DPLL_DC_OFF); + POWER_DOMAIN_DC_OFF); } pll->state.pipe_mask = 0; From 1af10a97b3a629f5f5b361f1870070c1d6e0308b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Tue, 19 Oct 2021 17:35:58 -0700 Subject: [PATCH 025/176] drm/i915/display: Add warn_on in intel_psr_pause() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now the only user of psr_pause/resume is intel_cdclk but additional users will be added in the future and we may need do reference counting for PSR pause and resume, for now only adding a warn_on so this cases do not go unnoticed. Cc: Mika Kahola Cc: Jouni Hogander Cc: Radhakrishna Sripada Signed-off-by: José Roberto de Souza Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20211020003558.222198-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 7a205fd5023bb..49c2dfbd40554 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1346,6 +1346,7 @@ void intel_psr_disable(struct intel_dp *intel_dp, */ void intel_psr_pause(struct intel_dp *intel_dp) { + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct intel_psr *psr = &intel_dp->psr; if (!CAN_PSR(intel_dp)) @@ -1358,6 +1359,9 @@ void intel_psr_pause(struct intel_dp *intel_dp) return; } + /* If we ever hit this, we will need to add refcount to pause/resume */ + drm_WARN_ON(&dev_priv->drm, psr->paused); + intel_psr_exit(intel_dp); intel_psr_wait_exit_locked(intel_dp); psr->paused = true; From 171c555c2c2664a250cd35680c34c31a6d233dc7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 19 Oct 2021 14:43:34 +0300 Subject: [PATCH 026/176] Revert "drm/i915/bios: gracefully disable dual eDP for now" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 05734ca2a8f76c9eb3890b3c9dfc3467f03105c1. It's not graceful, instead it leads to boot time warning splats in the case it is supposed to handle gracefully. Apparently the BIOS/GOP enabling the port we end up skipping leads to state readout problems. Back to the drawing board. References: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21255/bat-adlp-4/boot0.txt Fixes: 05734ca2a8f7 ("drm/i915/bios: gracefully disable dual eDP for now") Cc: José Roberto de Souza Cc: Uma Shankar Cc: Ville Syrjälä Cc: Swati Sharma Reviewed-by: José Roberto de Souza Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211019114334.24643-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 47 ----------------------- 1 file changed, 47 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index b99907c656bbf..f9776ca85de3e 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1930,50 +1930,6 @@ static int _intel_bios_max_tmds_clock(const struct intel_bios_encoder_data *devd } } -static enum port get_edp_port(struct drm_i915_private *i915) -{ - const struct intel_bios_encoder_data *devdata; - enum port port; - - for_each_port(port) { - devdata = i915->vbt.ports[port]; - - if (devdata && intel_bios_encoder_supports_edp(devdata)) - return port; - } - - return PORT_NONE; -} - -/* - * FIXME: The power sequencer and backlight code currently do not support more - * than one set registers, at least not on anything other than VLV/CHV. It will - * clobber the registers. As a temporary workaround, gracefully prevent more - * than one eDP from being registered. - */ -static void sanitize_dual_edp(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child = &devdata->child; - enum port p; - - /* CHV might not clobber PPS registers. */ - if (IS_CHERRYVIEW(i915)) - return; - - p = get_edp_port(i915); - if (p == PORT_NONE) - return; - - drm_dbg_kms(&i915->drm, "both ports %c and %c configured as eDP, " - "disabling port %c eDP\n", port_name(p), port_name(port), - port_name(port)); - - child->device_type &= ~DEVICE_TYPE_DISPLAYPORT_OUTPUT; - child->device_type &= ~DEVICE_TYPE_INTERNAL_CONNECTOR; -} - static bool is_port_valid(struct drm_i915_private *i915, enum port port) { /* @@ -2031,9 +1987,6 @@ static void parse_ddi_port(struct drm_i915_private *i915, supports_typec_usb, supports_tbt, devdata->dsc != NULL); - if (is_edp) - sanitize_dual_edp(devdata, port); - if (is_dvi) sanitize_ddc_pin(devdata, port); From e2b8329432b880f3821f85e1253a9b6b9d714a86 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:28 +0300 Subject: [PATCH 027/176] drm/i915: Add a table with a descriptor for all i915 modifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a table describing all the framebuffer modifiers used by i915 at one place. This has the benefit of deduplicating the listing of supported modifiers for each platform and checking the support of these modifiers on a given plane. This also simplifies in a similar way getting some attribute for a modifier, for instance checking if the modifier is a CCS modifier type. While at it drop the cursor plane filtering from skl_plane_has_rc_ccs(), as the cursor plane is registered with DRM core elsewhere. v1: Unchanged. v2: - Keep the plane caps calculation in the plane code and pass an enum with these caps to intel_fb_get_modifiers(). (Ville) - Get the modifiers calling intel_fb_get_modifiers() in i9xx_plane.c as well. v3: - s/.id/.modifier/ (Ville) - Keep modifier_desc vs. plane_cap filter conditions consistent. (Ville) - Drop redundant cursor plane check from skl_plane_has_rc_ccs(). (Ville) - Use from, until display version fields in modifier_desc instead of a mask. (Jani) - Unexport struct intel_modifier_desc, separate its decl and init. (Jani) - Remove enum pipe, plane_id forward decls from intel_fb.h, which are not needed after v2. v4: - Reuse IS_DISPLAY_VER() instead of open-coding it. (Jani) - Preserve the current modifier order exposed to user space. (Ville) v5: Use }, { on one line to seperate the descriptor array elements. (Jani) Cc: Ville Syrjälä Cc: Juha-Pekka Heikkila Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila (v3) Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/i9xx_plane.c | 30 +-- drivers/gpu/drm/i915/display/intel_cursor.c | 19 +- .../drm/i915/display/intel_display_types.h | 1 - drivers/gpu/drm/i915/display/intel_fb.c | 144 ++++++++++++++ drivers/gpu/drm/i915/display/intel_fb.h | 13 ++ drivers/gpu/drm/i915/display/intel_sprite.c | 35 +--- drivers/gpu/drm/i915/display/skl_scaler.c | 1 + .../drm/i915/display/skl_universal_plane.c | 178 +++++------------- 8 files changed, 237 insertions(+), 184 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index b1439ba78f67b..a939accff7ee2 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -60,22 +60,11 @@ static const u32 vlv_primary_formats[] = { DRM_FORMAT_XBGR16161616F, }; -static const u64 i9xx_format_modifiers[] = { - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: + if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) return false; - } switch (format) { case DRM_FORMAT_C8: @@ -92,13 +81,8 @@ static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, static bool i965_plane_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: + if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) return false; - } switch (format) { case DRM_FORMAT_C8: @@ -768,6 +752,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) struct intel_plane *plane; const struct drm_plane_funcs *plane_funcs; unsigned int supported_rotations; + const u64 *modifiers; const u32 *formats; int num_formats; int ret, zpos; @@ -875,21 +860,26 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->disable_flip_done = ilk_primary_disable_flip_done; } + modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_TILING); + if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, formats, num_formats, - i9xx_format_modifiers, + modifiers, DRM_PLANE_TYPE_PRIMARY, "primary %c", pipe_name(pipe)); else ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, formats, num_formats, - i9xx_format_modifiers, + modifiers, DRM_PLANE_TYPE_PRIMARY, "plane %c", plane_name(plane->i9xx_plane)); + + kfree(modifiers); + if (ret) goto fail; diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 11842f2126130..6b08d8bca5cd4 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -28,11 +28,6 @@ static const u32 intel_cursor_formats[] = { DRM_FORMAT_ARGB8888, }; -static const u64 cursor_format_modifiers[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - static u32 intel_cursor_base(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = @@ -605,8 +600,10 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane, static bool intel_cursor_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - return modifier == DRM_FORMAT_MOD_LINEAR && - format == DRM_FORMAT_ARGB8888; + if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) + return false; + + return format == DRM_FORMAT_ARGB8888; } static int @@ -754,6 +751,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, { struct intel_plane *cursor; int ret, zpos; + u64 *modifiers; cursor = intel_plane_alloc(); if (IS_ERR(cursor)) @@ -784,13 +782,18 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv)) cursor->cursor.size = ~0; + modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_NO_CAPS); + ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base, 0, &intel_cursor_plane_funcs, intel_cursor_formats, ARRAY_SIZE(intel_cursor_formats), - cursor_format_modifiers, + modifiers, DRM_PLANE_TYPE_CURSOR, "cursor %c", pipe_name(pipe)); + + kfree(modifiers); + if (ret) goto fail; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 1e42bf901263c..a4930a56bfa82 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1336,7 +1336,6 @@ struct intel_plane { enum plane_id id; enum pipe pipe; bool has_fbc; - bool has_ccs; bool need_async_flip_disable_wa; u32 frontbuffer_bit; diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index fa1f375e696bf..d42b7a1297af7 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -13,6 +13,150 @@ #define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a)) +struct intel_modifier_desc { + u64 modifier; + struct { + u8 from; + u8 until; + } display_ver; +#define DISPLAY_VER_ALL { 0, -1 } + + u8 is_linear:1; + + struct { +#define INTEL_CCS_RC BIT(0) +#define INTEL_CCS_RC_CC BIT(1) +#define INTEL_CCS_MC BIT(2) + +#define INTEL_CCS_ANY (INTEL_CCS_RC | INTEL_CCS_RC_CC | INTEL_CCS_MC) + u8 type:3; + } ccs; +}; + +static const struct intel_modifier_desc intel_modifiers[] = { + { + .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, + .display_ver = { 12, 13 }, + + .ccs.type = INTEL_CCS_MC, + }, { + .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, + .display_ver = { 12, 13 }, + + .ccs.type = INTEL_CCS_RC, + }, { + .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, + .display_ver = { 12, 13 }, + + .ccs.type = INTEL_CCS_RC_CC, + }, { + .modifier = I915_FORMAT_MOD_Yf_TILED_CCS, + .display_ver = { 9, 11 }, + + .ccs.type = INTEL_CCS_RC, + }, { + .modifier = I915_FORMAT_MOD_Y_TILED_CCS, + .display_ver = { 9, 11 }, + + .ccs.type = INTEL_CCS_RC, + }, { + .modifier = I915_FORMAT_MOD_Yf_TILED, + .display_ver = { 9, 11 }, + }, { + .modifier = I915_FORMAT_MOD_Y_TILED, + .display_ver = { 9, 13 }, + }, { + .modifier = I915_FORMAT_MOD_X_TILED, + .display_ver = DISPLAY_VER_ALL, + }, { + .modifier = DRM_FORMAT_MOD_LINEAR, + .display_ver = DISPLAY_VER_ALL, + + .is_linear = true, + }, +}; + +static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_type) +{ + return md->ccs.type & ccs_type; +} + +static bool plane_has_modifier(struct drm_i915_private *i915, + enum intel_plane_caps plane_caps, + const struct intel_modifier_desc *md) +{ + if (!IS_DISPLAY_VER(i915, md->display_ver.from, md->display_ver.until)) + return false; + + if (!md->is_linear && + !(plane_caps & PLANE_HAS_TILING)) + return false; + + if (is_ccs_type_modifier(md, INTEL_CCS_RC | INTEL_CCS_RC_CC) && + !(plane_caps & PLANE_HAS_CCS_RC)) + return false; + + if (is_ccs_type_modifier(md, INTEL_CCS_MC) && + !(plane_caps & PLANE_HAS_CCS_MC)) + return false; + + return true; +} + +/** + * intel_fb_plane_get_modifiers: Get the modifiers for the given platform and plane capabilities + * @i915: i915 device instance + * @plane_caps: capabilities for the plane the modifiers are queried for + * + * Returns: + * Returns the list of modifiers allowed by the @i915 platform and @plane_caps. + * The caller must free the returned buffer. + */ +u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, + enum intel_plane_caps plane_caps) +{ + u64 *list, *p; + int count = 1; /* +1 for invalid modifier terminator */ + int i; + + for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) { + if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i])) + count++; + } + + list = kmalloc_array(count, sizeof(*list), GFP_KERNEL); + if (drm_WARN_ON(&i915->drm, !list)) + return NULL; + + p = list; + for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) { + if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i])) + *p++ = intel_modifiers[i].modifier; + } + *p++ = DRM_FORMAT_MOD_INVALID; + + return list; +} + +/** + * intel_fb_plane_supports_modifier: Determine if a modifier is supported by the given plane + * @plane: Plane to check the modifier support for + * @modifier: The modifier to check the support for + * + * Returns: + * %true if the @modifier is supported on @plane. + */ +bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier) +{ + int i; + + for (i = 0; i < plane->base.modifier_count; i++) + if (plane->base.modifiers[i] == modifier) + return true; + + return false; +} + bool is_ccs_plane(const struct drm_framebuffer *fb, int plane) { if (!is_ccs_modifier(fb->modifier)) diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 1cbdd84502bdd..0f77e81e69d29 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -6,6 +6,7 @@ #ifndef __INTEL_FB_H__ #define __INTEL_FB_H__ +#include #include struct drm_device; @@ -16,13 +17,25 @@ struct drm_i915_private; struct drm_mode_fb_cmd2; struct intel_fb_view; struct intel_framebuffer; +struct intel_plane; struct intel_plane_state; +enum intel_plane_caps { + PLANE_HAS_NO_CAPS = 0, + PLANE_HAS_TILING = BIT(0), + PLANE_HAS_CCS_RC = BIT(1), + PLANE_HAS_CCS_MC = BIT(2), +}; + bool is_ccs_plane(const struct drm_framebuffer *fb, int plane); bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane); bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane); bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane); +u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, + enum intel_plane_caps plane_caps); +bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier); + bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane); int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 08116f41da26a..2f4f47ab9da03 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -45,6 +45,7 @@ #include "intel_atomic_plane.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_fb.h" #include "intel_frontbuffer.h" #include "intel_sprite.h" #include "i9xx_plane.h" @@ -1575,12 +1576,6 @@ static const u32 g4x_plane_formats[] = { DRM_FORMAT_VYUY, }; -static const u64 i9xx_plane_format_modifiers[] = { - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - static const u32 snb_plane_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, @@ -1629,13 +1624,8 @@ static const u32 chv_pipe_b_sprite_formats[] = { static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: + if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) return false; - } switch (format) { case DRM_FORMAT_XRGB8888: @@ -1655,13 +1645,8 @@ static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane, static bool snb_sprite_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: + if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) return false; - } switch (format) { case DRM_FORMAT_XRGB8888: @@ -1686,13 +1671,8 @@ static bool snb_sprite_format_mod_supported(struct drm_plane *_plane, static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: + if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) return false; - } switch (format) { case DRM_FORMAT_C8: @@ -1776,7 +1756,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, formats = vlv_plane_formats; num_formats = ARRAY_SIZE(vlv_plane_formats); } - modifiers = i9xx_plane_format_modifiers; plane_funcs = &vlv_sprite_funcs; } else if (DISPLAY_VER(dev_priv) >= 7) { @@ -1795,7 +1774,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, formats = snb_plane_formats; num_formats = ARRAY_SIZE(snb_plane_formats); - modifiers = i9xx_plane_format_modifiers; plane_funcs = &snb_sprite_funcs; } else { @@ -1806,7 +1784,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->max_stride = g4x_sprite_max_stride; plane->min_cdclk = g4x_sprite_min_cdclk; - modifiers = i9xx_plane_format_modifiers; if (IS_SANDYBRIDGE(dev_priv)) { formats = snb_plane_formats; num_formats = ARRAY_SIZE(snb_plane_formats); @@ -1833,11 +1810,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->id = PLANE_SPRITE0 + sprite; plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); + modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_TILING); + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, formats, num_formats, modifiers, DRM_PLANE_TYPE_OVERLAY, "sprite %c", sprite_name(pipe, sprite)); + kfree(modifiers); + if (ret) goto fail; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 37eabeff8197f..c2e94118566b6 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -4,6 +4,7 @@ */ #include "intel_de.h" #include "intel_display_types.h" +#include "intel_fb.h" #include "skl_scaler.h" #include "skl_universal_plane.h" diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 7444b88829ea7..7ee2114e420b7 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -163,50 +163,6 @@ static const u32 icl_hdr_plane_formats[] = { DRM_FORMAT_XVYU16161616, }; -static const u64 skl_plane_format_modifiers_noccs[] = { - I915_FORMAT_MOD_Yf_TILED, - I915_FORMAT_MOD_Y_TILED, - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - -static const u64 skl_plane_format_modifiers_ccs[] = { - I915_FORMAT_MOD_Yf_TILED_CCS, - I915_FORMAT_MOD_Y_TILED_CCS, - I915_FORMAT_MOD_Yf_TILED, - I915_FORMAT_MOD_Y_TILED, - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - -static const u64 gen12_plane_format_modifiers_mc_ccs[] = { - I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, - I915_FORMAT_MOD_Y_TILED, - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - -static const u64 gen12_plane_format_modifiers_rc_ccs[] = { - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, - I915_FORMAT_MOD_Y_TILED, - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - -static const u64 adlp_step_a_plane_format_modifiers[] = { - I915_FORMAT_MOD_Y_TILED, - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) { switch (format) { @@ -1882,42 +1838,13 @@ static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv, } } -static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, - enum pipe pipe, enum plane_id plane_id) -{ - if (plane_id == PLANE_CURSOR) - return false; - - if (DISPLAY_VER(dev_priv) >= 11) - return true; - - if (IS_GEMINILAKE(dev_priv)) - return pipe != PIPE_C; - - return pipe != PIPE_C && - (plane_id == PLANE_PRIMARY || - plane_id == PLANE_SPRITE0); -} - static bool skl_plane_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { struct intel_plane *plane = to_intel_plane(_plane); - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - break; - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - if (!plane->has_ccs) - return false; - break; - default: + if (!intel_fb_plane_supports_modifier(plane, modifier)) return false; - } switch (format) { case DRM_FORMAT_XRGB8888: @@ -1965,45 +1892,13 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, } } -static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv, - enum plane_id plane_id) -{ - /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */ - if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) || - IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_D0)) - return false; - - /* Wa_22011186057 */ - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) - return false; - - return plane_id < PLANE_SPRITE4; -} - static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, u32 format, u64 modifier) { - struct drm_i915_private *dev_priv = to_i915(_plane->dev); struct intel_plane *plane = to_intel_plane(_plane); - switch (modifier) { - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id)) - return false; - fallthrough; - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - case I915_FORMAT_MOD_Y_TILED: - break; - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: - /* Wa_22011186057 */ - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) - return false; - break; - default: + if (!intel_fb_plane_supports_modifier(plane, modifier)) return false; - } switch (format) { case DRM_FORMAT_XRGB8888: @@ -2051,18 +1946,6 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, } } -static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv, - enum plane_id plane_id) -{ - /* Wa_22011186057 */ - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) - return adlp_step_a_plane_format_modifiers; - else if (gen12_plane_supports_mc_ccs(dev_priv, plane_id)) - return gen12_plane_format_modifiers_mc_ccs; - else - return gen12_plane_format_modifiers_rc_ccs; -} - static const struct drm_plane_funcs skl_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -2103,6 +1986,39 @@ skl_plane_disable_flip_done(struct intel_plane *plane) spin_unlock_irq(&i915->irq_lock); } +static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, + enum pipe pipe, enum plane_id plane_id) +{ + /* Wa_22011186057 */ + if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) + return false; + + if (DISPLAY_VER(i915) >= 11) + return true; + + if (IS_GEMINILAKE(i915)) + return pipe != PIPE_C; + + return pipe != PIPE_C && + (plane_id == PLANE_PRIMARY || + plane_id == PLANE_SPRITE0); +} + +static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, + enum plane_id plane_id) +{ + /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */ + if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || + IS_TGL_DISPLAY_STEP(i915, STEP_A0, STEP_D0)) + return false; + + /* Wa_22011186057 */ + if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) + return false; + + return plane_id < PLANE_SPRITE4; +} + struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id) @@ -2110,6 +2026,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, const struct drm_plane_funcs *plane_funcs; struct intel_plane *plane; enum drm_plane_type plane_type; + enum intel_plane_caps plane_caps; unsigned int supported_rotations; unsigned int supported_csc; const u64 *modifiers; @@ -2171,29 +2088,34 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, formats = skl_get_plane_formats(dev_priv, pipe, plane_id, &num_formats); - plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id); - if (DISPLAY_VER(dev_priv) >= 12) { - modifiers = gen12_get_plane_modifiers(dev_priv, plane_id); + if (DISPLAY_VER(dev_priv) >= 12) plane_funcs = &gen12_plane_funcs; - } else { - if (plane->has_ccs) - modifiers = skl_plane_format_modifiers_ccs; - else - modifiers = skl_plane_format_modifiers_noccs; + else plane_funcs = &skl_plane_funcs; - } if (plane_id == PLANE_PRIMARY) plane_type = DRM_PLANE_TYPE_PRIMARY; else plane_type = DRM_PLANE_TYPE_OVERLAY; + plane_caps = PLANE_HAS_TILING; + if (skl_plane_has_rc_ccs(dev_priv, pipe, plane_id)) + plane_caps |= PLANE_HAS_CCS_RC; + + if (gen12_plane_has_mc_ccs(dev_priv, plane_id)) + plane_caps |= PLANE_HAS_CCS_MC; + + modifiers = intel_fb_plane_get_modifiers(dev_priv, plane_caps); + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, formats, num_formats, modifiers, plane_type, "plane %d%c", plane_id + 1, pipe_name(pipe)); + + kfree(modifiers); + if (ret) goto fail; From 672d07517e728acf15c1e39c3dfb7052000b434e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:29 +0300 Subject: [PATCH 028/176] drm/i915: Move intel_get_format_info() to intel_fb.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the function retrieving the format override information for a given format/modifier to intel_fb.c. We can store a pointer to the format list in each modifier's descriptor instead of the corresponding switch/case logic, avoiding the listing of the modifiers twice. v1: Unchanged. v2: Handle invalid modifiers in intel_fb_get_format_info() passed from userspace. (CI/igt_kms_addfb_basic/addfb25-bad-modifier) v3: Move lookup_modifier() to the next patch, where it's first used. Cc: Juha-Pekka Heikkila Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 132 +--------------- drivers/gpu/drm/i915/display/intel_fb.c | 153 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fb.h | 3 + 3 files changed, 157 insertions(+), 131 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 79a7552af7b5e..86333c0cd7937 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -669,136 +669,6 @@ void intel_add_fb_offsets(int *x, int *y, *y += state->view.color_plane[color_plane].y; } -/* - * From the Sky Lake PRM: - * "The Color Control Surface (CCS) contains the compression status of - * the cache-line pairs. The compression state of the cache-line pair - * is specified by 2 bits in the CCS. Each CCS cache-line represents - * an area on the main surface of 16 x16 sets of 128 byte Y-tiled - * cache-line-pairs. CCS is always Y tiled." - * - * Since cache line pairs refers to horizontally adjacent cache lines, - * each cache line in the CCS corresponds to an area of 32x16 cache - * lines on the main surface. Since each pixel is 4 bytes, this gives - * us a ratio of one byte in the CCS for each 8x16 pixels in the - * main surface. - */ -static const struct drm_format_info skl_ccs_formats[] = { - { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, - .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, - { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, - .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, - { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, - .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, - { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, - .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, -}; - -/* - * Gen-12 compression uses 4 bits of CCS data for each cache line pair in the - * main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles - * in the main surface. With 4 byte pixels and each Y-tile having dimensions of - * 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in - * the main surface. - */ -static const struct drm_format_info gen12_ccs_formats[] = { - { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, - .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 1, .vsub = 1, }, - { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, - .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 1, .vsub = 1, }, - { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, - .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 1, .vsub = 1, .has_alpha = true }, - { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, - .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 1, .vsub = 1, .has_alpha = true }, - { .format = DRM_FORMAT_YUYV, .num_planes = 2, - .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 2, .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_YVYU, .num_planes = 2, - .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 2, .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_UYVY, .num_planes = 2, - .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 2, .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_VYUY, .num_planes = 2, - .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 2, .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_XYUV8888, .num_planes = 2, - .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, - .hsub = 1, .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_NV12, .num_planes = 4, - .char_per_block = { 1, 2, 1, 1 }, .block_w = { 1, 1, 4, 4 }, .block_h = { 1, 1, 1, 1 }, - .hsub = 2, .vsub = 2, .is_yuv = true }, - { .format = DRM_FORMAT_P010, .num_planes = 4, - .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, - .hsub = 2, .vsub = 2, .is_yuv = true }, - { .format = DRM_FORMAT_P012, .num_planes = 4, - .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, - .hsub = 2, .vsub = 2, .is_yuv = true }, - { .format = DRM_FORMAT_P016, .num_planes = 4, - .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, - .hsub = 2, .vsub = 2, .is_yuv = true }, -}; - -/* - * Same as gen12_ccs_formats[] above, but with additional surface used - * to pass Clear Color information in plane 2 with 64 bits of data. - */ -static const struct drm_format_info gen12_ccs_cc_formats[] = { - { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3, - .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, - .hsub = 1, .vsub = 1, }, - { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3, - .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, - .hsub = 1, .vsub = 1, }, - { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3, - .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, - .hsub = 1, .vsub = 1, .has_alpha = true }, - { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3, - .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, - .hsub = 1, .vsub = 1, .has_alpha = true }, -}; - -static const struct drm_format_info * -lookup_format_info(const struct drm_format_info formats[], - int num_formats, u32 format) -{ - int i; - - for (i = 0; i < num_formats; i++) { - if (formats[i].format == format) - return &formats[i]; - } - - return NULL; -} - -static const struct drm_format_info * -intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd) -{ - switch (cmd->modifier[0]) { - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - return lookup_format_info(skl_ccs_formats, - ARRAY_SIZE(skl_ccs_formats), - cmd->pixel_format); - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - return lookup_format_info(gen12_ccs_formats, - ARRAY_SIZE(gen12_ccs_formats), - cmd->pixel_format); - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: - return lookup_format_info(gen12_ccs_cc_formats, - ARRAY_SIZE(gen12_ccs_cc_formats), - cmd->pixel_format); - default: - return NULL; - } -} - u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, u32 pixel_format, u64 modifier) { @@ -9538,7 +9408,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_create = intel_user_framebuffer_create, - .get_format_info = intel_get_format_info, + .get_format_info = intel_fb_get_format_info, .output_poll_changed = intel_fbdev_output_poll_changed, .mode_valid = intel_mode_valid, .atomic_check = intel_atomic_check, diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index d42b7a1297af7..42919d22a035b 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -13,6 +13,99 @@ #define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a)) +/* + * From the Sky Lake PRM: + * "The Color Control Surface (CCS) contains the compression status of + * the cache-line pairs. The compression state of the cache-line pair + * is specified by 2 bits in the CCS. Each CCS cache-line represents + * an area on the main surface of 16 x16 sets of 128 byte Y-tiled + * cache-line-pairs. CCS is always Y tiled." + * + * Since cache line pairs refers to horizontally adjacent cache lines, + * each cache line in the CCS corresponds to an area of 32x16 cache + * lines on the main surface. Since each pixel is 4 bytes, this gives + * us a ratio of one byte in the CCS for each 8x16 pixels in the + * main surface. + */ +static const struct drm_format_info skl_ccs_formats[] = { + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, + .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, + .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, + .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, + .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, +}; + +/* + * Gen-12 compression uses 4 bits of CCS data for each cache line pair in the + * main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles + * in the main surface. With 4 byte pixels and each Y-tile having dimensions of + * 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in + * the main surface. + */ +static const struct drm_format_info gen12_ccs_formats[] = { + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, .has_alpha = true }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, .has_alpha = true }, + { .format = DRM_FORMAT_YUYV, .num_planes = 2, + .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 2, .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_YVYU, .num_planes = 2, + .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 2, .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_UYVY, .num_planes = 2, + .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 2, .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_VYUY, .num_planes = 2, + .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 2, .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_XYUV8888, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_NV12, .num_planes = 4, + .char_per_block = { 1, 2, 1, 1 }, .block_w = { 1, 1, 4, 4 }, .block_h = { 1, 1, 1, 1 }, + .hsub = 2, .vsub = 2, .is_yuv = true }, + { .format = DRM_FORMAT_P010, .num_planes = 4, + .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, + .hsub = 2, .vsub = 2, .is_yuv = true }, + { .format = DRM_FORMAT_P012, .num_planes = 4, + .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, + .hsub = 2, .vsub = 2, .is_yuv = true }, + { .format = DRM_FORMAT_P016, .num_planes = 4, + .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, + .hsub = 2, .vsub = 2, .is_yuv = true }, +}; + +/* + * Same as gen12_ccs_formats[] above, but with additional surface used + * to pass Clear Color information in plane 2 with 64 bits of data. + */ +static const struct drm_format_info gen12_ccs_cc_formats[] = { + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3, + .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, + .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3, + .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, + .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3, + .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, + .hsub = 1, .vsub = 1, .has_alpha = true }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3, + .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, + .hsub = 1, .vsub = 1, .has_alpha = true }, +}; + struct intel_modifier_desc { u64 modifier; struct { @@ -21,6 +114,12 @@ struct intel_modifier_desc { } display_ver; #define DISPLAY_VER_ALL { 0, -1 } + const struct drm_format_info *formats; + int format_count; +#define FORMAT_OVERRIDE(format_list) \ + .formats = format_list, \ + .format_count = ARRAY_SIZE(format_list) + u8 is_linear:1; struct { @@ -39,26 +138,36 @@ static const struct intel_modifier_desc intel_modifiers[] = { .display_ver = { 12, 13 }, .ccs.type = INTEL_CCS_MC, + + FORMAT_OVERRIDE(gen12_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, .display_ver = { 12, 13 }, .ccs.type = INTEL_CCS_RC, + + FORMAT_OVERRIDE(gen12_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, .display_ver = { 12, 13 }, .ccs.type = INTEL_CCS_RC_CC, + + FORMAT_OVERRIDE(gen12_ccs_cc_formats), }, { .modifier = I915_FORMAT_MOD_Yf_TILED_CCS, .display_ver = { 9, 11 }, .ccs.type = INTEL_CCS_RC, + + FORMAT_OVERRIDE(skl_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Y_TILED_CCS, .display_ver = { 9, 11 }, .ccs.type = INTEL_CCS_RC, + + FORMAT_OVERRIDE(skl_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Yf_TILED, .display_ver = { 9, 11 }, @@ -76,6 +185,50 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, }; +static const struct intel_modifier_desc *lookup_modifier_or_null(u64 modifier) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) + if (intel_modifiers[i].modifier == modifier) + return &intel_modifiers[i]; + + return NULL; +} + +static const struct drm_format_info * +lookup_format_info(const struct drm_format_info formats[], + int num_formats, u32 format) +{ + int i; + + for (i = 0; i < num_formats; i++) { + if (formats[i].format == format) + return &formats[i]; + } + + return NULL; +} + +/** + * intel_fb_get_format_info: Get a modifier specific format information + * @cmd: FB add command structure + * + * Returns: + * Returns the format information for @cmd->pixel_format specific to @cmd->modifier[0], + * or %NULL if the modifier doesn't override the format. + */ +const struct drm_format_info * +intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd) +{ + const struct intel_modifier_desc *md = lookup_modifier_or_null(cmd->modifier[0]); + + if (!md || !md->formats) + return NULL; + + return lookup_format_info(md->formats, md->format_count, cmd->pixel_format); +} + static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_type) { return md->ccs.type & ccs_type; diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 0f77e81e69d29..97b31c3a29825 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -36,6 +36,9 @@ u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, enum intel_plane_caps plane_caps); bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier); +const struct drm_format_info * +intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd); + bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane); int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane); From 3dfb2d6b489f7f1a627774f84a6341c18785f43f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:30 +0300 Subject: [PATCH 029/176] drm/i915: Add tiling attribute to the modifier descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a tiling atttribute to the modifier descriptor, which let's us get the tiling without listing the modifiers twice. v1-v2: Unchanged. v3: - Initialize .tiling to I915_TILING_NONE explicitly (Ville) - Move from previous patch lookup_modifier() to here, where it's first used. Cc: Juha-Pekka Heikkila Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 33 ++++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 42919d22a035b..0355a73ebdcb5 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -120,6 +120,7 @@ struct intel_modifier_desc { .formats = format_list, \ .format_count = ARRAY_SIZE(format_list) + u8 tiling; u8 is_linear:1; struct { @@ -136,6 +137,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, .display_ver = { 12, 13 }, + .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_MC, @@ -143,6 +145,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, .display_ver = { 12, 13 }, + .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_RC, @@ -150,6 +153,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, .display_ver = { 12, 13 }, + .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_RC_CC, @@ -157,6 +161,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Yf_TILED_CCS, .display_ver = { 9, 11 }, + .tiling = I915_TILING_NONE, .ccs.type = INTEL_CCS_RC, @@ -164,6 +169,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Y_TILED_CCS, .display_ver = { 9, 11 }, + .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_RC, @@ -171,15 +177,19 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Yf_TILED, .display_ver = { 9, 11 }, + .tiling = I915_TILING_NONE, }, { .modifier = I915_FORMAT_MOD_Y_TILED, .display_ver = { 9, 13 }, + .tiling = I915_TILING_Y, }, { .modifier = I915_FORMAT_MOD_X_TILED, .display_ver = DISPLAY_VER_ALL, + .tiling = I915_TILING_X, }, { .modifier = DRM_FORMAT_MOD_LINEAR, .display_ver = DISPLAY_VER_ALL, + .tiling = I915_TILING_NONE, .is_linear = true, }, @@ -196,6 +206,16 @@ static const struct intel_modifier_desc *lookup_modifier_or_null(u64 modifier) return NULL; } +static const struct intel_modifier_desc *lookup_modifier(u64 modifier) +{ + const struct intel_modifier_desc *md = lookup_modifier_or_null(modifier); + + if (WARN_ON(!md)) + return &intel_modifiers[0]; + + return md; +} + static const struct drm_format_info * lookup_format_info(const struct drm_format_info formats[], int num_formats, u32 format) @@ -520,18 +540,7 @@ intel_fb_align_height(const struct drm_framebuffer *fb, static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) { - switch (fb_modifier) { - case I915_FORMAT_MOD_X_TILED: - return I915_TILING_X; - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - return I915_TILING_Y; - default: - return I915_TILING_NONE; - } + return lookup_modifier(fb_modifier)->tiling; } unsigned int intel_cursor_alignment(const struct drm_i915_private *i915) From d89357ded55e1294e172cec176f49e1685dca06d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:31 +0300 Subject: [PATCH 030/176] drm/i915: Simplify the modifier check for interlaced scanout support Checking the modifiers that support interlacing makes the condition simpler and avoids us having to add new modifiers to the list (presuming all/most of the new modifiers won't support interlacing). Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 7ee2114e420b7..2c3d11193caa7 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1235,13 +1235,8 @@ 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 && - (fb->modifier == I915_FORMAT_MOD_Y_TILED || - fb->modifier == I915_FORMAT_MOD_Yf_TILED || - fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS || - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) { + fb->modifier != DRM_FORMAT_MOD_LINEAR && + fb->modifier != I915_FORMAT_MOD_X_TILED) { drm_dbg_kms(&dev_priv->drm, "Y/Yf tiling not supported in IF-ID mode\n"); return -EINVAL; From b1562f0f0f69120225285977eb2bd488c7eb5482 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:32 +0300 Subject: [PATCH 031/176] drm/i915: Unexport is_semiplanar_uv_plane() This function is only used by intel_fb.c, so unexport it. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-6-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- drivers/gpu/drm/i915/display/intel_fb.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 0355a73ebdcb5..3fe22f4418a0d 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -349,7 +349,7 @@ bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane) plane == 2; } -bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane) +static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane) { return intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && color_plane == 1; diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 97b31c3a29825..c331df575490d 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -30,7 +30,6 @@ enum intel_plane_caps { bool is_ccs_plane(const struct drm_framebuffer *fb, int plane); bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane); bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane); -bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane); u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, enum intel_plane_caps plane_caps); From 0f2922ef48484ca4687319d03f72afdda2172e97 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:33 +0300 Subject: [PATCH 032/176] drm/i915: Move intel_format_info_is_yuv_semiplanar() to intel_fb.c Move intel_format_info_is_yuv_semiplanar() to intel_fb.c . The number of planes for YUV semiplanar formats using CCS modifiers will change on future platforms. We can use the modifier descriptors to simplify getting the plane numbers for all modifiers, prepare for that here. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-7-imre.deak@intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 8 ----- drivers/gpu/drm/i915/display/intel_display.h | 3 -- drivers/gpu/drm/i915/display/intel_fb.c | 30 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fb.h | 4 +++ drivers/gpu/drm/i915/intel_pm.c | 1 + 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 0be8c00e3db9a..f61a48e1a562b 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -39,6 +39,7 @@ #include "intel_atomic_plane.h" #include "intel_cdclk.h" #include "intel_display_types.h" +#include "intel_fb.h" #include "intel_fb_pin.h" #include "intel_pm.h" #include "intel_sprite.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 86333c0cd7937..c66d525612ad1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -595,14 +595,6 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state) intel_wait_for_pipe_off(old_crtc_state); } -bool -intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, - u64 modifier) -{ - return info->is_yuv && - info->num_planes == (is_ccs_modifier(modifier) ? 4 : 2); -} - unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info) { unsigned int size = 0; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index c2efba7c6c172..38c15ec30ee7c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -605,9 +605,6 @@ int bdw_get_pipemisc_bpp(struct intel_crtc *crtc); unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state); bool intel_plane_uses_fence(const struct intel_plane_state *plane_state); -bool -intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, - u64 modifier); struct intel_encoder * intel_get_crtc_new_encoder(const struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 3fe22f4418a0d..00e76571799ed 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -330,6 +330,36 @@ bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier) return false; } +static bool format_is_yuv_semiplanar(const struct intel_modifier_desc *md, + const struct drm_format_info *info) +{ + int yuv_planes; + + if (!info->is_yuv) + return false; + + if (is_ccs_type_modifier(md, INTEL_CCS_ANY)) + yuv_planes = 4; + else + yuv_planes = 2; + + return info->num_planes == yuv_planes; +} + +/** + * intel_format_info_is_yuv_semiplanar: Check if the given format is YUV semiplanar + * @info: format to check + * @modifier: modifier used with the format + * + * Returns: + * %true if @info / @modifier is YUV semiplanar. + */ +bool intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, + u64 modifier) +{ + return format_is_yuv_semiplanar(lookup_modifier(modifier), info); +} + bool is_ccs_plane(const struct drm_framebuffer *fb, int plane) { if (!is_ccs_modifier(fb->modifier)) diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index c331df575490d..a2cdf48f13395 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -38,6 +38,10 @@ bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier); const struct drm_format_info * intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd); +bool +intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, + u64 modifier); + bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane); int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index aaa3a0998e4c6..9089569f36a3c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -37,6 +37,7 @@ #include "display/intel_bw.h" #include "display/intel_de.h" #include "display/intel_display_types.h" +#include "display/intel_fb.h" #include "display/intel_fbc.h" #include "display/intel_sprite.h" #include "display/skl_universal_plane.h" From b0f1670d22ce1e192f29e931069297ff16156026 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:34 +0300 Subject: [PATCH 033/176] drm/i915: Add a platform independent way to get the RC CCS CC plane On future platforms the index of the color-clear plane will change from the one used by the GEN12 RC CCS CC modifier, so add a way to retrieve the index independently of the platform/modifier. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-8-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 10 +++++--- drivers/gpu/drm/i915/display/intel_fb.c | 25 ++++++++++++++++++-- drivers/gpu/drm/i915/display/intel_fb.h | 2 ++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c66d525612ad1..2b97c87971773 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8572,10 +8572,14 @@ static void intel_atomic_prepare_plane_clear_colors(struct intel_atomic_state *s for_each_new_intel_plane_in_state(state, plane, plane_state, i) { struct drm_framebuffer *fb = plane_state->hw.fb; + int cc_plane; int ret; - if (!fb || - fb->modifier != I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC) + if (!fb) + continue; + + cc_plane = intel_fb_rc_ccs_cc_plane(fb); + if (cc_plane < 0) continue; /* @@ -8592,7 +8596,7 @@ static void intel_atomic_prepare_plane_clear_colors(struct intel_atomic_state *s * GPU write on it. */ ret = i915_gem_object_read_from_page(intel_fb_obj(fb), - fb->offsets[2] + 16, + fb->offsets[cc_plane] + 16, &plane_state->ccval, sizeof(plane_state->ccval)); /* The above could only fail if the FB obj has an unexpected backing store type. */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 00e76571799ed..387d9a3a30f78 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -130,6 +130,7 @@ struct intel_modifier_desc { #define INTEL_CCS_ANY (INTEL_CCS_RC | INTEL_CCS_RC_CC | INTEL_CCS_MC) u8 type:3; + u8 cc_planes:3; } ccs; }; @@ -156,6 +157,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_RC_CC, + .ccs.cc_planes = BIT(2), FORMAT_OVERRIDE(gen12_ccs_cc_formats), }, { @@ -373,10 +375,29 @@ bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane) return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane); } +/** + * intel_fb_rc_ccs_cc_plane: Get the CCS CC color plane index for a framebuffer + * @fb: Framebuffer + * + * Returns: + * Returns the index of the color clear plane for @fb, or -1 if @fb is not a + * framebuffer using a render compression/color clear modifier. + */ +int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb) +{ + const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); + + if (!md->ccs.cc_planes) + return -1; + + drm_WARN_ON_ONCE(fb->dev, hweight8(md->ccs.cc_planes) > 1); + + return ilog2((int)md->ccs.cc_planes); +} + bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane) { - return fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC && - plane == 2; + return intel_fb_rc_ccs_cc_plane(fb) == plane; } static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane) diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index a2cdf48f13395..74e0fc03319b9 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -31,6 +31,8 @@ bool is_ccs_plane(const struct drm_framebuffer *fb, int plane); bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane); bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane); +int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb); + u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, enum intel_plane_caps plane_caps); bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier); From df63860da913e6afc0d725a87f99e930ee237451 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:35 +0300 Subject: [PATCH 034/176] drm/i915: Handle CCS CC planes separately from CCS AUX planes CCS CC planes are quite different from CCS AUX planes, even though we regard the CC planes as a linear buffer having a 64 byte stride. Thus it's clearer to check for either CCS plane types explicitly when we need to handle them; add the required CCS CC planes check here, while the next patch will change all is_ccs_plane()/is_gen12_ccs_plane() checks to consider only the CCS AUX planes. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-9-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 387d9a3a30f78..0cc712e819ae8 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -409,7 +409,8 @@ static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_p bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane) { return fb->modifier == DRM_FORMAT_MOD_LINEAR || - is_gen12_ccs_plane(fb, color_plane); + is_gen12_ccs_plane(fb, color_plane) || + is_gen12_ccs_cc_plane(fb, color_plane); } int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) @@ -502,7 +503,8 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - if (is_ccs_plane(fb, color_plane)) + if (is_ccs_plane(fb, color_plane) || + is_gen12_ccs_cc_plane(fb, color_plane)) return 64; fallthrough; case I915_FORMAT_MOD_Y_TILED: From f50423436105e136e2409b500719334188a77aa6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:36 +0300 Subject: [PATCH 035/176] drm/i915: Add a platform independent way to check for CCS AUX planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Future platforms change the location of CCS AUX planes in CCS framebuffers, so add intel_fb_is_ccs_aux_plane() to query for these planes independently of the platform. This function can be used everywhere instead of is_ccs_plane() (or is_ccs_plane() && !cc_plane()), since all the callers are only interested in CCS AUX planes (and not CCS color-clear planes). Add the corresponding intel_fb_is_gen12_ccs_aux_plane(), which can be used everywhere instead of is_gen12_ccs_plane(), based on the above explanation. This change also unexports the is_gen12_ccs_modifier(), is_gen12_ccs_plane(), is_gen12_ccs_cc_plane() functions as they are only used in intel_fb.c v1-v2: Unchanged v3: (Ville) - Use ccs_aux instead of the ccs_ctrl term everywhere. - Use color_plane instead of plane term for FB plane indicies. v4: Fix version range check. (Jani) Cc: Juha-Pekka Heikkila Cc: Ville Syrjälä Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-10-imre.deak@intel.com --- .../drm/i915/display/intel_display_types.h | 7 -- drivers/gpu/drm/i915/display/intel_fb.c | 82 ++++++++++++++----- drivers/gpu/drm/i915/display/intel_fb.h | 5 +- .../drm/i915/display/skl_universal_plane.c | 3 +- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index a4930a56bfa82..bf97a56bdbc37 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -2051,11 +2051,4 @@ static inline bool is_ccs_modifier(u64 modifier) modifier == I915_FORMAT_MOD_Yf_TILED_CCS; } -static inline bool is_gen12_ccs_modifier(u64 modifier) -{ - return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS; -} - #endif /* __INTEL_DISPLAY_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 0cc712e819ae8..f5e1ad37f4f1a 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -131,6 +131,8 @@ struct intel_modifier_desc { #define INTEL_CCS_ANY (INTEL_CCS_RC | INTEL_CCS_RC_CC | INTEL_CCS_MC) u8 type:3; u8 cc_planes:3; + u8 packed_aux_planes:4; + u8 planar_aux_planes:4; } ccs; }; @@ -141,6 +143,8 @@ static const struct intel_modifier_desc intel_modifiers[] = { .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_MC, + .ccs.packed_aux_planes = BIT(1), + .ccs.planar_aux_planes = BIT(2) | BIT(3), FORMAT_OVERRIDE(gen12_ccs_formats), }, { @@ -149,6 +153,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_RC, + .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(gen12_ccs_formats), }, { @@ -158,6 +163,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .ccs.type = INTEL_CCS_RC_CC, .ccs.cc_planes = BIT(2), + .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(gen12_ccs_cc_formats), }, { @@ -166,6 +172,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .tiling = I915_TILING_NONE, .ccs.type = INTEL_CCS_RC, + .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(skl_ccs_formats), }, { @@ -174,6 +181,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .tiling = I915_TILING_Y, .ccs.type = INTEL_CCS_RC, + .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(skl_ccs_formats), }, { @@ -256,6 +264,13 @@ static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_ty return md->ccs.type & ccs_type; } +static bool check_modifier_display_ver_range(const struct intel_modifier_desc *md, + u8 display_ver_from, u8 display_ver_until) +{ + return md->display_ver.from <= display_ver_until && + display_ver_from <= md->display_ver.until; +} + static bool plane_has_modifier(struct drm_i915_private *i915, enum intel_plane_caps plane_caps, const struct intel_modifier_desc *md) @@ -362,17 +377,44 @@ bool intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, return format_is_yuv_semiplanar(lookup_modifier(modifier), info); } -bool is_ccs_plane(const struct drm_framebuffer *fb, int plane) +static u8 ccs_aux_plane_mask(const struct intel_modifier_desc *md, + const struct drm_format_info *format) { - if (!is_ccs_modifier(fb->modifier)) - return false; + if (format_is_yuv_semiplanar(md, format)) + return md->ccs.planar_aux_planes; + else + return md->ccs.packed_aux_planes; +} - return plane >= fb->format->num_planes / 2; +/** + * intel_fb_is_ccs_aux_plane: Check if a framebuffer color plane is a CCS AUX plane + * @fb: Framebuffer + * @color_plane: color plane index to check + * + * Returns: + * Returns %true if @fb's color plane at index @color_plane is a CCS AUX plane. + */ +bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane) +{ + const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); + + return ccs_aux_plane_mask(md, fb->format) & BIT(color_plane); } -bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane) +/** + * intel_fb_is_gen12_ccs_aux_plane: Check if a framebuffer color plane is a GEN12 CCS AUX plane + * @fb: Framebuffer + * @color_plane: color plane index to check + * + * Returns: + * Returns %true if @fb's color plane at index @color_plane is a GEN12 CCS AUX plane. + */ +static bool intel_fb_is_gen12_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane) { - return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane); + const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); + + return check_modifier_display_ver_range(md, 12, 13) && + ccs_aux_plane_mask(md, fb->format) & BIT(color_plane); } /** @@ -395,9 +437,9 @@ int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb) return ilog2((int)md->ccs.cc_planes); } -bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane) +static bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int color_plane) { - return intel_fb_rc_ccs_cc_plane(fb) == plane; + return intel_fb_rc_ccs_cc_plane(fb) == color_plane; } static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane) @@ -409,7 +451,7 @@ static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_p bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane) { return fb->modifier == DRM_FORMAT_MOD_LINEAR || - is_gen12_ccs_plane(fb, color_plane) || + intel_fb_is_gen12_ccs_aux_plane(fb, color_plane) || is_gen12_ccs_cc_plane(fb, color_plane); } @@ -497,13 +539,13 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) else return 512; case I915_FORMAT_MOD_Y_TILED_CCS: - if (is_ccs_plane(fb, color_plane)) + if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return 128; fallthrough; case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - if (is_ccs_plane(fb, color_plane) || + if (intel_fb_is_ccs_aux_plane(fb, color_plane) || is_gen12_ccs_cc_plane(fb, color_plane)) return 64; fallthrough; @@ -513,7 +555,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) else return 512; case I915_FORMAT_MOD_Yf_TILED_CCS: - if (is_ccs_plane(fb, color_plane)) + if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return 128; fallthrough; case I915_FORMAT_MOD_Yf_TILED: @@ -569,7 +611,7 @@ static void intel_tile_block_dims(const struct drm_framebuffer *fb, int color_pl { intel_tile_dims(fb, color_plane, tile_width, tile_height); - if (is_gen12_ccs_plane(fb, color_plane)) + if (intel_fb_is_gen12_ccs_aux_plane(fb, color_plane)) *tile_height = 1; } @@ -630,7 +672,7 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, return 512 * 4096; /* AUX_DIST needs only 4K alignment */ - if (is_ccs_plane(fb, color_plane)) + if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return 4096; if (is_semiplanar_uv_plane(fb, color_plane)) { @@ -689,7 +731,7 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub, * TODO: Deduct the subsampling from the char block for all CCS * formats and planes. */ - if (!is_gen12_ccs_plane(fb, color_plane)) { + if (!intel_fb_is_gen12_ccs_aux_plane(fb, color_plane)) { *hsub = fb->format->hsub; *vsub = fb->format->vsub; @@ -717,7 +759,7 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub, static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_plane, int *w, int *h) { struct drm_i915_private *i915 = to_i915(fb->base.dev); - int main_plane = is_ccs_plane(&fb->base, color_plane) ? + int main_plane = intel_fb_is_ccs_aux_plane(&fb->base, color_plane) ? skl_ccs_to_main_plane(&fb->base, color_plane) : 0; unsigned int main_width = fb->base.width; unsigned int main_height = fb->base.height; @@ -730,7 +772,7 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl * stride in the allocated FB object may not be power-of-two * sized, in which case it is auto-padded to the POT size. */ - if (IS_ALDERLAKE_P(i915) && is_ccs_plane(&fb->base, color_plane)) + if (IS_ALDERLAKE_P(i915) && intel_fb_is_ccs_aux_plane(&fb->base, color_plane)) main_width = gen12_aligned_scanout_stride(fb, 0) / fb->base.format->cpp[0]; @@ -969,7 +1011,7 @@ static int intel_fb_check_ccs_xy(const struct drm_framebuffer *fb, int ccs_plane int ccs_x, ccs_y; int main_x, main_y; - if (!is_ccs_plane(fb, ccs_plane) || is_gen12_ccs_cc_plane(fb, ccs_plane)) + if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane)) return 0; /* @@ -1173,7 +1215,7 @@ plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane, unsigned int pitch_tiles) { if (intel_fb_needs_pot_stride_remap(fb)) { - unsigned int min_stride = is_ccs_plane(&fb->base, color_plane) ? 2 : 8; + unsigned int min_stride = intel_fb_is_ccs_aux_plane(&fb->base, color_plane) ? 2 : 8; /* * ADL_P, the only platform needing a POT stride has a minimum * of 8 main surface and 2 CCS AUX stride tiles. @@ -1789,7 +1831,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb, goto err; } - if (is_gen12_ccs_plane(fb, i) && !is_gen12_ccs_cc_plane(fb, i)) { + if (intel_fb_is_gen12_ccs_aux_plane(fb, i)) { int ccs_aux_stride = gen12_ccs_aux_stride(intel_fb, i); if (fb->pitches[i] != ccs_aux_stride) { diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 74e0fc03319b9..c80822b3cb827 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -27,10 +27,7 @@ enum intel_plane_caps { PLANE_HAS_CCS_MC = BIT(2), }; -bool is_ccs_plane(const struct drm_framebuffer *fb, int plane); -bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane); -bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane); - +bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane); int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb); u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 2c3d11193caa7..cd17f03db57ae 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1602,8 +1602,7 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) int hsub, vsub; int x, y; - if (!is_ccs_plane(fb, ccs_plane) || - is_gen12_ccs_cc_plane(fb, ccs_plane)) + if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane)) continue; intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, From e359c47bfa6155b56d378864b7cc4a0d4e680c1b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:37 +0300 Subject: [PATCH 036/176] drm/i915: Move is_ccs_modifier() to intel_fb.c Move the function to intel_fb.c and rename it adding the intel_fb_ prefix following the naming of exported functions. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-11-imre.deak@intel.com --- .../drm/i915/display/intel_display_types.h | 9 ------ drivers/gpu/drm/i915/display/intel_fb.c | 29 ++++++++++++++----- drivers/gpu/drm/i915/display/intel_fb.h | 2 ++ .../drm/i915/display/skl_universal_plane.c | 12 ++++---- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index bf97a56bdbc37..85cb55034bb02 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -2042,13 +2042,4 @@ to_intel_frontbuffer(struct drm_framebuffer *fb) return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL; } -static inline bool is_ccs_modifier(u64 modifier) -{ - return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_CCS || - modifier == I915_FORMAT_MOD_Yf_TILED_CCS; -} - #endif /* __INTEL_DISPLAY_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index f5e1ad37f4f1a..6b4b3fb1e624d 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -264,6 +264,19 @@ static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_ty return md->ccs.type & ccs_type; } +/** + * intel_fb_is_ccs_modifier: Check if a modifier is a CCS modifier type + * @modifier: Modifier to check + * + * Returns: + * Returns %true if @modifier is a render, render with color clear or + * media compression modifier. + */ +bool intel_fb_is_ccs_modifier(u64 modifier) +{ + return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_ANY); +} + static bool check_modifier_display_ver_range(const struct intel_modifier_desc *md, u8 display_ver_from, u8 display_ver_until) { @@ -457,7 +470,7 @@ bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane) int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) { - drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) || + drm_WARN_ON(fb->dev, !intel_fb_is_ccs_modifier(fb->modifier) || (main_plane && main_plane >= fb->format->num_planes / 2)); return fb->format->num_planes / 2 + main_plane; @@ -465,7 +478,7 @@ int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane) { - drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) || + drm_WARN_ON(fb->dev, !intel_fb_is_ccs_modifier(fb->modifier) || ccs_plane < fb->format->num_planes / 2); if (is_gen12_ccs_cc_plane(fb, ccs_plane)) @@ -510,7 +523,7 @@ int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) { struct drm_i915_private *i915 = to_i915(fb->dev); - if (is_ccs_modifier(fb->modifier)) + if (intel_fb_is_ccs_modifier(fb->modifier)) return main_to_ccs_plane(fb, main_plane); else if (DISPLAY_VER(i915) < 11 && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) @@ -1074,7 +1087,7 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state) * The new CCS hash mode isn't compatible with remapping as * the virtual address of the pages affects the compressed data. */ - if (is_ccs_modifier(fb->modifier)) + if (intel_fb_is_ccs_modifier(fb->modifier)) return false; /* Linear needs a page aligned stride for remapping */ @@ -1481,7 +1494,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) src_w = drm_rect_width(&plane_state->uapi.src) >> 16; src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - drm_WARN_ON(&i915->drm, is_ccs_modifier(fb->modifier)); + drm_WARN_ON(&i915->drm, intel_fb_is_ccs_modifier(fb->modifier)); /* Make src coordinates relative to the viewport */ drm_rect_translate(&plane_state->uapi.src, @@ -1544,7 +1557,7 @@ u32 intel_fb_max_stride(struct drm_i915_private *dev_priv, * * The new CCS hash mode makes remapping impossible */ - if (DISPLAY_VER(dev_priv) < 4 || is_ccs_modifier(modifier) || + if (DISPLAY_VER(dev_priv) < 4 || intel_fb_is_ccs_modifier(modifier) || intel_modifier_uses_dpt(dev_priv, modifier)) return intel_plane_fb_max_stride(dev_priv, pixel_format, modifier); else if (DISPLAY_VER(dev_priv) >= 7) @@ -1569,14 +1582,14 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) * we need the stride to be page aligned. */ if (fb->pitches[color_plane] > max_stride && - !is_ccs_modifier(fb->modifier)) + !intel_fb_is_ccs_modifier(fb->modifier)) return intel_tile_size(dev_priv); else return 64; } tile_width = intel_tile_width_bytes(fb, color_plane); - if (is_ccs_modifier(fb->modifier)) { + if (intel_fb_is_ccs_modifier(fb->modifier)) { /* * On ADL-P the stride must be either 8 tiles or a stride * that is aligned to 16 tiles, required by the 16 tiles = diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index c80822b3cb827..f32306fbd3dee 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -27,6 +27,8 @@ enum intel_plane_caps { PLANE_HAS_CCS_MC = BIT(2), }; +bool intel_fb_is_ccs_modifier(u64 modifier); + bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane); int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index cd17f03db57ae..e2d1c05d4270c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1183,7 +1183,7 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, return 0; if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && - is_ccs_modifier(fb->modifier)) { + intel_fb_is_ccs_modifier(fb->modifier)) { drm_dbg_kms(&dev_priv->drm, "RC support only with 0/180 degree rotation (%x)\n", rotation); @@ -1482,7 +1482,7 @@ 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 (is_ccs_modifier(fb->modifier)) { + if (intel_fb_is_ccs_modifier(fb->modifier)) { while (!skl_check_main_ccs_coordinates(plane_state, x, y, offset, aux_plane)) { if (offset == 0) @@ -1546,7 +1546,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, uv_plane); - if (is_ccs_modifier(fb->modifier)) { + if (intel_fb_is_ccs_modifier(fb->modifier)) { int ccs_plane = main_to_ccs_plane(fb, uv_plane); u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; u32 alignment = intel_surf_alignment(fb, uv_plane); @@ -1644,7 +1644,7 @@ static int skl_check_plane_surface(struct intel_plane_state *plane_state) * Handle the AUX surface first since the main surface setup depends on * it. */ - if (is_ccs_modifier(fb->modifier)) { + if (intel_fb_is_ccs_modifier(fb->modifier)) { ret = skl_check_ccs_aux_surface(plane_state); if (ret) return ret; @@ -1845,7 +1845,7 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: - if (is_ccs_modifier(modifier)) + if (intel_fb_is_ccs_modifier(modifier)) return true; fallthrough; case DRM_FORMAT_RGB565: @@ -1899,7 +1899,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: - if (is_ccs_modifier(modifier)) + if (intel_fb_is_ccs_modifier(modifier)) return true; fallthrough; case DRM_FORMAT_YUYV: From 0b2c31dd8868651d878af4c60b235dfb52909e74 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 20 Oct 2021 22:51:38 +0300 Subject: [PATCH 037/176] drm/i915: Add functions to check for RC CCS CC and MC CCS modifiers Instead of open-coding the checks add functions for this, simplifying the handling of CCS modifiers on future platforms. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-12-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 24 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fb.h | 2 ++ .../drm/i915/display/skl_universal_plane.c | 4 ++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 6b4b3fb1e624d..9ce1d273dc7e1 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -277,6 +277,30 @@ bool intel_fb_is_ccs_modifier(u64 modifier) return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_ANY); } +/** + * intel_fb_is_rc_ccs_cc_modifier: Check if a modifier is an RC CCS CC modifier type + * @modifier: Modifier to check + * + * Returns: + * Returns %true if @modifier is a render with color clear modifier. + */ +bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier) +{ + return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_RC_CC); +} + +/** + * intel_fb_is_mc_ccs_modifier: Check if a modifier is an MC CCS modifier type + * @modifier: Modifier to check + * + * Returns: + * Returns %true if @modifier is a media compression modifier. + */ +bool intel_fb_is_mc_ccs_modifier(u64 modifier) +{ + return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_MC); +} + static bool check_modifier_display_ver_range(const struct intel_modifier_desc *md, u8 display_ver_from, u8 display_ver_until) { diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index f32306fbd3dee..042ad81f86082 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -28,6 +28,8 @@ enum intel_plane_caps { }; bool intel_fb_is_ccs_modifier(u64 modifier); +bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier); +bool intel_fb_is_mc_ccs_modifier(u64 modifier); bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane); int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index e2d1c05d4270c..69fd56de83a7a 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1078,7 +1078,7 @@ skl_program_plane(struct intel_plane *plane, if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id)) icl_program_input_csc(plane, crtc_state, plane_state); - if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC) + if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) intel_uncore_write64_fw(&dev_priv->uncore, PLANE_CC_VAL(pipe, plane_id), plane_state->ccval); @@ -1911,7 +1911,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_P010: case DRM_FORMAT_P012: case DRM_FORMAT_P016: - if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS) + if (intel_fb_is_mc_ccs_modifier(modifier)) return true; fallthrough; case DRM_FORMAT_RGB565: From 09f8fe4cae5ee8eb2ac44e437d4295357f3cdb36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 21 Oct 2021 01:33:36 +0300 Subject: [PATCH 038/176] drm/i915: Move function prototypes to the correct header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A bunch of function prototypes were left behind when the plane/crtc code got reshuffled to new files. Move the prototypes as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211020223339.669-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_crtc.h | 5 +++++ drivers/gpu/drm/i915/display/intel_psr.c | 2 +- drivers/gpu/drm/i915/display/intel_sprite.h | 4 ---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h index a5ae997581aa9..22363fbbc9255 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.h +++ b/drivers/gpu/drm/i915/display/intel_crtc.h @@ -9,10 +9,13 @@ #include enum pipe; +struct drm_display_mode; struct drm_i915_private; struct intel_crtc; struct intel_crtc_state; +int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, + int usecs); u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state); int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe); struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc); @@ -21,5 +24,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc); void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state); void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state); +void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); +void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); #endif diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 49c2dfbd40554..ccffe05784d3c 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -28,13 +28,13 @@ #include "i915_drv.h" #include "intel_atomic.h" +#include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dp_aux.h" #include "intel_hdmi.h" #include "intel_psr.h" #include "intel_snps_phy.h" -#include "intel_sprite.h" #include "skl_universal_plane.h" /** diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h index c085eb87705cc..4f63e49677314 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.h +++ b/drivers/gpu/drm/i915/display/intel_sprite.h @@ -27,14 +27,10 @@ struct intel_plane_state; #define VBLANK_EVASION_TIME_US 100 #endif -int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, - int usecs); struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, int plane); int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); -void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); int chv_plane_check_rotation(const struct intel_plane_state *plane_state); From 3cf460bd683df848c3df90b9bd6c28bc86acea8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 16:39:02 +0300 Subject: [PATCH 039/176] drm/i915/hdmi: Split intel_hdmi_bpc_possible() to source vs. sink pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_hdmi_bpc_possible() is used by the DP code as well where the native HDMI source limits do not apply. So let's split this into a pair of functions: one for the source vs. one for the sink. This is basically reverting some of commit 41828125acd6 ("drm/i915: Move platform checks into intel_hdmi_bpc_possible()") slightly, but in a nicer form. I guess I forgot at the time that the DP side uses this too. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015133921.4609-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdmi.c | 38 ++++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index d2e61f6c6e08e..d7196494cc27f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1873,18 +1873,29 @@ static int intel_hdmi_port_clock(int clock, int bpc) return clock * bpc / 8; } -static bool intel_hdmi_bpc_possible(struct drm_connector *connector, - int bpc, bool has_hdmi_sink, bool ycbcr420_output) +static bool intel_hdmi_source_bpc_possible(struct drm_i915_private *i915, int bpc) +{ + switch (bpc) { + case 12: + return !HAS_GMCH(i915); + case 10: + return DISPLAY_VER(i915) >= 11; + case 8: + return true; + default: + MISSING_CASE(bpc); + return false; + } +} + +static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector, + int bpc, bool has_hdmi_sink, bool ycbcr420_output) { - struct drm_i915_private *i915 = to_i915(connector->dev); const struct drm_display_info *info = &connector->display_info; const struct drm_hdmi_info *hdmi = &info->hdmi; switch (bpc) { case 12: - if (HAS_GMCH(i915)) - return false; - if (!has_hdmi_sink) return false; @@ -1893,9 +1904,6 @@ static bool intel_hdmi_bpc_possible(struct drm_connector *connector, else return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36; case 10: - if (DISPLAY_VER(i915) < 11) - return false; - if (!has_hdmi_sink) return false; @@ -1915,6 +1923,7 @@ static enum drm_mode_status intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, bool has_hdmi_sink, bool ycbcr420_output) { + struct drm_i915_private *i915 = to_i915(connector->dev); struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); enum drm_mode_status status; @@ -1927,13 +1936,15 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, /* if we can't do 8bpc we may still be able to do 12bpc */ if (status != MODE_OK && - intel_hdmi_bpc_possible(connector, 12, has_hdmi_sink, ycbcr420_output)) + intel_hdmi_source_bpc_possible(i915, 12) && + intel_hdmi_sink_bpc_possible(connector, 12, has_hdmi_sink, ycbcr420_output)) status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 12), true, has_hdmi_sink); /* if we can't do 8,12bpc we may still be able to do 10bpc */ if (status != MODE_OK && - intel_hdmi_bpc_possible(connector, 10, has_hdmi_sink, ycbcr420_output)) + intel_hdmi_source_bpc_possible(i915, 10) && + intel_hdmi_sink_bpc_possible(connector, 10, has_hdmi_sink, ycbcr420_output)) status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 10), true, has_hdmi_sink); @@ -1999,7 +2010,7 @@ bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, if (connector_state->crtc != crtc_state->uapi.crtc) continue; - if (!intel_hdmi_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output)) + if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output)) return false; } @@ -2014,6 +2025,9 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + if (!intel_hdmi_source_bpc_possible(dev_priv, bpc)) + return false; + /* * HDMI deep color affects the clocks, so it's only possible * when not cloning with other encoder types. From bb115220d248e394a65a52e128dbb8096c9c8868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 16:39:03 +0300 Subject: [PATCH 040/176] drm/i915/hdmi: Introduce intel_hdmi_is_ycbr420() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a small helper which given the crtc state tells us whether we're output YCbCr 4:2:0 or not. For native HDMI this is rather simple as we just look at the output_format. But I think the helper is beneficial since with DP HDMI DFPs we're going to need a more complex variant, and I want to unify the DP and HDMI sides of that as much as possible. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015133921.4609-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdmi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index d7196494cc27f..37ce8a6219736 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1799,6 +1799,11 @@ static bool intel_has_hdmi_sink(struct intel_hdmi *hdmi, READ_ONCE(to_intel_digital_connector_state(conn_state)->force_audio) != HDMI_AUDIO_OFF_DVI; } +static bool intel_hdmi_is_ycbcr420(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420; +} + static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, bool respect_downstream_limits, bool has_hdmi_sink) @@ -2036,7 +2041,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, return false; /* Display Wa_1405510057:icl,ehl */ - if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && + if (intel_hdmi_is_ycbcr420(crtc_state) && bpc == 10 && DISPLAY_VER(dev_priv) == 11 && (adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start) % 8 == 2) @@ -2044,8 +2049,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, return intel_hdmi_deep_color_possible(crtc_state, bpc, crtc_state->has_hdmi_sink, - crtc_state->output_format == - INTEL_OUTPUT_FORMAT_YCBCR420); + intel_hdmi_is_ycbcr420(crtc_state)); } static int intel_hdmi_compute_bpc(struct intel_encoder *encoder, @@ -2079,7 +2083,7 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder, clock *= 2; /* YCBCR420 TMDS rate requirement is half the pixel clock */ - if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) + if (intel_hdmi_is_ycbcr420(crtc_state)) clock /= 2; bpc = intel_hdmi_compute_bpc(encoder, crtc_state, clock); @@ -2176,7 +2180,7 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, ret = intel_hdmi_compute_clock(encoder, crtc_state); if (ret) { - if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 && + if (!intel_hdmi_is_ycbcr420(crtc_state) && connector->ycbcr_420_allowed && drm_mode_is_420_also(&connector->display_info, adjusted_mode)) { crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; @@ -2221,7 +2225,7 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, if (ret) return ret; - if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { + if (intel_hdmi_is_ycbcr420(pipe_config)) { ret = intel_panel_fitting(pipe_config, conn_state); if (ret) return ret; From 59908256d8101da0f051a4687438b744b24b9059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 16:39:04 +0300 Subject: [PATCH 041/176] drm/i915/hdmi: Introduce intel_hdmi_tmds_clock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename intel_hdmi_port_clock() into intel_hdmi_tmds_clock(), and move the 4:2:0 TMDS clock halving into intel_hdmi_tmds_clock() so the callers don't have to worry about such details. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015133921.4609-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdmi.c | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 37ce8a6219736..e97c83535965f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1868,8 +1868,12 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, return MODE_OK; } -static int intel_hdmi_port_clock(int clock, int bpc) +static int intel_hdmi_tmds_clock(int clock, int bpc, bool ycbcr420_output) { + /* YCBCR420 TMDS rate requirement is half the pixel clock */ + if (ycbcr420_output) + clock /= 2; + /* * Need to adjust the port link by: * 1.5x for 12bpc @@ -1932,25 +1936,22 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); enum drm_mode_status status; - if (ycbcr420_output) - clock /= 2; - /* check if we can do 8bpc */ - status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 8), + status = hdmi_port_clock_valid(hdmi, intel_hdmi_tmds_clock(clock, 8, ycbcr420_output), true, has_hdmi_sink); /* if we can't do 8bpc we may still be able to do 12bpc */ if (status != MODE_OK && intel_hdmi_source_bpc_possible(i915, 12) && intel_hdmi_sink_bpc_possible(connector, 12, has_hdmi_sink, ycbcr420_output)) - status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 12), + status = hdmi_port_clock_valid(hdmi, intel_hdmi_tmds_clock(clock, 12, ycbcr420_output), true, has_hdmi_sink); /* if we can't do 8,12bpc we may still be able to do 10bpc */ if (status != MODE_OK && intel_hdmi_source_bpc_possible(i915, 10) && intel_hdmi_sink_bpc_possible(connector, 10, has_hdmi_sink, ycbcr420_output)) - status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 10), + status = hdmi_port_clock_valid(hdmi, intel_hdmi_tmds_clock(clock, 10, ycbcr420_output), true, has_hdmi_sink); return status; @@ -2057,12 +2058,13 @@ static int intel_hdmi_compute_bpc(struct intel_encoder *encoder, int clock) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + bool ycbcr420_output = intel_hdmi_is_ycbcr420(crtc_state); int bpc; for (bpc = 12; bpc >= 10; bpc -= 2) { if (hdmi_deep_color_possible(crtc_state, bpc) && hdmi_port_clock_valid(intel_hdmi, - intel_hdmi_port_clock(clock, bpc), + intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output), true, crtc_state->has_hdmi_sink) == MODE_OK) return bpc; } @@ -2082,13 +2084,10 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) clock *= 2; - /* YCBCR420 TMDS rate requirement is half the pixel clock */ - if (intel_hdmi_is_ycbcr420(crtc_state)) - clock /= 2; - bpc = intel_hdmi_compute_bpc(encoder, crtc_state, clock); - crtc_state->port_clock = intel_hdmi_port_clock(clock, bpc); + crtc_state->port_clock = intel_hdmi_tmds_clock(clock, bpc, + intel_hdmi_is_ycbcr420(crtc_state)); /* * pipe_bpp could already be below 8bpc due to From f4fdf37684ebf8ca122723ab6074d74299921064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 16:39:05 +0300 Subject: [PATCH 042/176] drm/i915/hdmi: Unify "4:2:0 also" logic between .mode_valid() and .compute_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently .mode_valid() and .compute_config() have their "4:2:0 also" logic inverted. Unify things so that we use the same logic on both sides. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015133921.4609-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdmi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index e97c83535965f..18e7ef1258278 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2179,12 +2179,13 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, ret = intel_hdmi_compute_clock(encoder, crtc_state); if (ret) { - if (!intel_hdmi_is_ycbcr420(crtc_state) && - connector->ycbcr_420_allowed && - drm_mode_is_420_also(&connector->display_info, adjusted_mode)) { - crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; - ret = intel_hdmi_compute_clock(encoder, crtc_state); - } + if (intel_hdmi_is_ycbcr420(crtc_state) || + !connector->ycbcr_420_allowed || + !drm_mode_is_420_also(&connector->display_info, adjusted_mode)) + return ret; + + crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; + ret = intel_hdmi_compute_clock(encoder, crtc_state); } return ret; From 81148c266f6a51f4e149afbc52fff9a04d274310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 15 Oct 2021 16:39:06 +0300 Subject: [PATCH 043/176] drm/i915/hdmi: Extract intel_hdmi_output_format() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganize the HDMI 4:2:0 handling a bit by introducing intel_hdmi_output_format(). We already have the DP counterpart and I want to unify the 4:2:0 handling across both a bit. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211015133921.4609-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdmi.c | 35 ++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 18e7ef1258278..7e6af959bf838 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2157,34 +2157,43 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder, return intel_conn_state->force_audio == HDMI_AUDIO_ON; } +static enum intel_output_format +intel_hdmi_output_format(struct intel_connector *connector, + bool ycbcr_420_output) +{ + if (connector->base.ycbcr_420_allowed && ycbcr_420_output) + return INTEL_OUTPUT_FORMAT_YCBCR420; + else + return INTEL_OUTPUT_FORMAT_RGB; +} + static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_connector *connector = conn_state->connector; - struct drm_i915_private *i915 = to_i915(connector->dev); + struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + const struct drm_display_info *info = &connector->base.display_info; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode); int ret; - bool ycbcr_420_only; - ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, adjusted_mode); - if (connector->ycbcr_420_allowed && ycbcr_420_only) { - crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; - } else { - if (!connector->ycbcr_420_allowed && ycbcr_420_only) - drm_dbg_kms(&i915->drm, - "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); + crtc_state->output_format = intel_hdmi_output_format(connector, ycbcr_420_only); + + if (ycbcr_420_only && !intel_hdmi_is_ycbcr420(crtc_state)) { + drm_dbg_kms(&i915->drm, + "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB; } ret = intel_hdmi_compute_clock(encoder, crtc_state); if (ret) { if (intel_hdmi_is_ycbcr420(crtc_state) || - !connector->ycbcr_420_allowed || - !drm_mode_is_420_also(&connector->display_info, adjusted_mode)) + !connector->base.ycbcr_420_allowed || + !drm_mode_is_420_also(info, adjusted_mode)) return ret; - crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; + crtc_state->output_format = intel_hdmi_output_format(connector, true); ret = intel_hdmi_compute_clock(encoder, crtc_state); } From 6eaecf014807f34acf1303fcdc35833998595db4 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 21 Oct 2021 11:18:47 -0700 Subject: [PATCH 044/176] drm/i915: remove CNL leftover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We left the definition IS_CANNONLAKE() macro while removing it from the tree due to having to merge the changes in different branches. Now that everything is back in sync and nobody is using IS_CANNONLAKE(), we can safely ditch it. Signed-off-by: Lucas De Marchi Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211021181847.1543341-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 12256218634f4..19e6700a4315b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1455,7 +1455,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_GEMINILAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_GEMINILAKE) #define IS_COFFEELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COFFEELAKE) #define IS_COMETLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COMETLAKE) -#define IS_CANNONLAKE(dev_priv) 0 #define IS_ICELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_ICELAKE) #define IS_JSL_EHL(dev_priv) (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE) || \ IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE)) From 877d074939a5f82b099da2db3bcccc6c418b9c39 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 21 Oct 2021 16:34:08 +0300 Subject: [PATCH 045/176] drm/i915/cdclk: put the cdclk vtables in const data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the const that was accidentally left out from the vtables. Fixes: 6b4cd9cba620 ("drm/i915: constify the cdclk vtable") Cc: Dave Airlie Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211021133408.32166-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_cdclk.c | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 9e466d829019a..868dd43a7542f 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2885,7 +2885,7 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) return freq; } -static struct intel_cdclk_funcs tgl_cdclk_funcs = { +static const struct intel_cdclk_funcs tgl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2893,7 +2893,7 @@ static struct intel_cdclk_funcs tgl_cdclk_funcs = { .calc_voltage_level = tgl_calc_voltage_level, }; -static struct intel_cdclk_funcs ehl_cdclk_funcs = { +static const struct intel_cdclk_funcs ehl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2901,7 +2901,7 @@ static struct intel_cdclk_funcs ehl_cdclk_funcs = { .calc_voltage_level = ehl_calc_voltage_level, }; -static struct intel_cdclk_funcs icl_cdclk_funcs = { +static const struct intel_cdclk_funcs icl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2909,7 +2909,7 @@ static struct intel_cdclk_funcs icl_cdclk_funcs = { .calc_voltage_level = icl_calc_voltage_level, }; -static struct intel_cdclk_funcs bxt_cdclk_funcs = { +static const struct intel_cdclk_funcs bxt_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2917,54 +2917,54 @@ static struct intel_cdclk_funcs bxt_cdclk_funcs = { .calc_voltage_level = bxt_calc_voltage_level, }; -static struct intel_cdclk_funcs skl_cdclk_funcs = { +static const struct intel_cdclk_funcs skl_cdclk_funcs = { .get_cdclk = skl_get_cdclk, .set_cdclk = skl_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = skl_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs bdw_cdclk_funcs = { +static const struct intel_cdclk_funcs bdw_cdclk_funcs = { .get_cdclk = bdw_get_cdclk, .set_cdclk = bdw_set_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = bdw_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs chv_cdclk_funcs = { +static const struct intel_cdclk_funcs chv_cdclk_funcs = { .get_cdclk = vlv_get_cdclk, .set_cdclk = chv_set_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = vlv_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs vlv_cdclk_funcs = { +static const struct intel_cdclk_funcs vlv_cdclk_funcs = { .get_cdclk = vlv_get_cdclk, .set_cdclk = vlv_set_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = vlv_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs hsw_cdclk_funcs = { +static const struct intel_cdclk_funcs hsw_cdclk_funcs = { .get_cdclk = hsw_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; /* SNB, IVB, 965G, 945G */ -static struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = { +static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = { .get_cdclk = fixed_400mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs ilk_cdclk_funcs = { +static const struct intel_cdclk_funcs ilk_cdclk_funcs = { .get_cdclk = fixed_450mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs gm45_cdclk_funcs = { +static const struct intel_cdclk_funcs gm45_cdclk_funcs = { .get_cdclk = gm45_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, @@ -2972,7 +2972,7 @@ static struct intel_cdclk_funcs gm45_cdclk_funcs = { /* G45 uses G33 */ -static struct intel_cdclk_funcs i965gm_cdclk_funcs = { +static const struct intel_cdclk_funcs i965gm_cdclk_funcs = { .get_cdclk = i965gm_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, @@ -2980,19 +2980,19 @@ static struct intel_cdclk_funcs i965gm_cdclk_funcs = { /* i965G uses fixed 400 */ -static struct intel_cdclk_funcs pnv_cdclk_funcs = { +static const struct intel_cdclk_funcs pnv_cdclk_funcs = { .get_cdclk = pnv_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs g33_cdclk_funcs = { +static const struct intel_cdclk_funcs g33_cdclk_funcs = { .get_cdclk = g33_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i945gm_cdclk_funcs = { +static const struct intel_cdclk_funcs i945gm_cdclk_funcs = { .get_cdclk = i945gm_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, @@ -3000,37 +3000,37 @@ static struct intel_cdclk_funcs i945gm_cdclk_funcs = { /* i945G uses fixed 400 */ -static struct intel_cdclk_funcs i915gm_cdclk_funcs = { +static const struct intel_cdclk_funcs i915gm_cdclk_funcs = { .get_cdclk = i915gm_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i915g_cdclk_funcs = { +static const struct intel_cdclk_funcs i915g_cdclk_funcs = { .get_cdclk = fixed_333mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i865g_cdclk_funcs = { +static const struct intel_cdclk_funcs i865g_cdclk_funcs = { .get_cdclk = fixed_266mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i85x_cdclk_funcs = { +static const struct intel_cdclk_funcs i85x_cdclk_funcs = { .get_cdclk = i85x_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i845g_cdclk_funcs = { +static const struct intel_cdclk_funcs i845g_cdclk_funcs = { .get_cdclk = fixed_200mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i830_cdclk_funcs = { +static const struct intel_cdclk_funcs i830_cdclk_funcs = { .get_cdclk = fixed_133mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, From c4ae82a0e9222d275e3e4dd91c1cc3931ac0eca1 Mon Sep 17 00:00:00 2001 From: He Ying Date: Thu, 21 Oct 2021 22:22:43 -0400 Subject: [PATCH 046/176] drm: Small optimization to intel_dp_mst_atomic_master_trans_check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we want to return from for_each_intel_connector_iter(), one way is calling drm_connector_list_iter_end() before returning to avoid memleak. The other way is just breaking from the bracket and then returning after the outside drm_connector_list_iter_end(). Obviously, the second way makes code smaller and more clear. Apply it to the function intel_dp_mst_atomic_master_trans_check(). Signed-off-by: He Ying Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022022243.138860-1-heying24@huawei.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 0de0b4ff4d731..16620172abf79 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -231,6 +231,7 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector, struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct drm_connector_list_iter connector_list_iter; struct intel_connector *connector_iter; + int ret = 0; if (DISPLAY_VER(dev_priv) < 12) return 0; @@ -243,7 +244,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector, struct intel_digital_connector_state *conn_iter_state; struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - int ret; if (connector_iter->mst_port != connector->mst_port || connector_iter == connector) @@ -252,8 +252,8 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector, conn_iter_state = intel_atomic_get_digital_connector_state(state, connector_iter); if (IS_ERR(conn_iter_state)) { - drm_connector_list_iter_end(&connector_list_iter); - return PTR_ERR(conn_iter_state); + ret = PTR_ERR(conn_iter_state); + break; } if (!conn_iter_state->base.crtc) @@ -262,20 +262,18 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector, crtc = to_intel_crtc(conn_iter_state->base.crtc); crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); if (IS_ERR(crtc_state)) { - drm_connector_list_iter_end(&connector_list_iter); - return PTR_ERR(crtc_state); + ret = PTR_ERR(crtc_state); + break; } ret = drm_atomic_add_affected_planes(&state->base, &crtc->base); - if (ret) { - drm_connector_list_iter_end(&connector_list_iter); - return ret; - } + if (ret) + break; crtc_state->uapi.mode_changed = true; } drm_connector_list_iter_end(&connector_list_iter); - return 0; + return ret; } static int From bf0d608b55d9b7f426031dfd9f08d9df36c94728 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 26 Oct 2021 12:34:07 +0300 Subject: [PATCH 047/176] drm/i915/dp: fix integer overflow in 128b/132b data rate calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intermediate value 1000000 * 10 * 9671 overflows 32 bits, so force promotion to a bigger type. From the logs: [drm:intel_dp_compute_config [i915]] DP link rate required 3657063 available -580783288 v2: Use mul_u32_u32() (Ville) Fixes: 48efd014f0ea ("drm/i915/dp: add max data rate calculation for UHBR rates") Cc: Manasi Navare Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211026093407.11381-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f5dc2126d1400..537c689a15286 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -352,7 +352,7 @@ intel_dp_max_data_rate(int max_link_rate, int max_lanes) */ int max_link_rate_kbps = max_link_rate * 10; - max_link_rate_kbps = DIV_ROUND_CLOSEST_ULL(max_link_rate_kbps * 9671, 10000); + max_link_rate_kbps = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(max_link_rate_kbps, 9671), 10000); max_link_rate = max_link_rate_kbps / 8; } From fed98c16f13f4c68fc507384d3429516ef5c3b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Tue, 5 Oct 2021 16:18:51 -0700 Subject: [PATCH 048/176] drm/i915/display: Wait PSR2 get out of deep sleep to update pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alderlake-P was getting 'max time under evasion' messages when PSR2 is enabled, this is due PIPE_SCANLINE/PIPEDSL returning 0 over a period of time longer than VBLANK_EVASION_TIME_US. For PSR1 we had the same issue so intel_psr_wait_for_idle() was implemented to wait for PSR1 to get into idle state but nothing was done for PSR2. For PSR2 we can't only wait for idle state as PSR2 tends to keep into sleep state(ready to send selective updates). Waiting for any state below deep sleep proved to be effective in avoiding the evasion messages and also not wasted a lot of time. v2: - dropping the additional wait_for loops, only the _wait_for_atomic() is necessary - waiting for states below EDP_PSR2_STATUS_STATE_DEEP_SLEEP v3: - dropping intel_wait_for_condition_atomic() function Cc: Ville Syrjälä Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza Reviewed-by: Gwan-gyeong Mun Link: https://patchwork.freedesktop.org/patch/msgid/20211005231851.67698-1-jose.souza@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 3 +- drivers/gpu/drm/i915/display/intel_psr.c | 52 +++++++++++-------- drivers/gpu/drm/i915/i915_reg.h | 10 ++-- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index e04767695530d..d7d6dde518a31 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -303,8 +303,7 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m) }; val = intel_de_read(dev_priv, EDP_PSR2_STATUS(intel_dp->psr.transcoder)); - status_val = (val & EDP_PSR2_STATUS_STATE_MASK) >> - EDP_PSR2_STATUS_STATE_SHIFT; + status_val = REG_FIELD_GET(EDP_PSR2_STATUS_STATE_MASK, val); if (status_val < ARRAY_SIZE(live_status)) status = live_status[status_val]; } else { diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index ccffe05784d3c..d35db50ef967a 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1813,15 +1813,21 @@ void intel_psr_post_plane_update(const struct intel_atomic_state *state) _intel_psr_post_plane_update(state, crtc_state); } -/** - * psr_wait_for_idle - wait for PSR1 to idle - * @intel_dp: Intel DP - * @out_value: PSR status in case of failure - * - * Returns: 0 on success or -ETIMEOUT if PSR status does not idle. - * - */ -static int psr_wait_for_idle(struct intel_dp *intel_dp, u32 *out_value) +static int _psr2_ready_for_pipe_update_locked(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + /* + * Any state lower than EDP_PSR2_STATUS_STATE_DEEP_SLEEP is enough. + * As all higher states has bit 4 of PSR2 state set we can just wait for + * EDP_PSR2_STATUS_STATE_DEEP_SLEEP to be cleared. + */ + return intel_de_wait_for_clear(dev_priv, + EDP_PSR2_STATUS(intel_dp->psr.transcoder), + EDP_PSR2_STATUS_STATE_DEEP_SLEEP, 50); +} + +static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1831,15 +1837,13 @@ static int psr_wait_for_idle(struct intel_dp *intel_dp, u32 *out_value) * exit training time + 1.5 ms of aux channel handshake. 50 ms is * defensive enough to cover everything. */ - return __intel_wait_for_register(&dev_priv->uncore, - EDP_PSR_STATUS(intel_dp->psr.transcoder), - EDP_PSR_STATUS_STATE_MASK, - EDP_PSR_STATUS_STATE_IDLE, 2, 50, - out_value); + return intel_de_wait_for_clear(dev_priv, + EDP_PSR_STATUS(intel_dp->psr.transcoder), + EDP_PSR_STATUS_STATE_MASK, 50); } /** - * intel_psr_wait_for_idle - wait for PSR1 to idle + * intel_psr_wait_for_idle - wait for PSR be ready for a pipe update * @new_crtc_state: new CRTC state * * This function is expected to be called from pipe_update_start() where it is @@ -1856,19 +1860,23 @@ void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state) for_each_intel_encoder_mask_with_psr(&dev_priv->drm, encoder, new_crtc_state->uapi.encoder_mask) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - u32 psr_status; + int ret; mutex_lock(&intel_dp->psr.lock); - if (!intel_dp->psr.enabled || intel_dp->psr.psr2_enabled) { + + if (!intel_dp->psr.enabled) { mutex_unlock(&intel_dp->psr.lock); continue; } - /* when the PSR1 is enabled */ - if (psr_wait_for_idle(intel_dp, &psr_status)) - drm_err(&dev_priv->drm, - "PSR idle timed out 0x%x, atomic update may fail\n", - psr_status); + if (intel_dp->psr.psr2_enabled) + ret = _psr2_ready_for_pipe_update_locked(intel_dp); + else + ret = _psr1_ready_for_pipe_update_locked(intel_dp); + + if (ret) + drm_err(&dev_priv->drm, "PSR wait timed out, atomic update may fail\n"); + mutex_unlock(&intel_dp->psr.lock); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d9f7a729333fa..7c97bc352497d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4698,11 +4698,11 @@ enum { #define PSR_EVENT_LPSP_MODE_EXIT (1 << 1) #define PSR_EVENT_PSR_DISABLE (1 << 0) -#define _PSR2_STATUS_A 0x60940 -#define _PSR2_STATUS_EDP 0x6f940 -#define EDP_PSR2_STATUS(tran) _MMIO_TRANS2(tran, _PSR2_STATUS_A) -#define EDP_PSR2_STATUS_STATE_MASK (0xf << 28) -#define EDP_PSR2_STATUS_STATE_SHIFT 28 +#define _PSR2_STATUS_A 0x60940 +#define _PSR2_STATUS_EDP 0x6f940 +#define EDP_PSR2_STATUS(tran) _MMIO_TRANS2(tran, _PSR2_STATUS_A) +#define EDP_PSR2_STATUS_STATE_MASK REG_GENMASK(31, 28) +#define EDP_PSR2_STATUS_STATE_DEEP_SLEEP REG_FIELD_PREP(EDP_PSR2_STATUS_STATE_MASK, 0x8) #define _PSR2_SU_STATUS_A 0x60914 #define _PSR2_SU_STATUS_EDP 0x6f914 From f0e204e0d32159d783577a4041331fbe49e8beca Mon Sep 17 00:00:00 2001 From: "Mullati, Siva" Date: Sat, 23 Oct 2021 00:57:56 +0530 Subject: [PATCH 049/176] drm/i915: abstraction for iosf to compile on all archs The asm/iosf_mbi.h header is x86-only. Let's make IOSF_MBI kconfig selection conditional to x86 and provide a header with stubs for other architectures. This helps getting i915 available for other architectures in future. Signed-off-by: Mullati, Siva Reviewed-by: Lucas De Marchi Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20211022192756.1228354-1-siva.mullati@intel.com --- drivers/gpu/drm/i915/Kconfig | 2 +- drivers/gpu/drm/i915/i915_iosf_mbi.h | 42 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_uncore.c | 2 +- drivers/gpu/drm/i915/vlv_sideband.c | 3 +- 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_iosf_mbi.h diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index bf041b26ffec3..8bea99622dd58 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -21,7 +21,7 @@ config DRM_I915 select ACPI_VIDEO if ACPI select ACPI_BUTTON if ACPI select SYNC_FILE - select IOSF_MBI + select IOSF_MBI if X86 select CRC32 select SND_HDA_I915 if SND_HDA_CORE select CEC_CORE if CEC_NOTIFIER diff --git a/drivers/gpu/drm/i915/i915_iosf_mbi.h b/drivers/gpu/drm/i915/i915_iosf_mbi.h new file mode 100644 index 0000000000000..8f81b7603d374 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_iosf_mbi.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __I915_IOSF_MBI_H__ +#define __I915_IOSF_MBI_H__ + +#if IS_ENABLED(CONFIG_IOSF_MBI) +#include +#else + +/* Stubs to compile for all non-x86 archs */ +#define MBI_PMIC_BUS_ACCESS_BEGIN 1 +#define MBI_PMIC_BUS_ACCESS_END 2 + +struct notifier_block; + +static inline void iosf_mbi_punit_acquire(void) {} +static inline void iosf_mbi_punit_release(void) {} +static inline void iosf_mbi_assert_punit_acquired(void) {} + +static inline +int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb) +{ + return 0; +} + +static inline int +iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(struct notifier_block *nb) +{ + return 0; +} + +static inline +int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) +{ + return 0; +} +#endif + +#endif /* __I915_IOSF_MBI_H__ */ diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index e072054adac57..722910d02b5ff 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -22,11 +22,11 @@ */ #include -#include #include "gt/intel_lrc_reg.h" /* for shadow reg list */ #include "i915_drv.h" +#include "i915_iosf_mbi.h" #include "i915_trace.h" #include "i915_vgpu.h" #include "intel_pm.h" diff --git a/drivers/gpu/drm/i915/vlv_sideband.c b/drivers/gpu/drm/i915/vlv_sideband.c index 35380738a9518..ed2ac5752ac4d 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.c +++ b/drivers/gpu/drm/i915/vlv_sideband.c @@ -3,9 +3,8 @@ * Copyright © 2013-2021 Intel Corporation */ -#include - #include "i915_drv.h" +#include "i915_iosf_mbi.h" #include "vlv_sideband.h" /* From 765972cb8564fb92f8cef6fac21995907d132e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:32:56 +0300 Subject: [PATCH 050/176] drm/i915/psr: Disable PSR before modesets turn off all planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PSR2 apparently requires some planes to be enabled for some silly reason, and so we are now trying to turn PSR off before planes go off. Except during a full modeset that is handled less clearly through reorganization of the modeset sequence. That is not great as it makes the code mode complex, and prevents us from doing nice things such as just turning off all the planes at the very start of the modeset. So let's move the PSR pre_plane_update() thing to a spot where it will handle both full modesets and everything else. Cc: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-2-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/intel_display.c | 3 ++- drivers/gpu/drm/i915/display/intel_psr.c | 25 +++++++------------- drivers/gpu/drm/i915/display/intel_psr.h | 3 ++- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2b97c87971773..5201d6cdd5dbc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1429,6 +1429,8 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; + intel_psr_pre_plane_update(state, crtc); + if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state)) hsw_disable_ips(old_crtc_state); @@ -8668,7 +8670,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_encoders_update_prepare(state); intel_dbuf_pre_plane_update(state); - intel_psr_pre_plane_update(state); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->uapi.async_flip) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d35db50ef967a..8d08e3cf08c1f 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1725,11 +1725,17 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, return 0; } -static void _intel_psr_pre_plane_update(const struct intel_atomic_state *state, - const struct intel_crtc_state *crtc_state) +void intel_psr_pre_plane_update(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_encoder *encoder; + if (!HAS_PSR(i915)) + return; + for_each_intel_encoder_mask_with_psr(state->base.dev, encoder, crtc_state->uapi.encoder_mask) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1744,6 +1750,7 @@ static void _intel_psr_pre_plane_update(const struct intel_atomic_state *state, * - All planes will go inactive * - Changing between PSR versions */ + needs_to_disable |= intel_crtc_needs_modeset(crtc_state); needs_to_disable |= !crtc_state->has_psr; needs_to_disable |= !crtc_state->active_planes; needs_to_disable |= crtc_state->has_psr2 != psr->psr2_enabled; @@ -1755,20 +1762,6 @@ static void _intel_psr_pre_plane_update(const struct intel_atomic_state *state, } } -void intel_psr_pre_plane_update(const struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct intel_crtc_state *crtc_state; - struct intel_crtc *crtc; - int i; - - if (!HAS_PSR(dev_priv)) - return; - - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) - _intel_psr_pre_plane_update(state, crtc_state); -} - static void _intel_psr_post_plane_update(const struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index facffbacd3575..3d9c0e13c3296 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -20,7 +20,8 @@ struct intel_plane; struct intel_encoder; void intel_psr_init_dpcd(struct intel_dp *intel_dp); -void intel_psr_pre_plane_update(const struct intel_atomic_state *state); +void intel_psr_pre_plane_update(struct intel_atomic_state *state, + struct intel_crtc *crtc); void intel_psr_post_plane_update(const struct intel_atomic_state *state); void intel_psr_disable(struct intel_dp *intel_dp, const struct intel_crtc_state *old_crtc_state); From f28c5950d57b280f17b950f04125ed556252403e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:32:57 +0300 Subject: [PATCH 051/176] Revert "drm/i915/display: Disable audio, DRRS and PSR before planes" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disabling planes in the middle of the modeset seuqnece does not make sense since userspace can anyway disable planes before the modeset even starts. So when the modeset seuqence starts the set of enabled planes is entirely arbitrary. Trying to sprinkle the plane disabling into the modeset sequence just means more randomness and potential for hard to reproduce bugs. So it makes most sense to just disable all planes first so that the rest of the modeset sequence remains identical regardless of which planes happen to be enabled by userspace at the time. This reverts commit 84030adb9e27d202a66022488bf0349a8bd45213. Cc: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 30 +++++++------------ drivers/gpu/drm/i915/display/intel_display.c | 24 --------------- .../drm/i915/display/intel_display_types.h | 4 --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 14 ++------- 4 files changed, 13 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index ab52eab346fe9..6c11992496f26 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3061,6 +3061,12 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state, intel_dp->link_trained = false; + if (old_crtc_state->has_audio) + intel_audio_codec_disable(encoder, + old_crtc_state, old_conn_state); + + intel_drrs_disable(intel_dp, old_crtc_state); + intel_psr_disable(intel_dp, old_crtc_state); intel_edp_backlight_off(old_conn_state); /* Disable the decompression in DP Sink */ intel_dp_sink_set_decompression_state(intel_dp, old_crtc_state, @@ -3078,6 +3084,10 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct drm_connector *connector = old_conn_state->connector; + if (old_crtc_state->has_audio) + intel_audio_codec_disable(encoder, + old_crtc_state, old_conn_state); + if (!intel_hdmi_handle_sink_scrambling(encoder, connector, false, false)) drm_dbg_kms(&i915->drm, @@ -3085,25 +3095,6 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state, connector->base.id, connector->name); } -static void intel_pre_disable_ddi(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - struct intel_dp *intel_dp; - - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, old_crtc_state, - old_conn_state); - - if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) - return; - - intel_dp = enc_to_intel_dp(encoder); - intel_drrs_disable(intel_dp, old_crtc_state); - intel_psr_disable(intel_dp, old_crtc_state); -} - static void intel_disable_ddi(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, @@ -4437,7 +4428,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->enable = intel_enable_ddi; encoder->pre_pll_enable = intel_ddi_pre_pll_enable; encoder->pre_enable = intel_ddi_pre_enable; - encoder->pre_disable = intel_pre_disable_ddi; encoder->disable = intel_disable_ddi; encoder->post_disable = intel_ddi_post_disable; encoder->update_pipe = intel_ddi_update_pipe; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5201d6cdd5dbc..3d2a1cba78c15 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1693,28 +1693,6 @@ static void intel_encoders_enable(struct intel_atomic_state *state, } } -static void intel_encoders_pre_disable(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - const struct drm_connector_state *old_conn_state; - struct drm_connector *conn; - int i; - - for_each_old_connector_in_state(&state->base, conn, old_conn_state, i) { - struct intel_encoder *encoder = - to_intel_encoder(old_conn_state->best_encoder); - - if (old_conn_state->crtc != &crtc->base) - continue; - - if (encoder->pre_disable) - encoder->pre_disable(state, encoder, old_crtc_state, - old_conn_state); - } -} - static void intel_encoders_disable(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -8273,8 +8251,6 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave); - intel_encoders_pre_disable(state, crtc); - intel_crtc_disable_planes(state, crtc); /* diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 85cb55034bb02..3568d33be096b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -194,10 +194,6 @@ struct intel_encoder { void (*update_complete)(struct intel_atomic_state *, struct intel_encoder *, struct intel_crtc *); - void (*pre_disable)(struct intel_atomic_state *, - struct intel_encoder *, - const struct intel_crtc_state *, - const struct drm_connector_state *); void (*disable)(struct intel_atomic_state *, struct intel_encoder *, const struct intel_crtc_state *, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 16620172abf79..a3faea3201054 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -346,16 +346,6 @@ static void wait_for_act_sent(struct intel_encoder *encoder, drm_dp_check_act_status(&intel_dp->mst_mgr); } -static void intel_mst_pre_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, old_crtc_state, - old_conn_state); -} - static void intel_mst_disable_dp(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, @@ -380,6 +370,9 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, if (ret) { drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret); } + if (old_crtc_state->has_audio) + intel_audio_codec_disable(encoder, + old_crtc_state, old_conn_state); } static void intel_mst_post_disable_dp(struct intel_atomic_state *state, @@ -914,7 +907,6 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe intel_encoder->compute_config = intel_dp_mst_compute_config; intel_encoder->compute_config_late = intel_dp_mst_compute_config_late; - intel_encoder->pre_disable = intel_mst_pre_disable_dp; intel_encoder->disable = intel_mst_disable_dp; intel_encoder->post_disable = intel_mst_post_disable_dp; intel_encoder->update_pipe = intel_ddi_update_pipe; From 39919997322f21d367347943ffd5ba8c4007c9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:32:58 +0300 Subject: [PATCH 052/176] drm/i915: Disable all planes before modesetting any pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's disable planes on all pipes affected by the modeset before we start doing the actual modeset. This means we have less random planes enabled during the modeset, and it also mirrors what we already do when enabling pipes on skl+ since we enable planes on all pipes as the very last step. As a bonus we also nuke a bunch og bigjoiner special casing. I've occasionally pondered about going even furher here and doing the pre_plane_update() stuff for all pipes first, then actually disabling the planes, and finally running the rest of the modeset sequence. This would potentially allow parallelizing all the extra vblank waits across multiple pipes, and would make the plane disable even more atomic. But let's go one step a time here. Cc: José Roberto de Souza Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 28 +++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3d2a1cba78c15..1d920ba83521a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8251,18 +8251,13 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave); - intel_crtc_disable_planes(state, crtc); - /* * We still need special handling for disabling bigjoiner master * and slaves since for slave we do not have encoder or plls * so we dont need to disable those. */ - if (old_crtc_state->bigjoiner) { - intel_crtc_disable_planes(state, - old_crtc_state->bigjoiner_linked_crtc); + if (old_crtc_state->bigjoiner) old_crtc_state->bigjoiner_linked_crtc->active = false; - } /* * We need to disable pipe CRC before disabling the pipe, @@ -8288,6 +8283,18 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) u32 handled = 0; int i; + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + if (!intel_crtc_needs_modeset(new_crtc_state)) + continue; + + if (!old_crtc_state->hw.active) + continue; + + intel_pre_plane_update(state, crtc); + intel_crtc_disable_planes(state, crtc); + } + /* Only disable port sync and MST slaves */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -8306,7 +8313,6 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) !intel_dp_mst_is_slave_trans(old_crtc_state)) continue; - intel_pre_plane_update(state, crtc); intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, crtc); handled |= BIT(crtc->pipe); @@ -8320,14 +8326,6 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) old_crtc_state->bigjoiner_slave) continue; - intel_pre_plane_update(state, crtc); - if (old_crtc_state->bigjoiner) { - struct intel_crtc *slave = - old_crtc_state->bigjoiner_linked_crtc; - - intel_pre_plane_update(state, slave); - } - if (old_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, crtc); From f2e19b586637a2e84f56b08d9f60de30373a0a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:32:59 +0300 Subject: [PATCH 053/176] drm/i915: Introduce intel_master_crtc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper to determine the master crtc for bigjoiner usage. Also name the variables consistently. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 6 +-- drivers/gpu/drm/i915/display/intel_display.c | 57 +++++++++++--------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 6c11992496f26..f8d07689d20cc 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2825,12 +2825,10 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, } if (old_crtc_state->bigjoiner_linked_crtc) { - struct intel_atomic_state *state = - to_intel_atomic_state(old_crtc_state->uapi.state); - struct intel_crtc *slave = + struct intel_crtc *slave_crtc = old_crtc_state->bigjoiner_linked_crtc; const struct intel_crtc_state *old_slave_crtc_state = - intel_atomic_get_old_crtc_state(state, slave); + intel_atomic_get_old_crtc_state(state, slave_crtc); intel_crtc_vblank_off(old_slave_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1d920ba83521a..640d87a00e159 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -335,6 +335,14 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state) is_trans_port_sync_slave(crtc_state); } +static struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->bigjoiner_slave) + return crtc_state->bigjoiner_linked_crtc; + else + return to_intel_crtc(crtc_state->uapi.crtc); +} + static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, enum pipe pipe) { @@ -1947,21 +1955,19 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(master->base.dev); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *master_crtc_state; + struct intel_crtc *master_crtc; struct drm_connector_state *conn_state; struct drm_connector *conn; struct intel_encoder *encoder = NULL; int i; - if (crtc_state->bigjoiner_slave) - master = crtc_state->bigjoiner_linked_crtc; - - master_crtc_state = intel_atomic_get_new_crtc_state(state, master); + master_crtc = intel_master_crtc(crtc_state); + master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); for_each_new_connector_in_state(&state->base, conn, conn_state, i) { - if (conn_state->crtc != &master->base) + if (conn_state->crtc != &master_crtc->base) continue; encoder = to_intel_encoder(conn_state->best_encoder); @@ -1975,10 +1981,10 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, /* * Enable sequence steps 1-7 on bigjoiner master */ - intel_encoders_pre_pll_enable(state, master); + intel_encoders_pre_pll_enable(state, master_crtc); if (master_crtc_state->shared_dpll) intel_enable_shared_dpll(master_crtc_state); - intel_encoders_pre_enable(state, master); + intel_encoders_pre_enable(state, master_crtc); /* and DSC on slave */ intel_dsc_enable(NULL, crtc_state); @@ -6877,7 +6883,7 @@ verify_crtc_state(struct intel_crtc *crtc, struct intel_encoder *encoder; struct intel_crtc_state *pipe_config = old_crtc_state; struct drm_atomic_state *state = old_crtc_state->uapi.state; - struct intel_crtc *master = crtc; + struct intel_crtc *master_crtc; __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); intel_crtc_free_hw_state(old_crtc_state); @@ -6905,10 +6911,9 @@ verify_crtc_state(struct intel_crtc *crtc, "(expected %i, found %i)\n", new_crtc_state->hw.active, crtc->active); - if (new_crtc_state->bigjoiner_slave) - master = new_crtc_state->bigjoiner_linked_crtc; + master_crtc = intel_master_crtc(new_crtc_state); - for_each_encoder_on_crtc(dev, &master->base, encoder) { + for_each_encoder_on_crtc(dev, &master_crtc->base, encoder) { enum pipe pipe; bool active; @@ -6918,7 +6923,7 @@ verify_crtc_state(struct intel_crtc *crtc, encoder->base.base.id, active, new_crtc_state->hw.active); - I915_STATE_WARN(active && master->pipe != pipe, + I915_STATE_WARN(active && master_crtc->pipe != pipe, "Encoder connected to wrong pipe %c\n", pipe_name(pipe)); @@ -7590,13 +7595,13 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, struct intel_crtc_state *new_crtc_state) { struct intel_crtc_state *slave_crtc_state, *master_crtc_state; - struct intel_crtc *slave, *master; + struct intel_crtc *slave_crtc, *master_crtc; /* slave being enabled, is master is still claiming this crtc? */ if (old_crtc_state->bigjoiner_slave) { - slave = crtc; - master = old_crtc_state->bigjoiner_linked_crtc; - master_crtc_state = intel_atomic_get_new_crtc_state(state, master); + slave_crtc = crtc; + master_crtc = old_crtc_state->bigjoiner_linked_crtc; + master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); if (!master_crtc_state || !intel_crtc_needs_modeset(master_crtc_state)) goto claimed; } @@ -7604,17 +7609,17 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, if (!new_crtc_state->bigjoiner) return 0; - slave = intel_dsc_get_bigjoiner_secondary(crtc); - if (!slave) { + slave_crtc = intel_dsc_get_bigjoiner_secondary(crtc); + if (!slave_crtc) { DRM_DEBUG_KMS("[CRTC:%d:%s] Big joiner configuration requires " "CRTC + 1 to be used, doesn't exist\n", crtc->base.base.id, crtc->base.name); return -EINVAL; } - new_crtc_state->bigjoiner_linked_crtc = slave; - slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave); - master = crtc; + new_crtc_state->bigjoiner_linked_crtc = slave_crtc; + slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave_crtc); + master_crtc = crtc; if (IS_ERR(slave_crtc_state)) return PTR_ERR(slave_crtc_state); @@ -7623,15 +7628,15 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, goto claimed; DRM_DEBUG_KMS("[CRTC:%d:%s] Used as slave for big joiner\n", - slave->base.base.id, slave->base.name); + slave_crtc->base.base.id, slave_crtc->base.name); return copy_bigjoiner_crtc_state(slave_crtc_state, new_crtc_state); claimed: DRM_DEBUG_KMS("[CRTC:%d:%s] Slave is enabled as normal CRTC, but " "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n", - slave->base.base.id, slave->base.name, - master->base.base.id, master->base.name); + slave_crtc->base.base.id, slave_crtc->base.name, + master_crtc->base.base.id, master_crtc->base.name); return -EINVAL; } From e0bf3e23e2002461b0bff09c1cc0b92ddb8eafd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:33:00 +0300 Subject: [PATCH 054/176] drm/i915: Simplify intel_crtc_copy_uapi_to_hw_state_nomodeset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite intel_crtc_copy_uapi_to_hw_state_nomodeset() in a slightly more straightforward manner. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 640d87a00e159..e745eb4650e4b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5762,18 +5762,15 @@ static void intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - const struct intel_crtc_state *from_crtc_state = crtc_state; - - if (crtc_state->bigjoiner_slave) { - from_crtc_state = intel_atomic_get_new_crtc_state(state, - crtc_state->bigjoiner_linked_crtc); + const struct intel_crtc_state *master_crtc_state; + struct intel_crtc *master_crtc; - /* No need to copy state if the master state is unchanged */ - if (!from_crtc_state) - return; - } + master_crtc = intel_master_crtc(crtc_state); + master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); - intel_crtc_copy_color_blobs(crtc_state, from_crtc_state); + /* No need to copy state if the master state is unchanged */ + if (master_crtc_state) + intel_crtc_copy_color_blobs(crtc_state, master_crtc_state); } static void From 3126977d43079866aa0ea351863a7496feec98d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:33:01 +0300 Subject: [PATCH 055/176] drm/i915: Split PPS write from DSC enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PPS SDP is fed into the transcoder whereas the DSC block is (or at least can be) per pipe. Let's split these into two distinct operations in an effort to untagle the bigjoiner mess where we have two pipes feeding a single transcoder. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 6 ++-- drivers/gpu/drm/i915/display/intel_ddi.c | 14 +++++++-- drivers/gpu/drm/i915/display/intel_display.c | 5 ++- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 33 +++++++++----------- drivers/gpu/drm/i915/display/intel_vdsc.h | 10 +++--- 6 files changed, 39 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 168c84a74d30b..19167efae07ab 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1232,7 +1232,9 @@ static void gen11_dsi_pre_enable(struct intel_atomic_state *state, /* step5: program and powerup panel */ gen11_dsi_powerup_panel(encoder); - intel_dsc_enable(encoder, pipe_config); + intel_dsc_dsi_pps_write(encoder, pipe_config); + + intel_dsc_enable(pipe_config); /* step6c: configure transcoder timings */ gen11_dsi_set_transcoder_timings(encoder, pipe_config); @@ -1628,7 +1630,7 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder, /* FIXME: initialize from VBT */ vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST; - ret = intel_dsc_compute_params(encoder, crtc_state); + ret = intel_dsc_compute_params(crtc_state); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index f8d07689d20cc..8b4ef9ef77fba 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2386,7 +2386,10 @@ static void dg2_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 5.k Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); - intel_dsc_enable(encoder, crtc_state); + + intel_dsc_dp_pps_write(encoder, crtc_state); + + intel_dsc_enable(crtc_state); } static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, @@ -2520,8 +2523,11 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 7.l Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); + + intel_dsc_dp_pps_write(encoder, crtc_state); + if (!crtc_state->bigjoiner) - intel_dsc_enable(encoder, crtc_state); + intel_dsc_enable(crtc_state); } static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, @@ -2586,8 +2592,10 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, if (!is_mst) intel_ddi_enable_pipe_clock(encoder, crtc_state); + intel_dsc_dp_pps_write(encoder, crtc_state); + if (!crtc_state->bigjoiner) - intel_dsc_enable(encoder, crtc_state); + intel_dsc_enable(crtc_state); } static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e745eb4650e4b..6a8da98ad60a6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1976,7 +1976,7 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, if (!crtc_state->bigjoiner_slave) { /* need to enable VDSC, which we skipped in pre-enable */ - intel_dsc_enable(encoder, crtc_state); + intel_dsc_enable(crtc_state); } else { /* * Enable sequence steps 1-7 on bigjoiner master @@ -1986,8 +1986,7 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, intel_enable_shared_dpll(master_crtc_state); intel_encoders_pre_enable(state, master_crtc); - /* and DSC on slave */ - intel_dsc_enable(NULL, crtc_state); + intel_dsc_enable(crtc_state); } if (DISPLAY_VER(dev_priv) >= 13) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 537c689a15286..6d5988f0f067c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1345,7 +1345,7 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, else vdsc_cfg->slice_height = 2; - ret = intel_dsc_compute_params(encoder, crtc_state); + ret = intel_dsc_compute_params(crtc_state); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 2275f99ce9d7e..fa84be609d5d2 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -442,10 +442,10 @@ calculate_rc_params(struct rc_parameters *rc, } } -int intel_dsc_compute_params(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) +int intel_dsc_compute_params(struct intel_crtc_state *pipe_config) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config; u16 compressed_bpp = pipe_config->dsc.compressed_bpp; const struct rc_parameters *rc_params; @@ -1055,8 +1055,8 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) } } -static void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); @@ -1064,6 +1064,9 @@ static void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, struct drm_dsc_picture_parameter_set pps; enum port port; + if (!crtc_state->dsc.compression_enable) + return; + drm_dsc_pps_payload_pack(&pps, vdsc_cfg); for_each_dsi_port(port, intel_dsi->ports) { @@ -1074,14 +1077,16 @@ static void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, } } -static void intel_dsc_dp_pps_write(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +void intel_dsc_dp_pps_write(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; struct drm_dsc_pps_infoframe dp_dsc_pps_sdp; + if (!crtc_state->dsc.compression_enable) + return; + /* Prepare DP SDP PPS header as per DP 1.4 spec, Table 2-123 */ drm_dsc_dp_pps_header_init(&dp_dsc_pps_sdp.pps_header); @@ -1142,8 +1147,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state) } } -void intel_dsc_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +void intel_dsc_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -1155,13 +1159,6 @@ void intel_dsc_enable(struct intel_encoder *encoder, intel_dsc_pps_configure(crtc_state); - if (!crtc_state->bigjoiner_slave) { - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) - intel_dsc_dsi_pps_write(encoder, crtc_state); - else - intel_dsc_dp_pps_write(encoder, crtc_state); - } - dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE; if (crtc_state->dsc.dsc_split) { dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index 0c5d80a572daf..4ec75f7159869 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -15,15 +15,17 @@ struct intel_encoder; bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state); void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state); -void intel_dsc_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state); +void intel_dsc_enable(const struct intel_crtc_state *crtc_state); void intel_dsc_disable(const struct intel_crtc_state *crtc_state); -int intel_dsc_compute_params(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config); +int intel_dsc_compute_params(struct intel_crtc_state *pipe_config); void intel_uncompressed_joiner_get_config(struct intel_crtc_state *crtc_state); void intel_dsc_get_config(struct intel_crtc_state *crtc_state); enum intel_display_power_domain intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder); struct intel_crtc *intel_dsc_get_bigjoiner_secondary(const struct intel_crtc *primary_crtc); +void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); +void intel_dsc_dp_pps_write(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); #endif /* __INTEL_VDSC_H__ */ From 723559f379af5cd200bc981a723aaf3971f7a166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:33:02 +0300 Subject: [PATCH 056/176] drm/i915: Perform correct cpu_transcoder readout for bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read out cpu_transcoder correctly for the bigjoiner slave pipes. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 66 ++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6a8da98ad60a6..753f443e74bd6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4064,6 +4064,16 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, return ret; } +static u8 bigjoiner_pipes(struct drm_i915_private *i915) +{ + if (DISPLAY_VER(i915) >= 12) + return BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D); + else if (DISPLAY_VER(i915) >= 11) + return BIT(PIPE_B) | BIT(PIPE_C); + else + return 0; +} + static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { @@ -4079,6 +4089,54 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv, return tmp & TRANS_DDI_FUNC_ENABLE; } +static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv) +{ + u8 master_pipes = 0, slave_pipes = 0; + struct intel_crtc *crtc; + + for_each_intel_crtc(&dev_priv->drm, crtc) { + enum intel_display_power_domain power_domain; + enum pipe pipe = crtc->pipe; + intel_wakeref_t wakeref; + + if ((bigjoiner_pipes(dev_priv) & BIT(pipe)) == 0) + continue; + + power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe); + with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) { + u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); + + if (!(tmp & BIG_JOINER_ENABLE)) + continue; + + if (tmp & MASTER_BIG_JOINER_ENABLE) + master_pipes |= BIT(pipe); + else + slave_pipes |= BIT(pipe); + } + + if (DISPLAY_VER(dev_priv) < 13) + continue; + + power_domain = POWER_DOMAIN_PIPE(pipe); + with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) { + u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); + + if (tmp & UNCOMPRESSED_JOINER_MASTER) + master_pipes |= BIT(pipe); + if (tmp & UNCOMPRESSED_JOINER_SLAVE) + slave_pipes |= BIT(pipe); + } + } + + /* Bigjoiner pipes should always be consecutive master and slave */ + drm_WARN(&dev_priv->drm, slave_pipes != master_pipes << 1, + "Bigjoiner misconfigured (master pipes 0x%x, slave pipes 0x%x)\n", + master_pipes, slave_pipes); + + return slave_pipes; +} + static u8 hsw_panel_transcoders(struct drm_i915_private *i915) { u8 panel_transcoder_mask = BIT(TRANSCODER_EDP); @@ -4140,10 +4198,18 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) enabled_transcoders |= BIT(cpu_transcoder); } + /* single pipe or bigjoiner master */ cpu_transcoder = (enum transcoder) crtc->pipe; if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) enabled_transcoders |= BIT(cpu_transcoder); + /* bigjoiner slave -> consider the master pipe's transcoder as well */ + if (enabled_bigjoiner_pipes(dev_priv) & BIT(crtc->pipe)) { + cpu_transcoder = (enum transcoder) crtc->pipe - 1; + if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) + enabled_transcoders |= BIT(cpu_transcoder); + } + return enabled_transcoders; } From e12d6218fda20d03960f3f2cca44741ba8d5e9a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:33:03 +0300 Subject: [PATCH 057/176] drm/i915: Reduce bigjoiner special casing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Try to make bigjoiner pipes less special. The main things here are that each pipe now does full clock computation/readout with its own shared_dpll reference. Also every pipe's cpu_transcoder always points correctly at the master transcoder. Due to the above changes state readout is now complete and all the related hacks can go away. The actual modeset sequence code is still a mess, but I think in order to clean that up properly we're probably going to have to redesign the modeset logic to treat transcoders vs. pipes separately. That is going to require significant amounts of work. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 16 +-- drivers/gpu/drm/i915/display/intel_display.c | 136 ++++++------------- 2 files changed, 41 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 8b4ef9ef77fba..9fb99b09fff8b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3515,18 +3515,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder))) return; - if (pipe_config->bigjoiner_slave) { - /* read out pipe settings from master */ - enum transcoder save = pipe_config->cpu_transcoder; - - /* Our own transcoder needs to be disabled when reading it in intel_ddi_read_func_ctl() */ - WARN_ON(pipe_config->output_types); - pipe_config->cpu_transcoder = (enum transcoder)pipe_config->bigjoiner_linked_crtc->pipe; - intel_ddi_read_func_ctl(encoder, pipe_config); - pipe_config->cpu_transcoder = save; - } else { - intel_ddi_read_func_ctl(encoder, pipe_config); - } + intel_ddi_read_func_ctl(encoder, pipe_config); intel_ddi_mso_get_config(encoder, pipe_config); @@ -3554,8 +3543,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; } - if (!pipe_config->bigjoiner_slave) - ddi_dotclock_get(pipe_config); + ddi_dotclock_get(pipe_config); if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pipe_config->lane_lat_optim_mask = diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 753f443e74bd6..f21030ffa83d4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1038,15 +1038,17 @@ struct intel_encoder * intel_get_crtc_new_encoder(const struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_connector_state *connector_state; const struct drm_connector *connector; struct intel_encoder *encoder = NULL; + struct intel_crtc *master_crtc; int num_encoders = 0; int i; + master_crtc = intel_master_crtc(crtc_state); + for_each_new_connector_in_state(&state->base, connector, connector_state, i) { - if (connector_state->crtc != &crtc->base) + if (connector_state->crtc != &master_crtc->base) continue; encoder = to_intel_encoder(connector_state->best_encoder); @@ -1055,7 +1057,7 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, drm_WARN(encoder->base.dev, num_encoders != 1, "%d encoders for pipe %c\n", - num_encoders, pipe_name(crtc->pipe)); + num_encoders, pipe_name(master_crtc->pipe)); return encoder; } @@ -1974,20 +1976,20 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, break; } - if (!crtc_state->bigjoiner_slave) { - /* need to enable VDSC, which we skipped in pre-enable */ - intel_dsc_enable(crtc_state); - } else { - /* - * Enable sequence steps 1-7 on bigjoiner master - */ + /* + * Enable sequence steps 1-7 on bigjoiner master + */ + if (crtc_state->bigjoiner_slave) intel_encoders_pre_pll_enable(state, master_crtc); - if (master_crtc_state->shared_dpll) - intel_enable_shared_dpll(master_crtc_state); + + if (crtc_state->shared_dpll) + intel_enable_shared_dpll(crtc_state); + + if (crtc_state->bigjoiner_slave) intel_encoders_pre_enable(state, master_crtc); - intel_dsc_enable(crtc_state); - } + /* need to enable VDSC, which we skipped in pre-enable */ + intel_dsc_enable(crtc_state); if (DISPLAY_VER(dev_priv) >= 13) intel_uncompressed_joiner_enable(crtc_state); @@ -2148,12 +2150,17 @@ static void ilk_crtc_disable(struct intel_atomic_state *state, static void hsw_crtc_disable(struct intel_atomic_state *state, struct intel_crtc *crtc) { + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + /* * FIXME collapse everything to one hook. * Need care with mst->ddi interactions. */ - intel_encoders_disable(state, crtc); - intel_encoders_post_disable(state, crtc); + if (!old_crtc_state->bigjoiner_slave) { + intel_encoders_disable(state, crtc); + intel_encoders_post_disable(state, crtc); + } } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -4356,20 +4363,12 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 13 && !pipe_config->dsc.compression_enable) intel_uncompressed_joiner_get_config(pipe_config); - if (!active) { - /* bigjoiner slave doesn't enable transcoder */ - if (!pipe_config->bigjoiner_slave) - goto out; - - active = true; - pipe_config->pixel_multiplier = 1; + if (!active) + goto out; - /* we cannot read out most state, so don't bother.. */ - pipe_config->quirks |= PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE; - } else if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || - DISPLAY_VER(dev_priv) >= 11) { + if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || + DISPLAY_VER(dev_priv) >= 11) intel_get_transcoder_timings(crtc, pipe_config); - } if (HAS_VRR(dev_priv) && !transcoder_is_dsi(pipe_config->cpu_transcoder)) intel_vrr_get_config(crtc, pipe_config); @@ -4437,10 +4436,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, } } - if (pipe_config->bigjoiner_slave) { - /* Cannot be read out as a slave, set to 0. */ - pipe_config->pixel_multiplier = 0; - } else if (pipe_config->cpu_transcoder != TRANSCODER_EDP && + if (pipe_config->cpu_transcoder != TRANSCODER_EDP && !transcoder_is_dsi(pipe_config->cpu_transcoder)) { pipe_config->pixel_multiplier = intel_de_read(dev_priv, @@ -5270,8 +5266,6 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, crtc_state->update_wm_post = true; if (mode_changed && crtc_state->hw.enable && - dev_priv->dpll_funcs && - !crtc_state->bigjoiner_slave && !drm_WARN_ON(&dev_priv->drm, crtc_state->shared_dpll)) { ret = dev_priv->dpll_funcs->crtc_compute_clock(crtc_state); if (ret) @@ -5878,7 +5872,6 @@ copy_bigjoiner_crtc_state(struct intel_crtc_state *crtc_state, const struct intel_crtc_state *from_crtc_state) { struct intel_crtc_state *saved_state; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); saved_state = kmemdup(from_crtc_state, sizeof(*saved_state), GFP_KERNEL); if (!saved_state) @@ -5908,8 +5901,8 @@ copy_bigjoiner_crtc_state(struct intel_crtc_state *crtc_state, crtc_state->nv12_planes = crtc_state->c8_planes = crtc_state->update_planes = 0; crtc_state->bigjoiner_linked_crtc = to_intel_crtc(from_crtc_state->uapi.crtc); crtc_state->bigjoiner_slave = true; - crtc_state->cpu_transcoder = (enum transcoder)crtc->pipe; - crtc_state->has_audio = false; + crtc_state->cpu_transcoder = from_crtc_state->cpu_transcoder; + crtc_state->has_audio = from_crtc_state->has_audio; return 0; } @@ -6996,10 +6989,6 @@ verify_crtc_state(struct intel_crtc *crtc, if (!new_crtc_state->hw.active) return; - if (new_crtc_state->bigjoiner_slave) - /* No PLLs set for slave */ - pipe_config->shared_dpll = NULL; - intel_pipe_config_sanity_check(dev_priv, pipe_config); if (!intel_pipe_config_compare(new_crtc_state, @@ -7118,9 +7107,6 @@ verify_mpllb_state(struct intel_atomic_state *state, if (!new_crtc_state->hw.active) return; - if (new_crtc_state->bigjoiner_slave) - return; - encoder = intel_get_crtc_new_encoder(state, new_crtc_state); intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state); @@ -8316,16 +8302,6 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave); - - /* - * We still need special handling for disabling bigjoiner master - * and slaves since for slave we do not have encoder or plls - * so we dont need to disable those. - */ - if (old_crtc_state->bigjoiner) - old_crtc_state->bigjoiner_linked_crtc->active = false; - /* * We need to disable pipe CRC before disabling the pipe, * or we race against vblank off. @@ -8365,7 +8341,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) /* Only disable port sync and MST slaves */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (!intel_crtc_needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner) + if (!intel_crtc_needs_modeset(new_crtc_state)) continue; if (!old_crtc_state->hw.active) @@ -8377,7 +8353,8 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) * Slave vblanks are masked till Master Vblanks. */ if (!is_trans_port_sync_slave(old_crtc_state) && - !intel_dp_mst_is_slave_trans(old_crtc_state)) + !intel_dp_mst_is_slave_trans(old_crtc_state) && + !old_crtc_state->bigjoiner_slave) continue; intel_old_crtc_state_disables(state, old_crtc_state, @@ -8389,13 +8366,14 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!intel_crtc_needs_modeset(new_crtc_state) || - (handled & BIT(crtc->pipe)) || - old_crtc_state->bigjoiner_slave) + (handled & BIT(crtc->pipe))) continue; - if (old_crtc_state->hw.active) - intel_old_crtc_state_disables(state, old_crtc_state, - new_crtc_state, crtc); + if (!old_crtc_state->hw.active) + continue; + + intel_old_crtc_state_disables(state, old_crtc_state, + new_crtc_state, crtc); } } @@ -10494,9 +10472,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_plane *plane; int min_cdclk = 0; - if (crtc_state->bigjoiner_slave) - continue; - if (crtc_state->hw.active) { /* * The initial mode needs to be set in order to keep @@ -10556,39 +10531,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_bw_crtc_update(bw_state, crtc_state); intel_pipe_config_sanity_check(dev_priv, crtc_state); - - /* discard our incomplete slave state, copy it from master */ - if (crtc_state->bigjoiner && crtc_state->hw.active) { - struct intel_crtc *slave = crtc_state->bigjoiner_linked_crtc; - struct intel_crtc_state *slave_crtc_state = - to_intel_crtc_state(slave->base.state); - - copy_bigjoiner_crtc_state(slave_crtc_state, crtc_state); - slave->base.mode = crtc->base.mode; - - cdclk_state->min_cdclk[slave->pipe] = min_cdclk; - cdclk_state->min_voltage_level[slave->pipe] = - crtc_state->min_voltage_level; - - for_each_intel_plane_on_crtc(&dev_priv->drm, slave, plane) { - const struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - - /* - * FIXME don't have the fb yet, so can't - * use intel_plane_data_rate() :( - */ - if (plane_state->uapi.visible) - crtc_state->data_rate[plane->id] = - 4 * crtc_state->pixel_rate; - else - crtc_state->data_rate[plane->id] = 0; - } - - intel_bw_crtc_update(bw_state, slave_crtc_state); - drm_calc_timestamping_constants(&slave->base, - &slave_crtc_state->hw.adjusted_mode); - } } } From 818a1968a73188451fd1c16604b4e47ab5a40d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Oct 2021 13:33:04 +0300 Subject: [PATCH 058/176] drm/i915: Nuke PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the bigjoiner state readout/computation has been made to do the right thing nuke the related state checker quirk. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211022103304.24164-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 115 ++++++++---------- .../drm/i915/display/intel_display_types.h | 1 - 2 files changed, 52 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f21030ffa83d4..79cd158503b37 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6498,51 +6498,48 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(output_types); - /* FIXME do the readout properly and get rid of this quirk */ - if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) { - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_end); - - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_end); - - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); - - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end); - - PIPE_CONF_CHECK_I(pixel_multiplier); - + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_end); + + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_end); + + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); + + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end); + + PIPE_CONF_CHECK_I(pixel_multiplier); + + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_INTERLACE); + + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_INTERLACE); - - if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_PHSYNC); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_NHSYNC); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_PVSYNC); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_NVSYNC); - } + DRM_MODE_FLAG_PHSYNC); + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_NHSYNC); + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_PVSYNC); + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_NVSYNC); } PIPE_CONF_CHECK_I(output_format); @@ -6554,9 +6551,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(hdmi_scrambling); PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio); PIPE_CONF_CHECK_BOOL(has_infoframe); - /* FIXME do the readout properly and get rid of this quirk */ - if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) - PIPE_CONF_CHECK_BOOL(fec_enable); + PIPE_CONF_CHECK_BOOL(fec_enable); PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); @@ -6585,9 +6580,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } PIPE_CONF_CHECK_I(scaler_state.scaler_id); - /* FIXME do the readout properly and get rid of this quirk */ - if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) - PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); + PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); PIPE_CONF_CHECK_X(gamma_mode); if (IS_CHERRYVIEW(dev_priv)) @@ -6614,11 +6607,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); - if (dev_priv->dpll.mgr) + if (dev_priv->dpll.mgr) { PIPE_CONF_CHECK_P(shared_dpll); - /* FIXME do the readout properly and get rid of this quirk */ - if (dev_priv->dpll.mgr && !PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) { PIPE_CONF_CHECK_X(dpll_hw_state.dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); PIPE_CONF_CHECK_X(dpll_hw_state.fp0); @@ -6652,19 +6643,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias); } - if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) { - PIPE_CONF_CHECK_X(dsi_pll.ctrl); - PIPE_CONF_CHECK_X(dsi_pll.div); + PIPE_CONF_CHECK_X(dsi_pll.ctrl); + PIPE_CONF_CHECK_X(dsi_pll.div); - if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5) - PIPE_CONF_CHECK_I(pipe_bpp); + if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5) + PIPE_CONF_CHECK_I(pipe_bpp); - PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); - PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); - PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); - PIPE_CONF_CHECK_I(min_voltage_level); - } + PIPE_CONF_CHECK_I(min_voltage_level); if (current_config->has_psr || pipe_config->has_psr) PIPE_CONF_CHECK_X_WITH_MASK(infoframes.enable, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 3568d33be096b..991972da07038 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -945,7 +945,6 @@ struct intel_crtc_state { * accordingly. */ #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ -#define PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE (1<<1) /* bigjoiner slave, partial readout */ unsigned long quirks; unsigned fb_bits; /* framebuffers to flip */ From 16aea0f32f1de320550ec3488bff9ca86b3848bf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 27 Oct 2021 16:59:00 +0300 Subject: [PATCH 059/176] drm/i915/dsc: demote noisy drm_info() to drm_kms_dbg() The PPS, RC_RANGE_PARAM, and RC_BUF_THRESH logging are clearly for debugging, and should not be info level messages. Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211027135900.6329-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index fa84be609d5d2..bf8d3c7ca2d9a 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -598,7 +598,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val |= DSC_422_ENABLE; if (vdsc_cfg->vbr_enable) pps_val |= DSC_VBR_ENABLE; - drm_info(&dev_priv->drm, "PPS0 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS0 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_0, pps_val); @@ -622,7 +622,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) /* Populate PICTURE_PARAMETER_SET_1 registers */ pps_val = 0; pps_val |= DSC_BPP(vdsc_cfg->bits_per_pixel); - drm_info(&dev_priv->drm, "PPS1 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS1 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_1, pps_val); @@ -647,7 +647,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) | DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances); - drm_info(&dev_priv->drm, "PPS2 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS2 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_2, pps_val); @@ -672,7 +672,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_SLICE_HEIGHT(vdsc_cfg->slice_height) | DSC_SLICE_WIDTH(vdsc_cfg->slice_width); - drm_info(&dev_priv->drm, "PPS3 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS3 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_3, pps_val); @@ -697,7 +697,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) | DSC_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay); - drm_info(&dev_priv->drm, "PPS4 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS4 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_4, pps_val); @@ -722,7 +722,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) | DSC_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval); - drm_info(&dev_priv->drm, "PPS5 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS5 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_5, pps_val); @@ -749,7 +749,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) DSC_FIRST_LINE_BPG_OFFSET(vdsc_cfg->first_line_bpg_offset) | DSC_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) | DSC_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp); - drm_info(&dev_priv->drm, "PPS6 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS6 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_6, pps_val); @@ -774,7 +774,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) | DSC_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset); - drm_info(&dev_priv->drm, "PPS7 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS7 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_7, pps_val); @@ -799,7 +799,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_FINAL_OFFSET(vdsc_cfg->final_offset) | DSC_INITIAL_OFFSET(vdsc_cfg->initial_offset); - drm_info(&dev_priv->drm, "PPS8 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS8 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_8, pps_val); @@ -824,7 +824,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val = 0; pps_val |= DSC_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) | DSC_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST); - drm_info(&dev_priv->drm, "PPS9 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS9 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_9, pps_val); @@ -851,7 +851,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) DSC_RC_QUANT_INC_LIMIT1(vdsc_cfg->rc_quant_incr_limit1) | DSC_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) | DSC_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST); - drm_info(&dev_priv->drm, "PPS10 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS10 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_10, pps_val); @@ -879,7 +879,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) vdsc_cfg->slice_width) | DSC_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height / vdsc_cfg->slice_height); - drm_info(&dev_priv->drm, "PPS16 = 0x%08x\n", pps_val); + drm_dbg_kms(&dev_priv->drm, "PPS16 = 0x%08x\n", pps_val); if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_16, pps_val); @@ -906,8 +906,8 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) rc_buf_thresh_dword[i / 4] |= (u32)(vdsc_cfg->rc_buf_thresh[i] << BITS_PER_BYTE * (i % 4)); - drm_info(&dev_priv->drm, " RC_BUF_THRESH%d = 0x%08x\n", i, - rc_buf_thresh_dword[i / 4]); + drm_dbg_kms(&dev_priv->drm, "RC_BUF_THRESH_%d = 0x%08x\n", i, + rc_buf_thresh_dword[i / 4]); } if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_0, @@ -963,8 +963,8 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) RC_MAX_QP_SHIFT) | (vdsc_cfg->rc_range_params[i].range_min_qp << RC_MIN_QP_SHIFT)) << 16 * (i % 2)); - drm_info(&dev_priv->drm, " RC_RANGE_PARAM_%d = 0x%08x\n", i, - rc_range_params_dword[i / 2]); + drm_dbg_kms(&dev_priv->drm, "RC_RANGE_PARAM_%d = 0x%08x\n", i, + rc_range_params_dword[i / 2]); } if (!is_pipe_dsc(crtc, cpu_transcoder)) { intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_0, From 4c3d005307c87c7a35e85a307b8bcf49f1d56114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 27 Oct 2021 11:05:45 -0700 Subject: [PATCH 060/176] drm/i915/adlp: Extend PSR2 support in transcoder B MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PSR2 is supported in transcoder A and B on Alderlake-P. v2: - explicity checking for transcoder A and B to avoid invalid transcoder BSpec: 49185 Reviewed-by: Jouni Högander # v1 Cc: Jani Nikula Cc: Mika Kahola Cc: Jouni Hogander Signed-off-by: José Roberto de Souza Reviewed-by: Mika Kahola # v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211027180545.55660-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 8d08e3cf08c1f..33b50646b9c97 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -588,7 +588,9 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) static bool transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder trans) { - if (DISPLAY_VER(dev_priv) >= 12) + if (IS_ALDERLAKE_P(dev_priv)) + return trans == TRANSCODER_A || trans == TRANSCODER_B; + else if (DISPLAY_VER(dev_priv) >= 12) return trans == TRANSCODER_A; else return trans == TRANSCODER_EDP; From 32c2bc89c7420fad2959ee23ef5b6be8b05d2bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 25 Oct 2021 17:21:47 +0300 Subject: [PATCH 061/176] drm/i915: Fix type1 DVI DP dual mode adapter heuristic for modern platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like we never updated intel_bios_is_port_dp_dual_mode() when the VBT port mapping became erratic on modern platforms. This is causing us to look up the wrong child device and thus throwing the heuristic off (ie. we might end looking at a child device for a genuine DP++ port when we were supposed to look at one for a native HDMI port). Fix it up by not using the outdated port_mapping[] in intel_bios_is_port_dp_dual_mode() and rely on intel_bios_encoder_data_lookup() instead. Cc: stable@vger.kernel.org Tested-by: Randy Dunlap Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4138 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211025142147.23897-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 85 +++++++++++++++++------ 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index f9776ca85de3e..2b1423a43437d 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1707,6 +1707,39 @@ static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata, child->aux_channel = 0; } +static u8 dvo_port_type(u8 dvo_port) +{ + switch (dvo_port) { + case DVO_PORT_HDMIA: + case DVO_PORT_HDMIB: + case DVO_PORT_HDMIC: + case DVO_PORT_HDMID: + case DVO_PORT_HDMIE: + case DVO_PORT_HDMIF: + case DVO_PORT_HDMIG: + case DVO_PORT_HDMIH: + case DVO_PORT_HDMII: + return DVO_PORT_HDMIA; + case DVO_PORT_DPA: + case DVO_PORT_DPB: + case DVO_PORT_DPC: + case DVO_PORT_DPD: + case DVO_PORT_DPE: + case DVO_PORT_DPF: + case DVO_PORT_DPG: + case DVO_PORT_DPH: + case DVO_PORT_DPI: + return DVO_PORT_DPA; + case DVO_PORT_MIPIA: + case DVO_PORT_MIPIB: + case DVO_PORT_MIPIC: + case DVO_PORT_MIPID: + return DVO_PORT_MIPIA; + default: + return dvo_port; + } +} + static enum port __dvo_port_to_port(int n_ports, int n_dvo, const int port_mapping[][3], u8 dvo_port) { @@ -2623,35 +2656,17 @@ bool intel_bios_is_port_edp(struct drm_i915_private *i915, enum port port) return false; } -static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, - enum port port) +static bool child_dev_is_dp_dual_mode(const struct child_device_config *child) { - static const struct { - u16 dp, hdmi; - } port_mapping[] = { - /* - * Buggy VBTs may declare DP ports as having - * HDMI type dvo_port :( So let's check both. - */ - [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, }, - [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, }, - [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, - [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, - [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, - }; - - if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) - return false; - if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) return false; - if (child->dvo_port == port_mapping[port].dp) + if (dvo_port_type(child->dvo_port) == DVO_PORT_DPA) return true; /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ - if (child->dvo_port == port_mapping[port].hdmi && + if (dvo_port_type(child->dvo_port) == DVO_PORT_HDMIA && child->aux_channel != 0) return true; @@ -2661,10 +2676,36 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915, enum port port) { + static const struct { + u16 dp, hdmi; + } port_mapping[] = { + /* + * Buggy VBTs may declare DP ports as having + * HDMI type dvo_port :( So let's check both. + */ + [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, }, + [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, }, + [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, + [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, + [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, + }; const struct intel_bios_encoder_data *devdata; + if (HAS_DDI(i915)) { + const struct intel_bios_encoder_data *devdata; + + devdata = intel_bios_encoder_data_lookup(i915, port); + + return devdata && child_dev_is_dp_dual_mode(&devdata->child); + } + + if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) + return false; + list_for_each_entry(devdata, &i915->vbt.display_devices, node) { - if (child_dev_is_dp_dual_mode(&devdata->child, port)) + if ((devdata->child.dvo_port == port_mapping[port].dp || + devdata->child.dvo_port == port_mapping[port].hdmi) && + child_dev_is_dp_dual_mode(&devdata->child)) return true; } From ead3ea12e133416fbd800eedb2fb5d0faf2df431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:37 +0300 Subject: [PATCH 062/176] drm/i915: Fix icl+ combo phy static lane power down setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our lane power down defines already include the necessary shift, don't shift them a second time. Fortunately we masked off the correct bits, so we accidentally left all lanes powered up all the time. Bits 8-11 where we end up writing our misdirected lane mask are documented as MBZ, but looks like you can actually write there so they're not read only bits. No idea what side effect the bogus register write might have. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4151 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-17-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_combo_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 634e8d4494574..f628e05429337 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -301,7 +301,7 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, val = intel_de_read(dev_priv, ICL_PORT_CL_DW10(phy)); val &= ~PWR_DOWN_LN_MASK; - val |= lane_mask << PWR_DOWN_LN_SHIFT; + val |= lane_mask; intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy), val); } From da0c3e2c907aaa4c6818aabc2691a667e3578063 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 26 Oct 2021 19:15:15 +0300 Subject: [PATCH 063/176] drm/i915/fb: Don't report MC CCS plane capability on GEN<12 Remove the MC CCS plane capability on GEN<12, since it's not present there. This didn't cause a problem, since the display version check filtered out the MC CCS modifiers before GEN12. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026161517.2694067-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 69fd56de83a7a..8fa0ae89e5b3d 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2001,6 +2001,9 @@ static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, enum plane_id plane_id) { + if (DISPLAY_VER(i915) < 12) + return false; + /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */ if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || IS_TGL_DISPLAY_STEP(i915, STEP_A0, STEP_D0)) From 7df7bca56902e4d96c7b17b84378774f2254b707 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 26 Oct 2021 19:15:16 +0300 Subject: [PATCH 064/176] drm/i915/fb: Don't store bitmasks in the intel_plane_caps enum Variables of enum types can contain only the values listed at the enums definition, so don't store bitmasks in intel_plane_caps enum variables. Cc: Juha-Pekka Heikkila Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026161517.2694067-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 4 ++-- drivers/gpu/drm/i915/display/intel_fb.h | 2 +- drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 9ce1d273dc7e1..6b68f69940f0b 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -309,7 +309,7 @@ static bool check_modifier_display_ver_range(const struct intel_modifier_desc *m } static bool plane_has_modifier(struct drm_i915_private *i915, - enum intel_plane_caps plane_caps, + u8 plane_caps, const struct intel_modifier_desc *md) { if (!IS_DISPLAY_VER(i915, md->display_ver.from, md->display_ver.until)) @@ -340,7 +340,7 @@ static bool plane_has_modifier(struct drm_i915_private *i915, * The caller must free the returned buffer. */ u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, - enum intel_plane_caps plane_caps) + u8 plane_caps) { u64 *list, *p; int count = 1; /* +1 for invalid modifier terminator */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 042ad81f86082..19f46144474d8 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -35,7 +35,7 @@ bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb); u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, - enum intel_plane_caps plane_caps); + u8 plane_caps); bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier); const struct drm_format_info * diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 8fa0ae89e5b3d..317108e009bba 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2023,7 +2023,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, const struct drm_plane_funcs *plane_funcs; struct intel_plane *plane; enum drm_plane_type plane_type; - enum intel_plane_caps plane_caps; + u8 plane_caps; unsigned int supported_rotations; unsigned int supported_csc; const u64 *modifiers; From 10a657dd4cbc34ba9f1bf16140a96789688f6cd5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 15:51:50 +0300 Subject: [PATCH 065/176] drm/i915/fb: Fold modifier CCS type/tiling attribute to plane caps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By using the modifier plane capability flags to encode the modifiers' CCS type and tiling attributes, it becomes simpler to the check for any of these capabilities when providing the list of supported modifiers. This also allows distinguishing modifiers on future platforms where platforms with the same display version support different modifiers. An example is DG2 and ADLP, both being D13, where DG2 supports only F and X tiling, while ADLP supports only Y and X tiling. With the INTEL_PLANE_CAP_TILING_* flags added in this patch we can provide the correct modifiers for each platform. v2: - Define PLANE_HAS_* with macros instead of an enum. (Jani) - Rename PLANE_HAS_*_ANY to PLANE_HAS_*_MASK. (Jani) - Rename PLANE_HAS_* to INTEL_PLANE_CAP_*. - Set the CCS_RC_CC cap only for DISPLAY_VER >= 12. - Set the TILING_Y cap only for DISPLAY_VER < 13 || ADLP. - Simplify the SKL plane cap display version checks and move them to a separate function. Cc: Juha-Pekka Heikkila Cc: Ville Syrjälä Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211027125150.2891371-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/i9xx_plane.c | 2 +- drivers/gpu/drm/i915/display/intel_cursor.c | 2 +- drivers/gpu/drm/i915/display/intel_fb.c | 88 ++++++++++--------- drivers/gpu/drm/i915/display/intel_fb.h | 13 +-- drivers/gpu/drm/i915/display/intel_sprite.c | 2 +- .../drm/i915/display/skl_universal_plane.c | 33 +++++-- 6 files changed, 81 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index a939accff7ee2..2e16a66e8f9e7 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -860,7 +860,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->disable_flip_done = ilk_primary_disable_flip_done; } - modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_TILING); + modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X); if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 6b08d8bca5cd4..5ddd3c8fbc634 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -782,7 +782,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv)) cursor->cursor.size = ~0; - modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_NO_CAPS); + modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_NONE); ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base, 0, &intel_cursor_plane_funcs, diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 6b68f69940f0b..117e32fb3648e 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -120,29 +120,29 @@ struct intel_modifier_desc { .formats = format_list, \ .format_count = ARRAY_SIZE(format_list) - u8 tiling; - u8 is_linear:1; + u8 plane_caps; struct { -#define INTEL_CCS_RC BIT(0) -#define INTEL_CCS_RC_CC BIT(1) -#define INTEL_CCS_MC BIT(2) - -#define INTEL_CCS_ANY (INTEL_CCS_RC | INTEL_CCS_RC_CC | INTEL_CCS_MC) - u8 type:3; u8 cc_planes:3; u8 packed_aux_planes:4; u8 planar_aux_planes:4; } ccs; }; +#define INTEL_PLANE_CAP_CCS_MASK (INTEL_PLANE_CAP_CCS_RC | \ + INTEL_PLANE_CAP_CCS_RC_CC | \ + INTEL_PLANE_CAP_CCS_MC) +#define INTEL_PLANE_CAP_TILING_MASK (INTEL_PLANE_CAP_TILING_X | \ + INTEL_PLANE_CAP_TILING_Y | \ + INTEL_PLANE_CAP_TILING_Yf) +#define INTEL_PLANE_CAP_TILING_NONE 0 + static const struct intel_modifier_desc intel_modifiers[] = { { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, .display_ver = { 12, 13 }, - .tiling = I915_TILING_Y, + .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC, - .ccs.type = INTEL_CCS_MC, .ccs.packed_aux_planes = BIT(1), .ccs.planar_aux_planes = BIT(2) | BIT(3), @@ -150,18 +150,16 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, .display_ver = { 12, 13 }, - .tiling = I915_TILING_Y, + .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_RC, - .ccs.type = INTEL_CCS_RC, .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(gen12_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, .display_ver = { 12, 13 }, - .tiling = I915_TILING_Y, + .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_RC_CC, - .ccs.type = INTEL_CCS_RC_CC, .ccs.cc_planes = BIT(2), .ccs.packed_aux_planes = BIT(1), @@ -169,39 +167,34 @@ static const struct intel_modifier_desc intel_modifiers[] = { }, { .modifier = I915_FORMAT_MOD_Yf_TILED_CCS, .display_ver = { 9, 11 }, - .tiling = I915_TILING_NONE, + .plane_caps = INTEL_PLANE_CAP_TILING_Yf | INTEL_PLANE_CAP_CCS_RC, - .ccs.type = INTEL_CCS_RC, .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(skl_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Y_TILED_CCS, .display_ver = { 9, 11 }, - .tiling = I915_TILING_Y, + .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_RC, - .ccs.type = INTEL_CCS_RC, .ccs.packed_aux_planes = BIT(1), FORMAT_OVERRIDE(skl_ccs_formats), }, { .modifier = I915_FORMAT_MOD_Yf_TILED, .display_ver = { 9, 11 }, - .tiling = I915_TILING_NONE, + .plane_caps = INTEL_PLANE_CAP_TILING_Yf, }, { .modifier = I915_FORMAT_MOD_Y_TILED, .display_ver = { 9, 13 }, - .tiling = I915_TILING_Y, + .plane_caps = INTEL_PLANE_CAP_TILING_Y, }, { .modifier = I915_FORMAT_MOD_X_TILED, .display_ver = DISPLAY_VER_ALL, - .tiling = I915_TILING_X, + .plane_caps = INTEL_PLANE_CAP_TILING_X, }, { .modifier = DRM_FORMAT_MOD_LINEAR, .display_ver = DISPLAY_VER_ALL, - .tiling = I915_TILING_NONE, - - .is_linear = true, }, }; @@ -259,9 +252,14 @@ intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd) return lookup_format_info(md->formats, md->format_count, cmd->pixel_format); } -static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_type) +static bool plane_caps_contain_any(u8 caps, u8 mask) +{ + return caps & mask; +} + +static bool plane_caps_contain_all(u8 caps, u8 mask) { - return md->ccs.type & ccs_type; + return (caps & mask) == mask; } /** @@ -274,7 +272,8 @@ static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_ty */ bool intel_fb_is_ccs_modifier(u64 modifier) { - return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_ANY); + return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, + INTEL_PLANE_CAP_CCS_MASK); } /** @@ -286,7 +285,8 @@ bool intel_fb_is_ccs_modifier(u64 modifier) */ bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier) { - return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_RC_CC); + return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, + INTEL_PLANE_CAP_CCS_RC_CC); } /** @@ -298,7 +298,8 @@ bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier) */ bool intel_fb_is_mc_ccs_modifier(u64 modifier) { - return is_ccs_type_modifier(lookup_modifier(modifier), INTEL_CCS_MC); + return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, + INTEL_PLANE_CAP_CCS_MC); } static bool check_modifier_display_ver_range(const struct intel_modifier_desc *md, @@ -315,16 +316,7 @@ static bool plane_has_modifier(struct drm_i915_private *i915, if (!IS_DISPLAY_VER(i915, md->display_ver.from, md->display_ver.until)) return false; - if (!md->is_linear && - !(plane_caps & PLANE_HAS_TILING)) - return false; - - if (is_ccs_type_modifier(md, INTEL_CCS_RC | INTEL_CCS_RC_CC) && - !(plane_caps & PLANE_HAS_CCS_RC)) - return false; - - if (is_ccs_type_modifier(md, INTEL_CCS_MC) && - !(plane_caps & PLANE_HAS_CCS_MC)) + if (!plane_caps_contain_all(plane_caps, md->plane_caps)) return false; return true; @@ -392,7 +384,7 @@ static bool format_is_yuv_semiplanar(const struct intel_modifier_desc *md, if (!info->is_yuv) return false; - if (is_ccs_type_modifier(md, INTEL_CCS_ANY)) + if (plane_caps_contain_any(md->plane_caps, INTEL_PLANE_CAP_CCS_MASK)) yuv_planes = 4; else yuv_planes = 2; @@ -672,7 +664,21 @@ intel_fb_align_height(const struct drm_framebuffer *fb, static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) { - return lookup_modifier(fb_modifier)->tiling; + u8 tiling_caps = lookup_modifier(fb_modifier)->plane_caps & + INTEL_PLANE_CAP_TILING_MASK; + + switch (tiling_caps) { + case INTEL_PLANE_CAP_TILING_Y: + return I915_TILING_Y; + case INTEL_PLANE_CAP_TILING_X: + return I915_TILING_X; + case INTEL_PLANE_CAP_TILING_Yf: + case INTEL_PLANE_CAP_TILING_NONE: + return I915_TILING_NONE; + default: + MISSING_CASE(tiling_caps); + return I915_TILING_NONE; + } } unsigned int intel_cursor_alignment(const struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 19f46144474d8..b54997175d6da 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -20,12 +20,13 @@ struct intel_framebuffer; struct intel_plane; struct intel_plane_state; -enum intel_plane_caps { - PLANE_HAS_NO_CAPS = 0, - PLANE_HAS_TILING = BIT(0), - PLANE_HAS_CCS_RC = BIT(1), - PLANE_HAS_CCS_MC = BIT(2), -}; +#define INTEL_PLANE_CAP_NONE 0 +#define INTEL_PLANE_CAP_CCS_RC BIT(0) +#define INTEL_PLANE_CAP_CCS_RC_CC BIT(1) +#define INTEL_PLANE_CAP_CCS_MC BIT(2) +#define INTEL_PLANE_CAP_TILING_X BIT(3) +#define INTEL_PLANE_CAP_TILING_Y BIT(4) +#define INTEL_PLANE_CAP_TILING_Yf BIT(5) bool intel_fb_is_ccs_modifier(u64 modifier); bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 2f4f47ab9da03..367515a70ac4c 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1810,7 +1810,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->id = PLANE_SPRITE0 + sprite; plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); - modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_TILING); + modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X); ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 317108e009bba..ef7856db09f79 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2016,6 +2016,28 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, return plane_id < PLANE_SPRITE4; } +static u8 skl_get_plane_caps(struct drm_i915_private *i915, + enum pipe pipe, enum plane_id plane_id) +{ + u8 caps = INTEL_PLANE_CAP_TILING_X; + + if (DISPLAY_VER(i915) < 13 || IS_ALDERLAKE_P(i915)) + caps |= INTEL_PLANE_CAP_TILING_Y; + if (DISPLAY_VER(i915) < 12) + caps |= INTEL_PLANE_CAP_TILING_Yf; + + if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) { + caps |= INTEL_PLANE_CAP_CCS_RC; + if (DISPLAY_VER(i915) >= 12) + caps |= INTEL_PLANE_CAP_CCS_RC_CC; + } + + if (gen12_plane_has_mc_ccs(i915, plane_id)) + caps |= INTEL_PLANE_CAP_CCS_MC; + + return caps; +} + struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id) @@ -2023,7 +2045,6 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, const struct drm_plane_funcs *plane_funcs; struct intel_plane *plane; enum drm_plane_type plane_type; - u8 plane_caps; unsigned int supported_rotations; unsigned int supported_csc; const u64 *modifiers; @@ -2095,14 +2116,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, else plane_type = DRM_PLANE_TYPE_OVERLAY; - plane_caps = PLANE_HAS_TILING; - if (skl_plane_has_rc_ccs(dev_priv, pipe, plane_id)) - plane_caps |= PLANE_HAS_CCS_RC; - - if (gen12_plane_has_mc_ccs(dev_priv, plane_id)) - plane_caps |= PLANE_HAS_CCS_MC; - - modifiers = intel_fb_plane_get_modifiers(dev_priv, plane_caps); + modifiers = intel_fb_plane_get_modifiers(dev_priv, + skl_get_plane_caps(dev_priv, pipe, plane_id)); ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, From 3809991ff5f461cabccd9b5aa39f7561f10918b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Thu, 21 Oct 2021 13:10:23 +0300 Subject: [PATCH 066/176] drm/i915/display: Add initial selective fetch support for biplanar formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Biplanar formats are using two planes (Y and UV). This patch adds handling of Y selective fetch area by utilizing existing linked plane mechanism. Also UV plane Y offset configuration is modified according to Bspec. Signed-off-by: Jouni Högander Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20211021101024.13112-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 30 +++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 33b50646b9c97..bdbb5ed84f93b 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1469,10 +1469,19 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane, val |= plane_state->uapi.dst.x1; intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_POS(pipe, plane->id), val); - /* TODO: consider auxiliary surfaces */ - x = plane_state->uapi.src.x1 >> 16; - y = (plane_state->uapi.src.y1 >> 16) + clip->y1; + 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; + val = y << 16 | x; + intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_OFFSET(pipe, plane->id), val); @@ -1702,6 +1711,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { struct drm_rect *sel_fetch_area, inter; + struct intel_plane *linked = new_plane_state->planar_linked_plane; if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc || !new_plane_state->uapi.visible) @@ -1720,6 +1730,20 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, sel_fetch_area->y1 = inter.y1 - new_plane_state->uapi.dst.y1; sel_fetch_area->y2 = inter.y2 - new_plane_state->uapi.dst.y1; crtc_state->update_planes |= BIT(plane->id); + + /* + * Sel_fetch_area is calculated for UV plane. Use + * same area for Y plane as well. + */ + if (linked) { + struct intel_plane_state *linked_new_plane_state = + intel_atomic_get_new_plane_state(state, linked); + struct drm_rect *linked_sel_fetch_area = + &linked_new_plane_state->psr2_sel_fetch_area; + + linked_sel_fetch_area->y1 = sel_fetch_area->y1; + linked_sel_fetch_area->y2 = sel_fetch_area->y2; + } } skip_sel_fetch_set_loop: From c34c1c4cd68f3ffcd13c7169e7a2c35e267e34f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Thu, 21 Oct 2021 13:10:24 +0300 Subject: [PATCH 067/176] Revert "drm/i915/display/psr: Do full fetch when handling multi-planar formats" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1f61f0655b95d5b89589390e6f83c4a61d9b1e8d. Now we are supporting selective fetch for biplanar formats. We can revert WA patch which forced using full fetch for biplanar formats. Signed-off-by: Jouni Högander Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20211021101024.13112-3-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index bdbb5ed84f93b..9d589d471e335 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1573,9 +1573,6 @@ static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *c * also planes are not updated if they have a negative X * position so for now doing a full update in this cases * - * TODO: We are missing multi-planar formats handling, until it is - * implemented it will send full frame updates. - * * Plane scaling and rotation is not supported by selective fetch and both * properties can change without a modeset, so need to be check at every * atomic commmit. @@ -1585,7 +1582,6 @@ static bool psr2_sel_fetch_plane_state_supported(const struct intel_plane_state if (plane_state->uapi.dst.y1 < 0 || plane_state->uapi.dst.x1 < 0 || plane_state->scaler_id >= 0 || - plane_state->hw.fb->format->num_planes > 1 || plane_state->uapi.rotation != DRM_MODE_ROTATE_0) return false; From 9556829ce4d0618ae4295af8e4b3dd7e38f43598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Thu, 28 Oct 2021 16:04:49 -0700 Subject: [PATCH 068/176] drm/i915/adlp: Implement workaround 16013190616 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New workaround added to specification, requiring bit 15 of GEN8_CHICKEN_DCPR_1 to be programed before power well 1 is enabled. BSpec: 54369 Signed-off-by: José Roberto de Souza Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211028230449.115832-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 5 +++++ drivers/gpu/drm/i915/i915_reg.h | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 6637760d24e0c..344e3d6967020 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -435,6 +435,11 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv, pg = DISPLAY_VER(dev_priv) >= 11 ? ICL_PW_CTL_IDX_TO_PG(pw_idx) : SKL_PW_CTL_IDX_TO_PG(pw_idx); + + /* Wa_16013190616:adlp */ + if (IS_ALDERLAKE_P(dev_priv) && pg == SKL_PG1) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, DISABLE_FLR_SRC); + /* * For PW1 we have to wait both for the PW0/PG0 fuse state * before enabling the power well and PW1/PG1's own fuse diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7c97bc352497d..e4f1d8275ad07 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8308,9 +8308,10 @@ enum { #define RESET_PCH_HANDSHAKE_ENABLE (1 << 4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) -#define SKL_SELECT_ALTERNATE_DC_EXIT (1 << 30) -#define ICL_DELAY_PMRSP (1 << 22) -#define MASK_WAKEMEM (1 << 13) +#define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30) +#define ICL_DELAY_PMRSP REG_BIT(22) +#define DISABLE_FLR_SRC REG_BIT(15) +#define MASK_WAKEMEM REG_BIT(13) #define GEN11_CHICKEN_DCPR_2 _MMIO(0x46434) #define DCPR_MASK_MAXLATENCY_MEMUP_CLR REG_BIT(27) From f2787d8779b1b00768f8f397b3699698ed84300a Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Wed, 6 Oct 2021 13:45:47 -0700 Subject: [PATCH 069/176] i915/display/dmc: Add Support for PipeC and PipeD DMC So far we had support for main, PipeA and PipeB DMC. If we find a binary from PipeA-D, lets load it. Cc: Imre Deak Signed-off-by: Anusha Srivatsa Signed-off-by: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211006204547.669464-1-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index c3c00ff03869b..b20f3441ca606 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -20,6 +20,8 @@ enum { DMC_FW_MAIN = 0, DMC_FW_PIPEA, DMC_FW_PIPEB, + DMC_FW_PIPEC, + DMC_FW_PIPED, DMC_FW_MAX }; From fa2a6c5b9cfb0dfbd1b811b154a036df1017ce66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 29 Oct 2021 22:18:01 +0300 Subject: [PATCH 070/176] drm/i915: Don't request GMBUS to generate irqs when called while irqs are off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will need to do some i2c poking from the encoder->shutdown() hook. Currently that gets called after irqs have been turned off. We still poll the gmbus status bits even if the interrupt never arrives so things will work just fine. But seems like asking gmbus to generate interrupts we will never see is a bit pointless, so don't. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211029191802.18448-1-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_gmbus.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index ceb1bf8a8c3c2..3b8b841770855 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -334,6 +334,15 @@ intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin) algo->data = bus; } +static bool has_gmbus_irq(struct drm_i915_private *i915) +{ + /* + * encoder->shutdown() may want to use GMBUS + * after irqs have already been disabled. + */ + return HAS_GMBUS_IRQ(i915) && intel_irqs_enabled(i915); +} + static int gmbus_wait(struct drm_i915_private *dev_priv, u32 status, u32 irq_en) { DEFINE_WAIT(wait); @@ -344,7 +353,7 @@ static int gmbus_wait(struct drm_i915_private *dev_priv, u32 status, u32 irq_en) * we also need to check for NAKs besides the hw ready/idle signal, we * need to wake up periodically and check that ourselves. */ - if (!HAS_GMBUS_IRQ(dev_priv)) + if (!has_gmbus_irq(dev_priv)) irq_en = 0; add_wait_queue(&dev_priv->gmbus_wait_queue, &wait); @@ -375,7 +384,7 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) /* Important: The hw handles only the first bit, so set only one! */ irq_enable = 0; - if (HAS_GMBUS_IRQ(dev_priv)) + if (has_gmbus_irq(dev_priv)) irq_enable = GMBUS_IDLE_EN; add_wait_queue(&dev_priv->gmbus_wait_queue, &wait); From 49c55f7b035b87371a6d3c53d9af9f92ddc962db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 29 Oct 2021 22:18:02 +0300 Subject: [PATCH 071/176] drm/i915/hdmi: Turn DP++ TMDS output buffers back on in encoder->shutdown() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like our VBIOS/GOP generally fail to turn the DP dual mode adater TMDS output buffers back on after a reboot. This leads to a black screen after reboot if we turned the TMDS output buffers off prior to reboot. And if i915 decides to do a fastboot the black screen will persist even after i915 takes over. Apparently this has been a problem ever since commit b2ccb822d376 ("drm/i915: Enable/disable TMDS output buffers in DP++ adaptor as needed") if one rebooted while the display was turned off. And things became worse with commit fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") since now we always turn the display off before a reboot. This was reported on a RKL, but I confirmed the same behaviour on my SNB as well. So looks pretty universal. Let's fix this by explicitly turning the TMDS output buffers back on in the encoder->shutdown() hook. Note that this gets called after irqs have been disabled, so the i2c communication with the DP dual mode adapter has to be performed via polling (which the gmbus code is perfectly happy to do for us). We also need a bit of care in handling DDI encoders which may or may not be set up for HDMI output. Specifically ddc_pin will not be populated for a DP only DDI encoder, in which case we don't want to call intel_gmbus_get_adapter(). We can handle that by simply doing the dual mode adapter type check before calling intel_gmbus_get_adapter(). Cc: # v5.11+ Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4371 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211029191802.18448-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/g4x_hdmi.c | 1 + drivers/gpu/drm/i915/display/intel_ddi.c | 1 + drivers/gpu/drm/i915/display/intel_hdmi.c | 16 ++++++++++++++-- drivers/gpu/drm/i915/display/intel_hdmi.h | 1 + 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 88c427f3c3467..f5b4dd5b42757 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -584,6 +584,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, else intel_encoder->enable = g4x_enable_hdmi; } + intel_encoder->shutdown = intel_hdmi_encoder_shutdown; intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->power_domain = intel_port_to_power_domain(port); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 9fb99b09fff8b..5ef2882727e19 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4312,6 +4312,7 @@ static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) enum phy phy = intel_port_to_phy(i915, encoder->port); intel_dp_encoder_shutdown(encoder); + intel_hdmi_encoder_shutdown(encoder); if (!intel_phy_is_tc(i915, phy)) return; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 7e6af959bf838..3b5b9e7b05b7b 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1246,12 +1246,13 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) { struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); - struct i2c_adapter *adapter = - intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); + struct i2c_adapter *adapter; if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) return; + adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); + drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n", enable ? "Enabling" : "Disabling"); @@ -2285,6 +2286,17 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, return 0; } +void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder) +{ + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + + /* + * Give a hand to buggy BIOSen which forget to turn + * the TMDS output buffers back on after a reboot. + */ + intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); +} + static void intel_hdmi_unset_edid(struct drm_connector *connector) { diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index b43a180d007e0..2bf440eb400ab 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -28,6 +28,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, int intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); +void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder); bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, struct drm_connector *connector, bool high_tmds_clock_ratio, From 0826edb6a5e5b32d38b89d2df3d74c4dac8828dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 29 Oct 2021 13:24:32 -0700 Subject: [PATCH 072/176] drm/i915/display: Check async flip state of every crtc and plane once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For every crtc in state, intel_atomic_check_async() was checking all the crtc and plane states again. v2: comparing pipe ids instead of crtc pointers when iterating over planes Cc: Karthik B S Cc: Vandita Kulkarni Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211029202432.140745-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 38 ++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 79cd158503b37..e494028260621 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7707,35 +7707,37 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state, * correspond to the last vblank and have no relation to the actual time when * the flip done event was sent. */ -static int intel_atomic_check_async(struct intel_atomic_state *state) +static int intel_atomic_check_async(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *old_crtc_state, *new_crtc_state; const struct intel_plane_state *new_plane_state, *old_plane_state; - struct intel_crtc *crtc; struct intel_plane *plane; int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { - if (intel_crtc_needs_modeset(new_crtc_state)) { - drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n"); - return -EINVAL; - } + old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - if (!new_crtc_state->hw.active) { - drm_dbg_kms(&i915->drm, "CRTC inactive\n"); - return -EINVAL; - } - if (old_crtc_state->active_planes != new_crtc_state->active_planes) { - drm_dbg_kms(&i915->drm, - "Active planes cannot be changed during async flip\n"); - return -EINVAL; - } + if (intel_crtc_needs_modeset(new_crtc_state)) { + drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n"); + return -EINVAL; + } + + if (!new_crtc_state->hw.active) { + drm_dbg_kms(&i915->drm, "CRTC inactive\n"); + return -EINVAL; + } + if (old_crtc_state->active_planes != new_crtc_state->active_planes) { + drm_dbg_kms(&i915->drm, + "Active planes cannot be changed during async flip\n"); + return -EINVAL; } for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + if (plane->pipe != crtc->pipe) + continue; + /* * TODO: Async flip is only supported through the page flip IOCTL * as of now. So support currently added for primary plane only. @@ -8054,7 +8056,7 @@ static int intel_atomic_check(struct drm_device *dev, for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (new_crtc_state->uapi.async_flip) { - ret = intel_atomic_check_async(state); + ret = intel_atomic_check_async(state, crtc); if (ret) goto fail; } From 112a87c48e83cf226325735009712b515f48c495 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 21 Oct 2021 13:59:15 +0300 Subject: [PATCH 073/176] drm/i915/display: program audio CDCLK-TS for keepalives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XE_LPD display adds support for display audio codec keepalive feature. This feature works also when display codec is in D3 state and the audio link is off (BCLK off). To enable this functionality, display driver must update the AUD_TS_CDCLK_M/N registers whenever CDCLK is changed. Actual timestamps are generated only when the audio codec driver specifically enables the KeepAlive (KAE) feature. This patch adds new hooks to intel_set_cdclk() in order to inform display audio driver when CDCLK change is started and when it is complete. Bspec: 53679 Signed-off-by: Kai Vehmanen Reviewed-by: Uma Shankar Acked-by: Ville Syrjälä Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20211021105915.4128635-1-kai.vehmanen@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 37 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_audio.h | 2 ++ drivers/gpu/drm/i915/display/intel_cdclk.c | 5 +++ drivers/gpu/drm/i915/i915_reg.h | 4 +++ 4 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 03e8c05a74f63..a96523f1b052d 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -947,6 +947,40 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv) } } +struct aud_ts_cdclk_m_n { + u8 m; + u16 n; +}; + +void intel_audio_cdclk_change_pre(struct drm_i915_private *i915) +{ + if (DISPLAY_VER(i915) >= 13) + intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0); +} + +static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts) +{ + if (refclk == 24000) + aud_ts->m = 12; + else + aud_ts->m = 15; + + aud_ts->n = cdclk * aud_ts->m / 24000; +} + +void intel_audio_cdclk_change_post(struct drm_i915_private *i915) +{ + struct aud_ts_cdclk_m_n aud_ts; + + if (DISPLAY_VER(i915) >= 13) { + get_aud_ts_cdclk_m_n(i915->cdclk.hw.ref, i915->cdclk.hw.cdclk, &aud_ts); + + intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n); + intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN); + drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n); + } +} + static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state, struct intel_crtc *crtc, bool enable) @@ -1330,6 +1364,9 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv) dev_priv->audio_freq_cntrl = aud_freq; } + /* init with current cdclk */ + intel_audio_cdclk_change_post(dev_priv); + dev_priv->audio_component_registered = true; } diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index a3657c7a7ba2d..dcb259dd2da74 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -18,6 +18,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, void intel_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state); +void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv); +void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv); void intel_audio_init(struct drm_i915_private *dev_priv); void intel_audio_deinit(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 868dd43a7542f..91c19e0a98d7b 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -24,6 +24,7 @@ #include #include "intel_atomic.h" +#include "intel_audio.h" #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_de.h" @@ -1975,6 +1976,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv, intel_psr_pause(intel_dp); } + intel_audio_cdclk_change_pre(dev_priv); + /* * Lock aux/gmbus while we change cdclk in case those * functions use cdclk. Not all platforms/ports do, @@ -2003,6 +2006,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv, intel_psr_resume(intel_dp); } + intel_audio_cdclk_change_post(dev_priv); + if (drm_WARN(&dev_priv->drm, intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config), "cdclk state doesn't match!\n")) { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4f1d8275ad07..beeffbff6cf9d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9782,6 +9782,10 @@ enum { #define AUD_PIN_BUF_CTL _MMIO(0x48414) #define AUD_PIN_BUF_ENABLE REG_BIT(31) +#define AUD_TS_CDCLK_M _MMIO(0x65ea0) +#define AUD_TS_CDCLK_M_EN REG_BIT(31) +#define AUD_TS_CDCLK_N _MMIO(0x65ea4) + /* Display Audio Config Reg */ #define AUD_CONFIG_BE _MMIO(0x65ef0) #define HBLANK_EARLY_ENABLE_ICL(pipe) (0x1 << (20 - (pipe))) From 2ee5ef9c934ad26376c9282171e731e6c0339815 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:50:59 +0300 Subject: [PATCH 074/176] drm/i915/fb: Fix rounding error in subsampled plane size calculation For NV12 FBs with odd main surface tile-row height the CCS surface height was incorrectly calculated 1 less than the actual value. Fix this by rounding up the result of divison. For consistency do the same for the CCS surface width calculation. Fixes: b3e57bccd68a ("drm/i915/tgl: Gen-12 render decompression") Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 117e32fb3648e..221486dd42e44 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -822,8 +822,8 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane); intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane); - *w = main_width / main_hsub / hsub; - *h = main_height / main_vsub / vsub; + *w = DIV_ROUND_UP(main_width, main_hsub * hsub); + *h = DIV_ROUND_UP(main_height, main_vsub * vsub); } static u32 intel_adjust_tile_offset(int *x, int *y, From 6b6636e17649d75b4d0cc55d3dff9e44511a442a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:00 +0300 Subject: [PATCH 075/176] drm/i915/adlp/fb: Prevent the mapping of redundant trailing padding NULL pages So far the remapped view size in GTT/DPT was padded to the next aligned offset unnecessarily after the last color plane with an unaligned size. Remove the unnecessary padding. Cc: Juha-Pekka Heikkila Fixes: 3d1adc3d64cf ("drm/i915/adlp: Add support for remapping CCS FBs") Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 9 ++++++++- drivers/gpu/drm/i915/gt/intel_ggtt.c | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e494028260621..e43a8a3c71ff9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -620,9 +620,16 @@ unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info int i; for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) { + unsigned int plane_size; + + plane_size = rem_info->plane[i].dst_stride * rem_info->plane[i].height; + if (plane_size == 0) + continue; + if (rem_info->plane_alignment) size = ALIGN(size, rem_info->plane_alignment); - size += rem_info->plane[i].dst_stride * rem_info->plane[i].height; + + size += plane_size; } return size; diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index f17383e76eb71..57c97554393b9 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -1396,6 +1396,9 @@ remap_pages(struct drm_i915_gem_object *obj, { unsigned int row; + if (!width || !height) + return sg; + if (alignment_pad) { st->nents++; From dd5ba4ff4e924b14cb3c91335636baa6bacaf817 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:01 +0300 Subject: [PATCH 076/176] drm/i915/fb: Factor out functions to remap contiguous FB obj pages Factor out functions needed to map contiguous FB obj pages to a GTT/DPT VMA view in the next patch. While at it s/4096/I915_GTT_PAGE_SIZE/ in add_padding_pages(). No functional changes. v2: s/4096/I915_GTT_PAGE_SIZE/ (Matthew) Signed-off-by: Imre Deak Reviewed-by: Matthew Auld Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-4-imre.deak@intel.com --- drivers/gpu/drm/i915/gt/intel_ggtt.c | 110 +++++++++++++++------------ 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 57c97554393b9..d2f45bca05d16 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -1387,6 +1387,25 @@ intel_rotate_pages(struct intel_rotation_info *rot_info, return ERR_PTR(ret); } +static struct scatterlist * +add_padding_pages(unsigned int count, + struct sg_table *st, struct scatterlist *sg) +{ + st->nents++; + + /* + * The DE ignores the PTEs for the padding tiles, the sg entry + * here is just a convenience to indicate how many padding PTEs + * to insert at this spot. + */ + sg_set_page(sg, NULL, count * I915_GTT_PAGE_SIZE, 0); + sg_dma_address(sg) = 0; + sg_dma_len(sg) = count * I915_GTT_PAGE_SIZE; + sg = sg_next(sg); + + return sg; +} + static struct scatterlist * remap_pages(struct drm_i915_gem_object *obj, unsigned int offset, unsigned int alignment_pad, @@ -1399,19 +1418,8 @@ remap_pages(struct drm_i915_gem_object *obj, if (!width || !height) return sg; - if (alignment_pad) { - st->nents++; - - /* - * The DE ignores the PTEs for the padding tiles, the sg entry - * here is just a convenience to indicate how many padding PTEs - * to insert at this spot. - */ - sg_set_page(sg, NULL, alignment_pad * 4096, 0); - sg_dma_address(sg) = 0; - sg_dma_len(sg) = alignment_pad * 4096; - sg = sg_next(sg); - } + if (alignment_pad) + sg = add_padding_pages(alignment_pad, st, sg); for (row = 0; row < height; row++) { unsigned int left = width * I915_GTT_PAGE_SIZE; @@ -1448,22 +1456,45 @@ remap_pages(struct drm_i915_gem_object *obj, if (!left) continue; - st->nents++; - - /* - * The DE ignores the PTEs for the padding tiles, the sg entry - * here is just a conenience to indicate how many padding PTEs - * to insert at this spot. - */ - sg_set_page(sg, NULL, left, 0); - sg_dma_address(sg) = 0; - sg_dma_len(sg) = left; - sg = sg_next(sg); + sg = add_padding_pages(left >> PAGE_SHIFT, st, sg); } return sg; } +static struct scatterlist * +remap_contiguous_pages(struct drm_i915_gem_object *obj, + unsigned int obj_offset, + unsigned int count, + struct sg_table *st, struct scatterlist *sg) +{ + struct scatterlist *iter; + unsigned int offset; + + iter = i915_gem_object_get_sg_dma(obj, obj_offset, &offset); + GEM_BUG_ON(!iter); + + do { + unsigned int len; + + len = min(sg_dma_len(iter) - (offset << PAGE_SHIFT), + count << PAGE_SHIFT); + sg_set_page(sg, NULL, len, 0); + sg_dma_address(sg) = + sg_dma_address(iter) + (offset << PAGE_SHIFT); + sg_dma_len(sg) = len; + + st->nents++; + count -= len >> PAGE_SHIFT; + if (count == 0) + return sg; + + sg = __sg_next(sg); + iter = __sg_next(iter); + offset = 0; + } while (1); +} + static noinline struct sg_table * intel_remap_pages(struct intel_remapped_info *rem_info, struct drm_i915_gem_object *obj) @@ -1524,9 +1555,8 @@ intel_partial_pages(const struct i915_ggtt_view *view, struct drm_i915_gem_object *obj) { struct sg_table *st; - struct scatterlist *sg, *iter; + struct scatterlist *sg; unsigned int count = view->partial.size; - unsigned int offset; int ret = -ENOMEM; st = kmalloc(sizeof(*st), GFP_KERNEL); @@ -1537,34 +1567,14 @@ intel_partial_pages(const struct i915_ggtt_view *view, if (ret) goto err_sg_alloc; - iter = i915_gem_object_get_sg_dma(obj, view->partial.offset, &offset); - GEM_BUG_ON(!iter); - - sg = st->sgl; st->nents = 0; - do { - unsigned int len; - len = min(sg_dma_len(iter) - (offset << PAGE_SHIFT), - count << PAGE_SHIFT); - sg_set_page(sg, NULL, len, 0); - sg_dma_address(sg) = - sg_dma_address(iter) + (offset << PAGE_SHIFT); - sg_dma_len(sg) = len; + sg = remap_contiguous_pages(obj, view->partial.offset, count, st, st->sgl); - st->nents++; - count -= len >> PAGE_SHIFT; - if (count == 0) { - sg_mark_end(sg); - i915_sg_trim(st); /* Drop any unused tail entries. */ + sg_mark_end(sg); + i915_sg_trim(st); /* Drop any unused tail entries. */ - return st; - } - - sg = __sg_next(sg); - iter = __sg_next(iter); - offset = 0; - } while (1); + return st; err_sg_alloc: kfree(st); From 96837e8beeefe5181adabab2da6e08c51dc0cf5d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:02 +0300 Subject: [PATCH 077/176] drm/i915/adlp/fb: Fix remapping of linear CCS AUX surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During remapping CCS FBs the CCS AUX surface mapped size and offset->x,y coordinate calculations assumed a tiled layout. This works as long as the CCS surface height is aligned to 64 lines (ensuring a 4k bytes CCS surface tile layout). However this alignment is not required by the HW (and the driver doesn't enforces it either). Add the remapping logic required to remap the pages of CCS surfaces without the above alignment, assuming the natural linear layout of the CCS surface (vs. tiled main surface layout). Cc: Juha-Pekka Heikkila Cc: Ville Syrjälä Fixes: 3d1adc3d64cf ("drm/i915/adlp: Add support for remapping CCS FBs") Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 6 +- drivers/gpu/drm/i915/display/intel_fb.c | 107 ++++++++++++++----- drivers/gpu/drm/i915/gt/intel_ggtt.c | 85 +++++++++++---- drivers/gpu/drm/i915/i915_vma_types.h | 19 +++- 4 files changed, 164 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e43a8a3c71ff9..cad8998e68536 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -622,7 +622,11 @@ unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) { unsigned int plane_size; - plane_size = rem_info->plane[i].dst_stride * rem_info->plane[i].height; + if (rem_info->plane[i].linear) + plane_size = rem_info->plane[i].size; + else + plane_size = rem_info->plane[i].dst_stride * rem_info->plane[i].height; + if (plane_size == 0) continue; diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 221486dd42e44..ded1f74f611c5 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -853,6 +853,20 @@ static u32 intel_adjust_tile_offset(int *x, int *y, return new_offset; } +static u32 intel_adjust_linear_offset(int *x, int *y, + unsigned int cpp, + unsigned int pitch, + u32 old_offset, + u32 new_offset) +{ + old_offset += *y * pitch + *x * cpp; + + *y = (old_offset - new_offset) / pitch; + *x = ((old_offset - new_offset) - *y * pitch) / cpp; + + return new_offset; +} + static u32 intel_adjust_aligned_offset(int *x, int *y, const struct drm_framebuffer *fb, int color_plane, @@ -883,10 +897,8 @@ static u32 intel_adjust_aligned_offset(int *x, int *y, tile_size, pitch_tiles, old_offset, new_offset); } else { - old_offset += *y * pitch + *x * cpp; - - *y = (old_offset - new_offset) / pitch; - *x = ((old_offset - new_offset) - *y * pitch) / cpp; + intel_adjust_linear_offset(x, y, cpp, pitch, + old_offset, new_offset); } return new_offset; @@ -1258,12 +1270,11 @@ plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane, unsigned int pitch_tiles) { if (intel_fb_needs_pot_stride_remap(fb)) { - unsigned int min_stride = intel_fb_is_ccs_aux_plane(&fb->base, color_plane) ? 2 : 8; /* * ADL_P, the only platform needing a POT stride has a minimum - * of 8 main surface and 2 CCS AUX stride tiles. + * of 8 main surface tiles. */ - return roundup_pow_of_two(max(pitch_tiles, min_stride)); + return roundup_pow_of_two(max(pitch_tiles, 8u)); } else { return pitch_tiles; } @@ -1285,11 +1296,31 @@ plane_view_height_tiles(const struct intel_framebuffer *fb, int color_plane, return DIV_ROUND_UP(y + dims->height, dims->tile_height); } +static unsigned int +plane_view_linear_tiles(const struct intel_framebuffer *fb, int color_plane, + const struct fb_plane_view_dims *dims, + int x, int y) +{ + struct drm_i915_private *i915 = to_i915(fb->base.dev); + unsigned int size; + + size = (y + dims->height) * fb->base.pitches[color_plane] + + x * fb->base.format->cpp[color_plane]; + + return DIV_ROUND_UP(size, intel_tile_size(i915)); +} + #define assign_chk_ovf(i915, var, val) ({ \ drm_WARN_ON(&(i915)->drm, overflows_type(val, var)); \ (var) = (val); \ }) +#define assign_bfld_chk_ovf(i915, var, val) ({ \ + (var) = (val); \ + drm_WARN_ON(&(i915)->drm, (var) != (val)); \ + (var); \ +}) + static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_plane, const struct fb_plane_view_dims *dims, u32 obj_offset, u32 gtt_offset, int x, int y, @@ -1304,12 +1335,26 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p struct drm_rect r; u32 size = 0; - assign_chk_ovf(i915, remap_info->offset, obj_offset); - assign_chk_ovf(i915, remap_info->src_stride, plane_view_src_stride_tiles(fb, color_plane, dims)); - assign_chk_ovf(i915, remap_info->width, plane_view_width_tiles(fb, color_plane, dims, x)); - assign_chk_ovf(i915, remap_info->height, plane_view_height_tiles(fb, color_plane, dims, y)); + assign_bfld_chk_ovf(i915, remap_info->offset, obj_offset); + + if (intel_fb_is_gen12_ccs_aux_plane(&fb->base, color_plane)) { + remap_info->linear = 1; + + assign_chk_ovf(i915, remap_info->size, + plane_view_linear_tiles(fb, color_plane, dims, x, y)); + } else { + remap_info->linear = 0; + + assign_chk_ovf(i915, remap_info->src_stride, + plane_view_src_stride_tiles(fb, color_plane, dims)); + assign_chk_ovf(i915, remap_info->width, + plane_view_width_tiles(fb, color_plane, dims, x)); + assign_chk_ovf(i915, remap_info->height, + plane_view_height_tiles(fb, color_plane, dims, y)); + } if (view->gtt.type == I915_GGTT_VIEW_ROTATED) { + drm_WARN_ON(&i915->drm, remap_info->linear); check_array_bounds(i915, view->gtt.rotated.plane, color_plane); assign_chk_ovf(i915, remap_info->dst_stride, @@ -1344,16 +1389,23 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p gtt_offset = aligned_offset; } - assign_chk_ovf(i915, remap_info->dst_stride, - plane_view_dst_stride_tiles(fb, color_plane, remap_info->width)); - color_plane_info->x = x; color_plane_info->y = y; - color_plane_info->stride = remap_info->dst_stride * tile_width * - fb->base.format->cpp[color_plane]; + if (remap_info->linear) { + color_plane_info->stride = fb->base.pitches[color_plane]; + + size += remap_info->size; + } else { + unsigned int dst_stride = plane_view_dst_stride_tiles(fb, color_plane, + remap_info->width); + + assign_chk_ovf(i915, remap_info->dst_stride, dst_stride); + color_plane_info->stride = dst_stride * + tile_width * fb->base.format->cpp[color_plane]; - size += remap_info->dst_stride * remap_info->height; + size += dst_stride * remap_info->height; + } } /* @@ -1361,10 +1413,16 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p * the x/y offsets. x,y will hold the first pixel of the framebuffer * plane from the start of the remapped/rotated gtt mapping. */ - intel_adjust_tile_offset(&color_plane_info->x, &color_plane_info->y, - tile_width, tile_height, - tile_size, remap_info->dst_stride, - gtt_offset * tile_size, 0); + if (remap_info->linear) + intel_adjust_linear_offset(&color_plane_info->x, &color_plane_info->y, + fb->base.format->cpp[color_plane], + color_plane_info->stride, + gtt_offset * tile_size, 0); + else + intel_adjust_tile_offset(&color_plane_info->x, &color_plane_info->y, + tile_width, tile_height, + tile_size, remap_info->dst_stride, + gtt_offset * tile_size, 0); return size; } @@ -1377,15 +1435,10 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane, const struct fb_plane_view_dims *dims, int x, int y) { - struct drm_i915_private *i915 = to_i915(fb->base.dev); unsigned int tiles; if (is_surface_linear(&fb->base, color_plane)) { - unsigned int size; - - size = (y + dims->height) * fb->base.pitches[color_plane] + - x * fb->base.format->cpp[color_plane]; - tiles = DIV_ROUND_UP(size, intel_tile_size(i915)); + tiles = plane_view_linear_tiles(fb, color_plane, dims, x, y); } else { tiles = plane_view_src_stride_tiles(fb, color_plane, dims) * plane_view_height_tiles(fb, color_plane, dims, y); diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index d2f45bca05d16..c679d8e81f238 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -1407,11 +1407,12 @@ add_padding_pages(unsigned int count, } static struct scatterlist * -remap_pages(struct drm_i915_gem_object *obj, - unsigned int offset, unsigned int alignment_pad, - unsigned int width, unsigned int height, - unsigned int src_stride, unsigned int dst_stride, - struct sg_table *st, struct scatterlist *sg) +remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj, + unsigned int offset, unsigned int alignment_pad, + unsigned int width, unsigned int height, + unsigned int src_stride, unsigned int dst_stride, + struct sg_table *st, struct scatterlist *sg, + unsigned int *gtt_offset) { unsigned int row; @@ -1459,6 +1460,8 @@ remap_pages(struct drm_i915_gem_object *obj, sg = add_padding_pages(left >> PAGE_SHIFT, st, sg); } + *gtt_offset += alignment_pad + dst_stride * height; + return sg; } @@ -1495,6 +1498,61 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj, } while (1); } +static struct scatterlist * +remap_linear_color_plane_pages(struct drm_i915_gem_object *obj, + unsigned int obj_offset, unsigned int alignment_pad, + unsigned int size, + struct sg_table *st, struct scatterlist *sg, + unsigned int *gtt_offset) +{ + if (!size) + return sg; + + if (alignment_pad) + sg = add_padding_pages(alignment_pad, st, sg); + + sg = remap_contiguous_pages(obj, obj_offset, size, st, sg); + sg = sg_next(sg); + + *gtt_offset += alignment_pad + size; + + return sg; +} + +static struct scatterlist * +remap_color_plane_pages(const struct intel_remapped_info *rem_info, + struct drm_i915_gem_object *obj, + int color_plane, + struct sg_table *st, struct scatterlist *sg, + unsigned int *gtt_offset) +{ + unsigned int alignment_pad = 0; + + if (rem_info->plane_alignment) + alignment_pad = ALIGN(*gtt_offset, rem_info->plane_alignment) - *gtt_offset; + + if (rem_info->plane[color_plane].linear) + sg = remap_linear_color_plane_pages(obj, + rem_info->plane[color_plane].offset, + alignment_pad, + rem_info->plane[color_plane].size, + st, sg, + gtt_offset); + + else + sg = remap_tiled_color_plane_pages(obj, + rem_info->plane[color_plane].offset, + alignment_pad, + rem_info->plane[color_plane].width, + rem_info->plane[color_plane].height, + rem_info->plane[color_plane].src_stride, + rem_info->plane[color_plane].dst_stride, + st, sg, + gtt_offset); + + return sg; +} + static noinline struct sg_table * intel_remap_pages(struct intel_remapped_info *rem_info, struct drm_i915_gem_object *obj) @@ -1519,21 +1577,8 @@ intel_remap_pages(struct intel_remapped_info *rem_info, st->nents = 0; sg = st->sgl; - for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) { - unsigned int alignment_pad = 0; - - if (rem_info->plane_alignment) - alignment_pad = ALIGN(gtt_offset, rem_info->plane_alignment) - gtt_offset; - - sg = remap_pages(obj, - rem_info->plane[i].offset, alignment_pad, - rem_info->plane[i].width, rem_info->plane[i].height, - rem_info->plane[i].src_stride, rem_info->plane[i].dst_stride, - st, sg); - - gtt_offset += alignment_pad + - rem_info->plane[i].dst_stride * rem_info->plane[i].height; - } + for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) + sg = remap_color_plane_pages(rem_info, obj, i, st, sg, >t_offset); i915_sg_trim(st); diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index 80e93bf00f2e5..4ee6e54799f48 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -97,11 +97,20 @@ enum i915_cache_level; struct intel_remapped_plane_info { /* in gtt pages */ - u32 offset; - u16 width; - u16 height; - u16 src_stride; - u16 dst_stride; + u32 offset:31; + u32 linear:1; + union { + /* in gtt pages for !linear */ + struct { + u16 width; + u16 height; + u16 src_stride; + u16 dst_stride; + }; + + /* in gtt pages for linear */ + u32 size; + }; } __packed; struct intel_remapped_info { From be6c1dd5ac074defdfb1471d28e0bb6eedfe3ae5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:03 +0300 Subject: [PATCH 078/176] drm/i915/fb: Rename i915_color_plane_view::stride to mapping_stride The next patch needs to distinguish between a view's mapping and scanout stride. Rename the current stride parameter to mapping_stride with the script below. mapping_stride will keep the same meaning as stride had on all platforms so far, while the meaning of it will change on ADLP. No functional changes. @@ identifier intel_fb_view; identifier i915_color_plane_view; identifier color_plane; expression e; type T; @@ struct intel_fb_view { ... struct i915_color_plane_view { ... - T stride; + T mapping_stride; ... } color_plane[e]; ... }; @@ struct i915_color_plane_view pv; @@ pv. - stride + mapping_stride @@ struct i915_color_plane_view *pvp; @@ pvp-> - stride + mapping_stride Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-6-imre.deak@intel.com --- drivers/gpu/drm/i915/display/i9xx_plane.c | 4 +-- drivers/gpu/drm/i915/display/intel_cursor.c | 6 ++--- drivers/gpu/drm/i915/display/intel_display.c | 6 ++--- .../drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_fb.c | 25 ++++++++++--------- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- drivers/gpu/drm/i915/display/intel_sprite.c | 8 +++--- .../drm/i915/display/skl_universal_plane.c | 4 +-- 8 files changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 2e16a66e8f9e7..c8722771aa406 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -256,7 +256,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) u32 alignment = intel_surf_alignment(fb, 0); int cpp = fb->format->cpp[0]; - while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].stride) { + while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) { if (offset == 0) { drm_dbg_kms(&dev_priv->drm, "Unable to find suitable display surface offset due to X-tiling\n"); @@ -431,7 +431,7 @@ static void i9xx_update_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), - plane_state->view.color_plane[0].stride); + plane_state->view.color_plane[0].mapping_stride); if (DISPLAY_VER(dev_priv) < 4) { /* diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 5ddd3c8fbc634..e069a3fb8b995 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -190,7 +190,7 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, { return CURSOR_ENABLE | CURSOR_FORMAT_ARGB | - CURSOR_STRIDE(plane_state->view.color_plane[0].stride); + CURSOR_STRIDE(plane_state->view.color_plane[0].mapping_stride); } static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state) @@ -229,7 +229,7 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state, } drm_WARN_ON(&i915->drm, plane_state->uapi.visible && - plane_state->view.color_plane[0].stride != fb->pitches[0]); + plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]); switch (fb->pitches[0]) { case 256: @@ -450,7 +450,7 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, } drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible && - plane_state->view.color_plane[0].stride != fb->pitches[0]); + plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]); if (fb->pitches[0] != drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index cad8998e68536..29392dfc46c8d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -661,7 +661,7 @@ u32 intel_fb_xy_to_linear(int x, int y, { const struct drm_framebuffer *fb = state->hw.fb; unsigned int cpp = fb->format->cpp[color_plane]; - unsigned int pitch = state->view.color_plane[color_plane].stride; + unsigned int pitch = state->view.color_plane[color_plane].mapping_stride; return y * pitch + x * cpp; } @@ -7775,8 +7775,8 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int return -EINVAL; } - if (old_plane_state->view.color_plane[0].stride != - new_plane_state->view.color_plane[0].stride) { + if (old_plane_state->view.color_plane[0].mapping_stride != + new_plane_state->view.color_plane[0].mapping_stride) { drm_dbg_kms(&i915->drm, "Stride cannot be changed in async flip\n"); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 991972da07038..1107cbd93260d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -115,7 +115,7 @@ struct intel_fb_view { * bytes for 0/180 degree rotation * pixels for 90/270 degree rotation */ - unsigned int stride; + unsigned int mapping_stride; } color_plane[4]; }; diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index ded1f74f611c5..e0414fb4b0369 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -915,7 +915,7 @@ u32 intel_plane_adjust_aligned_offset(int *x, int *y, { return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane, state->hw.rotation, - state->view.color_plane[color_plane].stride, + state->view.color_plane[color_plane].mapping_stride, old_offset, new_offset); } @@ -996,7 +996,7 @@ u32 intel_plane_compute_aligned_offset(int *x, int *y, struct drm_i915_private *i915 = to_i915(intel_plane->base.dev); const struct drm_framebuffer *fb = state->hw.fb; unsigned int rotation = state->hw.rotation; - int pitch = state->view.color_plane[color_plane].stride; + int pitch = state->view.color_plane[color_plane].mapping_stride; u32 alignment; if (intel_plane->id == PLANE_CURSOR) @@ -1155,11 +1155,11 @@ bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb) static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation) { if (drm_rotation_90_or_270(rotation)) - return fb->rotated_view.color_plane[color_plane].stride; + return fb->rotated_view.color_plane[color_plane].mapping_stride; else if (intel_fb_needs_pot_stride_remap(fb)) - return fb->remapped_view.color_plane[color_plane].stride; + return fb->remapped_view.color_plane[color_plane].mapping_stride; else - return fb->normal_view.color_plane[color_plane].stride; + return fb->normal_view.color_plane[color_plane].mapping_stride; } static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) @@ -1370,7 +1370,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p color_plane_info->x = r.x1; color_plane_info->y = r.y1; - color_plane_info->stride = remap_info->dst_stride * tile_height; + color_plane_info->mapping_stride = remap_info->dst_stride * tile_height; size += remap_info->dst_stride * remap_info->width; @@ -1393,7 +1393,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p color_plane_info->y = y; if (remap_info->linear) { - color_plane_info->stride = fb->base.pitches[color_plane]; + color_plane_info->mapping_stride = fb->base.pitches[color_plane]; size += remap_info->size; } else { @@ -1401,8 +1401,9 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p remap_info->width); assign_chk_ovf(i915, remap_info->dst_stride, dst_stride); - color_plane_info->stride = dst_stride * - tile_width * fb->base.format->cpp[color_plane]; + color_plane_info->mapping_stride = dst_stride * + tile_width * + fb->base.format->cpp[color_plane]; size += dst_stride * remap_info->height; } @@ -1416,7 +1417,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p if (remap_info->linear) intel_adjust_linear_offset(&color_plane_info->x, &color_plane_info->y, fb->base.format->cpp[color_plane], - color_plane_info->stride, + color_plane_info->mapping_stride, gtt_offset * tile_size, 0); else intel_adjust_tile_offset(&color_plane_info->x, &color_plane_info->y, @@ -1527,7 +1528,7 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * */ fb->normal_view.color_plane[i].x = x; fb->normal_view.color_plane[i].y = y; - fb->normal_view.color_plane[i].stride = fb->base.pitches[i]; + fb->normal_view.color_plane[i].mapping_stride = fb->base.pitches[i]; offset = calc_plane_aligned_offset(fb, i, &x, &y); @@ -1721,7 +1722,7 @@ static int intel_plane_check_stride(const struct intel_plane_state *plane_state) return 0; /* FIXME other color planes? */ - stride = plane_state->view.color_plane[0].stride; + stride = plane_state->view.color_plane[0].mapping_stride; max_stride = plane->max_stride(plane, fb->format->format, fb->modifier, rotation); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 1f66de77a6b1e..834eb4cc7c105 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -68,7 +68,7 @@ static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int stride; - stride = plane_state->view.color_plane[0].stride; + stride = plane_state->view.color_plane[0].mapping_stride; if (!drm_rotation_90_or_270(plane_state->hw.rotation)) stride /= fb->format->cpp[0]; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 367515a70ac4c..1d710b3e51ee7 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -448,7 +448,7 @@ vlv_update_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id), - plane_state->view.color_plane[0].stride); + plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id), @@ -872,7 +872,7 @@ ivb_update_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPRSTRIDE(pipe), - plane_state->view.color_plane[0].stride); + plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, SPRPOS(pipe), (crtc_y << 16) | crtc_x); intel_de_write_fw(dev_priv, SPRSIZE(pipe), (crtc_h << 16) | crtc_w); if (IS_IVYBRIDGE(dev_priv)) @@ -1200,7 +1200,7 @@ g4x_update_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DVSSTRIDE(pipe), - plane_state->view.color_plane[0].stride); + plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, DVSPOS(pipe), (crtc_y << 16) | crtc_x); intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w); intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale); @@ -1300,7 +1300,7 @@ g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, int src_x, src_w, src_h, crtc_w, crtc_h; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - unsigned int stride = plane_state->view.color_plane[0].stride; + unsigned int stride = plane_state->view.color_plane[0].mapping_stride; unsigned int cpp = fb->format->cpp[0]; unsigned int width_bytes; int min_width, min_height; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index ef7856db09f79..7795ecd8c0fcd 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -589,7 +589,7 @@ static u32 skl_plane_stride(const struct intel_plane_state *plane_state, { const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; - u32 stride = plane_state->view.color_plane[color_plane].stride; + u32 stride = plane_state->view.color_plane[color_plane].mapping_stride; if (color_plane >= fb->format->num_planes) return 0; @@ -1433,7 +1433,7 @@ int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, if (fb->modifier == I915_FORMAT_MOD_X_TILED) { int cpp = fb->format->cpp[0]; - while ((*x + w) * cpp > plane_state->view.color_plane[0].stride) { + while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) { if (*offset == 0) { drm_dbg_kms(&dev_priv->drm, "Unable to find suitable display surface offset due to X-tiling\n"); From 17749ece0142c7c368834b6fb35d86bafecef69f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:04 +0300 Subject: [PATCH 079/176] drm/i915/adlp/fb: Remove restriction on semiplanar UV plane offset Since the surfaces of tiled FBs on ADLP are remapped it's pointless to require an alignment in the allocated object. The necessary tile-row alignment (to be programmed to the surface start register) will be ensured later when flipping to the FB. Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-7-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index e0414fb4b0369..c19a5f8816448 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1018,6 +1018,7 @@ static int intel_fb_offset_to_xy(int *x, int *y, u32 alignment; if (DISPLAY_VER(i915) >= 12 && + !intel_fb_needs_pot_stride_remap(to_intel_framebuffer(fb)) && is_semiplanar_uv_plane(fb, color_plane)) alignment = intel_tile_row_size(fb, color_plane); else if (fb->modifier != DRM_FORMAT_MOD_LINEAR) From e6d6f689435aaebc2e407026d9fdfc2d89bd7902 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:05 +0300 Subject: [PATCH 080/176] drm/i915/adlp/fb: Remove restriction on CCS AUX plane strides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As opposed to other GEN12 platforms ADLP provides a way to program the stride of CCS surfaces independently of the main surface stride (within the corresponding limit of the preceding and succeeding power-of-two values of the main surface stride). Using this HW feature we can remove the POT stride restriction on CCS surfaces, making the ADLP CCS FB uAPI (FB modifiers) identical to that of TGL. The HW makes the CCS stride flexible programming possible by deriving the stride from the value programmed to the PLANE_STRIDE register. After that the HW rounds up this value to the next power-of-two value and uses this for walking the pages of the main surface mapped to GTT/DPT. To align with the above scheme, introduce a scanout_stride view parameter which will be programmed to the PLANE_STRIDE register and use the mapping_stride view param to store the POT aligned value of the same. By requiring userspace to pass in FBs with a CCS stride that aligns with the main surface stride (matching the requirement of all GEN12 platforms), the scanout_stride will be the userspace main surface stride and the mapping_stride will be the POT rounded value of the same. Cc: Ville Syrjälä Cc: Juha-Pekka Heikkila Cc: Nanley G Chery Cc: Sameer Lattannavar Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-8-imre.deak@intel.com --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_fb.c | 67 +++++++------------ .../drm/i915/display/skl_universal_plane.c | 2 +- 3 files changed, 26 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 1107cbd93260d..a174b0b83640b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -116,6 +116,7 @@ struct intel_fb_view { * pixels for 90/270 degree rotation */ unsigned int mapping_stride; + unsigned int scanout_stride; } color_plane[4]; }; diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index c19a5f8816448..c4a743d0913fc 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -503,35 +503,12 @@ int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane) return ccs_plane - fb->format->num_planes / 2; } -static unsigned int gen12_aligned_scanout_stride(const struct intel_framebuffer *fb, - int color_plane) -{ - struct drm_i915_private *i915 = to_i915(fb->base.dev); - unsigned int stride = fb->base.pitches[color_plane]; - - if (IS_ALDERLAKE_P(i915)) - return roundup_pow_of_two(max(stride, - 8u * intel_tile_width_bytes(&fb->base, color_plane))); - - return stride; -} - static unsigned int gen12_ccs_aux_stride(struct intel_framebuffer *fb, int ccs_plane) { - struct drm_i915_private *i915 = to_i915(fb->base.dev); int main_plane = skl_ccs_to_main_plane(&fb->base, ccs_plane); unsigned int main_stride = fb->base.pitches[main_plane]; unsigned int main_tile_width = intel_tile_width_bytes(&fb->base, main_plane); - /* - * On ADL-P the AUX stride must align with a power-of-two aligned main - * surface stride. The stride of the allocated main surface object can - * be less than this POT stride, which is then autopadded to the POT - * size. - */ - if (IS_ALDERLAKE_P(i915)) - main_stride = gen12_aligned_scanout_stride(fb, main_plane); - return DIV_ROUND_UP(main_stride, 4 * main_tile_width) * 64; } @@ -801,7 +778,6 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub, static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_plane, int *w, int *h) { - struct drm_i915_private *i915 = to_i915(fb->base.dev); int main_plane = intel_fb_is_ccs_aux_plane(&fb->base, color_plane) ? skl_ccs_to_main_plane(&fb->base, color_plane) : 0; unsigned int main_width = fb->base.width; @@ -809,16 +785,6 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl int main_hsub, main_vsub; int hsub, vsub; - /* - * On ADL-P the CCS AUX surface layout always aligns with the - * power-of-two aligned main surface stride. The main surface - * stride in the allocated FB object may not be power-of-two - * sized, in which case it is auto-padded to the POT size. - */ - if (IS_ALDERLAKE_P(i915) && intel_fb_is_ccs_aux_plane(&fb->base, color_plane)) - main_width = gen12_aligned_scanout_stride(fb, 0) / - fb->base.format->cpp[0]; - intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane); intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane); @@ -1281,6 +1247,21 @@ plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane, } } +static unsigned int +plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane, + unsigned int tile_width, + unsigned int src_stride_tiles, unsigned int dst_stride_tiles) +{ + unsigned int stride_tiles; + + if (IS_ALDERLAKE_P(to_i915(fb->base.dev))) + stride_tiles = src_stride_tiles; + else + stride_tiles = dst_stride_tiles; + + return stride_tiles * tile_width * fb->base.format->cpp[color_plane]; +} + static unsigned int plane_view_width_tiles(const struct intel_framebuffer *fb, int color_plane, const struct fb_plane_view_dims *dims, @@ -1372,6 +1353,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p color_plane_info->y = r.y1; color_plane_info->mapping_stride = remap_info->dst_stride * tile_height; + color_plane_info->scanout_stride = color_plane_info->mapping_stride; size += remap_info->dst_stride * remap_info->width; @@ -1395,6 +1377,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p if (remap_info->linear) { color_plane_info->mapping_stride = fb->base.pitches[color_plane]; + color_plane_info->scanout_stride = color_plane_info->mapping_stride; size += remap_info->size; } else { @@ -1405,6 +1388,10 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p color_plane_info->mapping_stride = dst_stride * tile_width * fb->base.format->cpp[color_plane]; + color_plane_info->scanout_stride = + plane_view_scanout_stride(fb, color_plane, tile_width, + remap_info->src_stride, + dst_stride); size += dst_stride * remap_info->height; } @@ -1530,6 +1517,8 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * fb->normal_view.color_plane[i].x = x; fb->normal_view.color_plane[i].y = y; fb->normal_view.color_plane[i].mapping_stride = fb->base.pitches[i]; + fb->normal_view.color_plane[i].scanout_stride = + fb->normal_view.color_plane[i].mapping_stride; offset = calc_plane_aligned_offset(fb, i, &x, &y); @@ -1675,19 +1664,11 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) tile_width = intel_tile_width_bytes(fb, color_plane); if (intel_fb_is_ccs_modifier(fb->modifier)) { - /* - * On ADL-P the stride must be either 8 tiles or a stride - * that is aligned to 16 tiles, required by the 16 tiles = - * 64 kbyte CCS AUX PTE granularity, allowing CCS FBs to be - * remapped. - */ - if (IS_ALDERLAKE_P(dev_priv)) - tile_width *= fb->pitches[0] <= tile_width * 8 ? 8 : 16; /* * On TGL the surface stride must be 4 tile aligned, mapped by * one 64 byte cacheline on the CCS AUX surface. */ - else if (DISPLAY_VER(dev_priv) >= 12) + if (DISPLAY_VER(dev_priv) >= 12) tile_width *= 4; /* * Display WA #0531: skl,bxt,kbl,glk diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 7795ecd8c0fcd..91a79b1582c9e 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -589,7 +589,7 @@ static u32 skl_plane_stride(const struct intel_plane_state *plane_state, { const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; - u32 stride = plane_state->view.color_plane[color_plane].mapping_stride; + u32 stride = plane_state->view.color_plane[color_plane].scanout_stride; if (color_plane >= fb->format->num_planes) return 0; From 8d2f683f1c49b3a3c56ab92437722eda7e85bac2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 1 Nov 2021 20:35:50 +0200 Subject: [PATCH 081/176] drm/i915: Factor out i915_ggtt_suspend_vm/i915_ggtt_resume_vm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Factor out functions that are needed by the next patch to suspend/resume the memory mappings for DPT FBs. No functional change, except reordering during suspend the ggtt->invalidate(ggtt) call wrt. atomic_set(&ggtt->vm.open, open) and mutex_unlock(&ggtt->vm.mutex). This shouldn't matter due to the i915 suspend sequence being single threaded. Cc: Chris Wilson Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211101183551.3580546-1-imre.deak@intel.com --- drivers/gpu/drm/i915/gt/intel_ggtt.c | 71 +++++++++++++++++++++------- drivers/gpu/drm/i915/gt/intel_gtt.h | 2 + 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index c679d8e81f238..1fb4a03d7ac35 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -116,17 +116,26 @@ static bool needs_idle_maps(struct drm_i915_private *i915) return false; } -void i915_ggtt_suspend(struct i915_ggtt *ggtt) +/** + * i915_ggtt_suspend_vm - Suspend the memory mappings for a GGTT or DPT VM + * @vm: The VM to suspend the mappings for + * + * Suspend the memory mappings for all objects mapped to HW via the GGTT or a + * DPT page table. + */ +void i915_ggtt_suspend_vm(struct i915_address_space *vm) { struct i915_vma *vma, *vn; int open; - mutex_lock(&ggtt->vm.mutex); + drm_WARN_ON(&vm->i915->drm, !vm->is_ggtt && !vm->is_dpt); + + mutex_lock(&vm->mutex); /* Skip rewriting PTE on VMA unbind. */ - open = atomic_xchg(&ggtt->vm.open, 0); + open = atomic_xchg(&vm->open, 0); - list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link) { + list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) { GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); i915_vma_wait_for_bind(vma); @@ -139,11 +148,17 @@ void i915_ggtt_suspend(struct i915_ggtt *ggtt) } } - ggtt->vm.clear_range(&ggtt->vm, 0, ggtt->vm.total); - ggtt->invalidate(ggtt); - atomic_set(&ggtt->vm.open, open); + vm->clear_range(vm, 0, vm->total); - mutex_unlock(&ggtt->vm.mutex); + atomic_set(&vm->open, open); + + mutex_unlock(&vm->mutex); +} + +void i915_ggtt_suspend(struct i915_ggtt *ggtt) +{ + i915_ggtt_suspend_vm(&ggtt->vm); + ggtt->invalidate(ggtt); intel_gt_check_and_clear_faults(ggtt->vm.gt); } @@ -1253,37 +1268,59 @@ void i915_ggtt_disable_guc(struct i915_ggtt *ggtt) ggtt->invalidate(ggtt); } -void i915_ggtt_resume(struct i915_ggtt *ggtt) +/** + * i915_ggtt_resume_vm - Restore the memory mappings for a GGTT or DPT VM + * @vm: The VM to restore the mappings for + * + * Restore the memory mappings for all objects mapped to HW via the GGTT or a + * DPT page table. + * + * Returns %true if restoring the mapping for any object that was in a write + * domain before suspend. + */ +bool i915_ggtt_resume_vm(struct i915_address_space *vm) { struct i915_vma *vma; - bool flush = false; + bool write_domain_objs = false; int open; - intel_gt_check_and_clear_faults(ggtt->vm.gt); + drm_WARN_ON(&vm->i915->drm, !vm->is_ggtt && !vm->is_dpt); /* First fill our portion of the GTT with scratch pages */ - ggtt->vm.clear_range(&ggtt->vm, 0, ggtt->vm.total); + vm->clear_range(vm, 0, vm->total); /* Skip rewriting PTE on VMA unbind. */ - open = atomic_xchg(&ggtt->vm.open, 0); + open = atomic_xchg(&vm->open, 0); /* clflush objects bound into the GGTT and rebind them. */ - list_for_each_entry(vma, &ggtt->vm.bound_list, vm_link) { + list_for_each_entry(vma, &vm->bound_list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; unsigned int was_bound = atomic_read(&vma->flags) & I915_VMA_BIND_MASK; GEM_BUG_ON(!was_bound); - vma->ops->bind_vma(&ggtt->vm, NULL, vma, + vma->ops->bind_vma(vm, NULL, vma, obj ? obj->cache_level : 0, was_bound); if (obj) { /* only used during resume => exclusive access */ - flush |= fetch_and_zero(&obj->write_domain); + write_domain_objs |= fetch_and_zero(&obj->write_domain); obj->read_domains |= I915_GEM_DOMAIN_GTT; } } - atomic_set(&ggtt->vm.open, open); + atomic_set(&vm->open, open); + + return write_domain_objs; +} + +void i915_ggtt_resume(struct i915_ggtt *ggtt) +{ + bool flush; + + intel_gt_check_and_clear_faults(ggtt->vm.gt); + + flush = i915_ggtt_resume_vm(&ggtt->vm); + ggtt->invalidate(ggtt); if (flush) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index bc67502633599..dfeaef680aacd 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -544,6 +544,8 @@ int i915_ppgtt_init_hw(struct intel_gt *gt); struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt, unsigned long lmem_pt_obj_flags); +void i915_ggtt_suspend_vm(struct i915_address_space *vm); +bool i915_ggtt_resume_vm(struct i915_address_space *vm); void i915_ggtt_suspend(struct i915_ggtt *gtt); void i915_ggtt_resume(struct i915_ggtt *ggtt); From 9755f055f5121c40c481c1d5dd02a1c3fb0e7953 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 1 Nov 2021 20:35:51 +0200 Subject: [PATCH 082/176] drm/i915: Restore memory mapping for DPT FBs across system suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At least during hibernation the DPT mappings are lost with all stolen memory content, so suspend/resume these mappings similarly to GGTT mappings. This fixes a problem where the restoring modeset during system resume fails with pipe faults if a tiled framebuffer was active before suspend. v2: Clarify the way restore works in intel_dpt_resume()'s Docbook entry. (Chris) Cc: Chris Wilson Cc: Ville Syrjälä Cc: Vunny Sodhi Reported-and-tested-by: Vunny Sodhi Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211101183551.3580546-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpt.c | 52 ++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dpt.h | 4 ++ drivers/gpu/drm/i915/i915_drv.c | 5 +++ 3 files changed, 61 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 8f7b1f7534a48..56755788547d2 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -167,6 +167,58 @@ void intel_dpt_unpin(struct i915_address_space *vm) i915_vma_put(dpt->vma); } +/** + * intel_dpt_resume - restore the memory mapping for all DPT FBs during system resume + * @i915: device instance + * + * Restore the memory mapping during system resume for all framebuffers which + * are mapped to HW via a GGTT->DPT page table. The content of these page + * tables are not stored in the hibernation image during S4 and S3RST->S4 + * transitions, so here we reprogram the PTE entries in those tables. + * + * This function must be called after the mappings in GGTT have been restored calling + * i915_ggtt_resume(). + */ +void intel_dpt_resume(struct drm_i915_private *i915) +{ + struct drm_framebuffer *drm_fb; + + mutex_lock(&i915->drm.mode_config.fb_lock); + drm_for_each_fb(drm_fb, &i915->drm) { + struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb); + + if (fb->dpt_vm) + i915_ggtt_resume_vm(fb->dpt_vm); + } + mutex_unlock(&i915->drm.mode_config.fb_lock); +} + +/** + * intel_dpt_suspend - suspend the memory mapping for all DPT FBs during system suspend + * @i915: device instance + * + * Suspend the memory mapping during system suspend for all framebuffers which + * are mapped to HW via a GGTT->DPT page table. + * + * This function must be called before the mappings in GGTT are suspended calling + * i915_ggtt_suspend(). + */ +void intel_dpt_suspend(struct drm_i915_private *i915) +{ + struct drm_framebuffer *drm_fb; + + mutex_lock(&i915->drm.mode_config.fb_lock); + + drm_for_each_fb(drm_fb, &i915->drm) { + struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb); + + if (fb->dpt_vm) + i915_ggtt_suspend_vm(fb->dpt_vm); + } + + mutex_unlock(&i915->drm.mode_config.fb_lock); +} + struct i915_address_space * intel_dpt_create(struct intel_framebuffer *fb) { diff --git a/drivers/gpu/drm/i915/display/intel_dpt.h b/drivers/gpu/drm/i915/display/intel_dpt.h index 45142b8f849f6..e18a9f767b112 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.h +++ b/drivers/gpu/drm/i915/display/intel_dpt.h @@ -6,6 +6,8 @@ #ifndef __INTEL_DPT_H__ #define __INTEL_DPT_H__ +struct drm_i915_private; + struct i915_address_space; struct i915_vma; struct intel_framebuffer; @@ -13,6 +15,8 @@ struct intel_framebuffer; void intel_dpt_destroy(struct i915_address_space *vm); struct i915_vma *intel_dpt_pin(struct i915_address_space *vm); void intel_dpt_unpin(struct i915_address_space *vm); +void intel_dpt_suspend(struct drm_i915_private *i915); +void intel_dpt_resume(struct drm_i915_private *i915); struct i915_address_space * intel_dpt_create(struct intel_framebuffer *fb); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1e5b75ae99329..4a054aa1860b0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -51,6 +51,7 @@ #include "display/intel_dmc.h" #include "display/intel_display_types.h" #include "display/intel_dp.h" +#include "display/intel_dpt.h" #include "display/intel_fbdev.h" #include "display/intel_hotplug.h" #include "display/intel_overlay.h" @@ -1128,6 +1129,8 @@ static int i915_drm_suspend(struct drm_device *dev) intel_suspend_hw(dev_priv); + /* Must be called before GGTT is suspended. */ + intel_dpt_suspend(dev_priv); i915_ggtt_suspend(&dev_priv->ggtt); i915_save_display(dev_priv); @@ -1244,6 +1247,8 @@ static int i915_drm_resume(struct drm_device *dev) drm_err(&dev_priv->drm, "failed to re-enable GGTT\n"); i915_ggtt_resume(&dev_priv->ggtt); + /* Must be called after GGTT is resumed. */ + intel_dpt_resume(dev_priv); intel_dmc_ucode_resume(dev_priv); From 565edeee70db754e2e337ccd941f2dc10d276691 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 3 Nov 2021 13:28:05 +0100 Subject: [PATCH 083/176] drm/i915: Fix comment about modeset parameters The comment mentions that the KMS is enabled by default unless either the i915.modeset module parameter or vga_text_mode_force boot option are used. But the latter does not exist and instead the nomodeset option was meant. Signed-off-by: Javier Martinez Canillas Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211103122809.1040754-2-javierm@redhat.com --- drivers/gpu/drm/i915/i915_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_module.c b/drivers/gpu/drm/i915/i915_module.c index ab2295dd45001..c7507266aa832 100644 --- a/drivers/gpu/drm/i915/i915_module.c +++ b/drivers/gpu/drm/i915/i915_module.c @@ -24,8 +24,8 @@ static int i915_check_nomodeset(void) /* * Enable KMS by default, unless explicitly overriden by - * either the i915.modeset prarameter or by the - * vga_text_mode_force boot option. + * either the i915.modeset parameter or by the + * nomodeset boot option. */ if (i915_modparams.modeset == 0) From f20ca899a7c9e7ba48a5daec778607572fca5f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:28 +0300 Subject: [PATCH 084/176] drm/i915: Stop using group access when progrmming icl combo phy TX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Program each TX lane individually so that we can start to use per-lane drive settings. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-8-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 5ef2882727e19..327c5db167565 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1069,14 +1069,16 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val); /* Program PORT_TX_DW2 */ - val = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(0, phy)); - val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | - RCOMP_SCALAR_MASK); - val |= SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel); - val |= SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel); - /* Program Rcomp scalar for every table entry */ - val |= RCOMP_SCALAR(0x98); - intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), val); + for (ln = 0; ln < 4; ln++) { + val = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy)); + val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | + RCOMP_SCALAR_MASK); + val |= SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel); + val |= SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel); + /* Program Rcomp scalar for every table entry */ + val |= RCOMP_SCALAR(0x98); + intel_de_write(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy), val); + } /* Program PORT_TX_DW4 */ /* We cannot write to GRP. It would overwrite individual loadgen. */ @@ -1091,10 +1093,12 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, } /* Program PORT_TX_DW7 */ - val = intel_de_read(dev_priv, ICL_PORT_TX_DW7_LN(0, phy)); - val &= ~N_SCALAR_MASK; - val |= N_SCALAR(trans->entries[level].icl.dw7_n_scalar); - intel_de_write(dev_priv, ICL_PORT_TX_DW7_GRP(phy), val); + for (ln = 0; ln < 4; ln++) { + val = intel_de_read(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy)); + val &= ~N_SCALAR_MASK; + val |= N_SCALAR(trans->entries[level].icl.dw7_n_scalar); + intel_de_write(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy), val); + } } static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder, From 31e914a2307a29dfde8027cffa70292341bd379d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:29 +0300 Subject: [PATCH 085/176] drm/i915: Query the vswing levels per-lane for icl combo phy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare for per-lane drive settings by querying the desired vswing level per-lane. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-9-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 327c5db167565..6617e8172a747 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1040,7 +1040,6 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - int level = intel_ddi_level(encoder, crtc_state, 0); const struct intel_ddi_buf_trans *trans; enum phy phy = intel_port_to_phy(dev_priv, encoder->port); int n_entries, ln; @@ -1070,6 +1069,8 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, /* Program PORT_TX_DW2 */ for (ln = 0; ln < 4; ln++) { + int level = intel_ddi_level(encoder, crtc_state, ln); + val = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy)); val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | RCOMP_SCALAR_MASK); @@ -1083,6 +1084,8 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, /* Program PORT_TX_DW4 */ /* We cannot write to GRP. It would overwrite individual loadgen. */ for (ln = 0; ln < 4; ln++) { + int level = intel_ddi_level(encoder, crtc_state, ln); + val = intel_de_read(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy)); val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK); @@ -1094,6 +1097,8 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, /* Program PORT_TX_DW7 */ for (ln = 0; ln < 4; ln++) { + int level = intel_ddi_level(encoder, crtc_state, ln); + val = intel_de_read(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy)); val &= ~N_SCALAR_MASK; val |= N_SCALAR(trans->entries[level].icl.dw7_n_scalar); From 305448e55745dd4634272794c8c01edc872bcf63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:30 +0300 Subject: [PATCH 086/176] drm/i915: Query the vswing levels per-lane for icl mg phy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare for per-lane drive settings by querying the desired vswing level per-lane. Note that the code only does two loops, with each one writing the levels for two TX lanes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-10-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 6617e8172a747..97dd01b1026bf 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1164,7 +1164,6 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); - int level = intel_ddi_level(encoder, crtc_state, 0); const struct intel_ddi_buf_trans *trans; int n_entries, ln; u32 val; @@ -1189,12 +1188,18 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, /* Program MG_TX_SWINGCTRL with values from vswing table */ for (ln = 0; ln < 2; ln++) { + int level; + + level = intel_ddi_level(encoder, crtc_state, 2*ln+0); + val = intel_de_read(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port)); val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK; val |= CRI_TXDEEMPH_OVERRIDE_17_12( trans->entries[level].mg.cri_txdeemph_override_17_12); intel_de_write(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port), val); + level = intel_ddi_level(encoder, crtc_state, 2*ln+1); + val = intel_de_read(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port)); val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK; val |= CRI_TXDEEMPH_OVERRIDE_17_12( @@ -1204,6 +1209,10 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, /* Program MG_TX_DRVCTRL with values from vswing table */ for (ln = 0; ln < 2; ln++) { + int level; + + level = intel_ddi_level(encoder, crtc_state, 2*ln+0); + val = intel_de_read(dev_priv, MG_TX1_DRVCTRL(ln, tc_port)); val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK | CRI_TXDEEMPH_OVERRIDE_5_0_MASK); @@ -1214,6 +1223,8 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, CRI_TXDEEMPH_OVERRIDE_EN; intel_de_write(dev_priv, MG_TX1_DRVCTRL(ln, tc_port), val); + level = intel_ddi_level(encoder, crtc_state, 2*ln+1); + val = intel_de_read(dev_priv, MG_TX2_DRVCTRL(ln, tc_port)); val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK | CRI_TXDEEMPH_OVERRIDE_5_0_MASK); From a905ced613095c1ca406c179b2f0d44219d82381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:31 +0300 Subject: [PATCH 087/176] drm/i915: Query the vswing levels per-lane for tgl dkl phy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare for per-lane drive settings by querying the desired vswing level per-lane. Note that the code only does two loops, with each one writing the levels for two TX lanes. The register offsets also look a bit funny because each time through the loop we write to the exact same register offsets. The crucial bit is the HIP_INDEX_REG write that steers the same mmio window into different places. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-11-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 33 ++++++++++++++---------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 97dd01b1026bf..900be76b8f75e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1296,9 +1296,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); - int level = intel_ddi_level(encoder, crtc_state, 0); const struct intel_ddi_buf_trans *trans; - u32 val, dpcnt_mask, dpcnt_val; int n_entries, ln; if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) @@ -1308,28 +1306,35 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans)) return; - dpcnt_mask = (DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK); - dpcnt_val = DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing); - dpcnt_val |= DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis); - dpcnt_val |= DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot); - for (ln = 0; ln < 2; ln++) { + int level; + u32 val; + intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, ln)); intel_de_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), 0); - /* All the registers are RMW */ + level = intel_ddi_level(encoder, crtc_state, 2*ln+0); + val = intel_de_read(dev_priv, DKL_TX_DPCNTL0(tc_port)); - val &= ~dpcnt_mask; - val |= dpcnt_val; + val &= ~(DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK); + val |= DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot); intel_de_write(dev_priv, DKL_TX_DPCNTL0(tc_port), val); + level = intel_ddi_level(encoder, crtc_state, 2*ln+1); + val = intel_de_read(dev_priv, DKL_TX_DPCNTL1(tc_port)); - val &= ~dpcnt_mask; - val |= dpcnt_val; + val &= ~(DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK); + val |= DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot); intel_de_write(dev_priv, DKL_TX_DPCNTL1(tc_port), val); val = intel_de_read(dev_priv, DKL_TX_DPCNTL2(tc_port)); From 3e9cf8f055fcb42776156fa5f5eb9a5326f160c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:32 +0300 Subject: [PATCH 088/176] drm/i915: Query the vswing levels per-lane for snps phy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare for per-lane drive settings by querying the desired vswing level per-lane. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-12-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_snps_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 5e20f340730fb..c2251218a39e0 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -58,7 +58,6 @@ void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); const struct intel_ddi_buf_trans *trans; enum phy phy = intel_port_to_phy(dev_priv, encoder->port); - int level = intel_ddi_level(encoder, crtc_state, 0); int n_entries, ln; trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); @@ -66,6 +65,7 @@ void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, return; for (ln = 0; ln < 4; ln++) { + int level = intel_ddi_level(encoder, crtc_state, ln); u32 val = 0; val |= REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, trans->entries[level].snps.vswing); From 88a24415220990d41834838d54ba028399649ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:33 +0300 Subject: [PATCH 089/176] drm/i915: Enable per-lane drive settings for icl+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the link buf_trans, link training, and the combo/mg/dkl/snps phy programming are all fixed up we can allow per-lane DP drive settings on icl+. Make it so. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-13-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index a72f2dc937182..e264467de8ed1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -301,7 +301,10 @@ static u8 intel_dp_phy_preemph_max(struct intel_dp *intel_dp, static bool has_per_lane_signal_levels(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy) { - return !intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + return !intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy) || + DISPLAY_VER(i915) >= 11; } /* 128b/132b */ From c86e187372da0967a82994fef7cecd4806cd2baa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:34 +0300 Subject: [PATCH 090/176] drm/i915: Use intel_de_rmw() for tgl dkl phy programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamline the code by using intel_de_rmw(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-14-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 38 +++++++++++------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 900be76b8f75e..0fed8bd51909e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1308,7 +1308,6 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, for (ln = 0; ln < 2; ln++) { int level; - u32 val; intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, ln)); @@ -1317,29 +1316,26 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, level = intel_ddi_level(encoder, crtc_state, 2*ln+0); - val = intel_de_read(dev_priv, DKL_TX_DPCNTL0(tc_port)); - val &= ~(DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK); - val |= DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing) | - DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | - DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot); - intel_de_write(dev_priv, DKL_TX_DPCNTL0(tc_port), val); + intel_de_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), + DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK, + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); level = intel_ddi_level(encoder, crtc_state, 2*ln+1); - val = intel_de_read(dev_priv, DKL_TX_DPCNTL1(tc_port)); - val &= ~(DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK); - val |= DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing) | - DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | - DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot); - intel_de_write(dev_priv, DKL_TX_DPCNTL1(tc_port), val); - - val = intel_de_read(dev_priv, DKL_TX_DPCNTL2(tc_port)); - val &= ~DKL_TX_DP20BITMODE; - intel_de_write(dev_priv, DKL_TX_DPCNTL2(tc_port), val); + intel_de_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), + DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK, + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); + + intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), + DKL_TX_DP20BITMODE, 0); } } From d4e0f16325026eb001c48a6a619886048286cc42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:35 +0300 Subject: [PATCH 091/176] drm/i915: Use intel_de_rmw() for icl mg phy programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamline the code by using intel_de_rmw(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-15-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 115 +++++++++-------------- 1 file changed, 42 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0fed8bd51909e..8e9caae2b0a0a 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1166,7 +1166,6 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); const struct intel_ddi_buf_trans *trans; int n_entries, ln; - u32 val; if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) return; @@ -1175,15 +1174,11 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans)) return; - /* Set MG_TX_LINK_PARAMS cri_use_fs32 to 0. */ for (ln = 0; ln < 2; ln++) { - val = intel_de_read(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port)); - val &= ~CRI_USE_FS32; - intel_de_write(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port), val); - - val = intel_de_read(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port)); - val &= ~CRI_USE_FS32; - intel_de_write(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port), + CRI_USE_FS32, 0); + intel_de_rmw(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port), + CRI_USE_FS32, 0); } /* Program MG_TX_SWINGCTRL with values from vswing table */ @@ -1192,19 +1187,15 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, level = intel_ddi_level(encoder, crtc_state, 2*ln+0); - val = intel_de_read(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port)); - val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK; - val |= CRI_TXDEEMPH_OVERRIDE_17_12( - trans->entries[level].mg.cri_txdeemph_override_17_12); - intel_de_write(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port), + CRI_TXDEEMPH_OVERRIDE_17_12_MASK, + CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12)); level = intel_ddi_level(encoder, crtc_state, 2*ln+1); - val = intel_de_read(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port)); - val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK; - val |= CRI_TXDEEMPH_OVERRIDE_17_12( - trans->entries[level].mg.cri_txdeemph_override_17_12); - intel_de_write(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port), + CRI_TXDEEMPH_OVERRIDE_17_12_MASK, + CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12)); } /* Program MG_TX_DRVCTRL with values from vswing table */ @@ -1213,27 +1204,21 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, level = intel_ddi_level(encoder, crtc_state, 2*ln+0); - val = intel_de_read(dev_priv, MG_TX1_DRVCTRL(ln, tc_port)); - val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK | - CRI_TXDEEMPH_OVERRIDE_5_0_MASK); - val |= CRI_TXDEEMPH_OVERRIDE_5_0( - trans->entries[level].mg.cri_txdeemph_override_5_0) | - CRI_TXDEEMPH_OVERRIDE_11_6( - trans->entries[level].mg.cri_txdeemph_override_11_6) | - CRI_TXDEEMPH_OVERRIDE_EN; - intel_de_write(dev_priv, MG_TX1_DRVCTRL(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_TX1_DRVCTRL(ln, tc_port), + CRI_TXDEEMPH_OVERRIDE_11_6_MASK | + CRI_TXDEEMPH_OVERRIDE_5_0_MASK, + CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) | + CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) | + CRI_TXDEEMPH_OVERRIDE_EN); level = intel_ddi_level(encoder, crtc_state, 2*ln+1); - val = intel_de_read(dev_priv, MG_TX2_DRVCTRL(ln, tc_port)); - val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK | - CRI_TXDEEMPH_OVERRIDE_5_0_MASK); - val |= CRI_TXDEEMPH_OVERRIDE_5_0( - trans->entries[level].mg.cri_txdeemph_override_5_0) | - CRI_TXDEEMPH_OVERRIDE_11_6( - trans->entries[level].mg.cri_txdeemph_override_11_6) | - CRI_TXDEEMPH_OVERRIDE_EN; - intel_de_write(dev_priv, MG_TX2_DRVCTRL(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_TX2_DRVCTRL(ln, tc_port), + CRI_TXDEEMPH_OVERRIDE_11_6_MASK | + CRI_TXDEEMPH_OVERRIDE_5_0_MASK, + CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) | + CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) | + CRI_TXDEEMPH_OVERRIDE_EN); /* FIXME: Program CRI_LOADGEN_SEL after the spec is updated */ } @@ -1244,50 +1229,34 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, * values from table for which TX1 and TX2 enabled. */ for (ln = 0; ln < 2; ln++) { - val = intel_de_read(dev_priv, MG_CLKHUB(ln, tc_port)); - if (crtc_state->port_clock < 300000) - val |= CFG_LOW_RATE_LKREN_EN; - else - val &= ~CFG_LOW_RATE_LKREN_EN; - intel_de_write(dev_priv, MG_CLKHUB(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_CLKHUB(ln, tc_port), + CFG_LOW_RATE_LKREN_EN, + crtc_state->port_clock < 300000 ? CFG_LOW_RATE_LKREN_EN : 0); } /* Program the MG_TX_DCC based on the link frequency */ for (ln = 0; ln < 2; ln++) { - val = intel_de_read(dev_priv, MG_TX1_DCC(ln, tc_port)); - val &= ~CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK; - if (crtc_state->port_clock <= 500000) { - val &= ~CFG_AMI_CK_DIV_OVERRIDE_EN; - } else { - val |= CFG_AMI_CK_DIV_OVERRIDE_EN | - CFG_AMI_CK_DIV_OVERRIDE_VAL(1); - } - intel_de_write(dev_priv, MG_TX1_DCC(ln, tc_port), val); - - val = intel_de_read(dev_priv, MG_TX2_DCC(ln, tc_port)); - val &= ~CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK; - if (crtc_state->port_clock <= 500000) { - val &= ~CFG_AMI_CK_DIV_OVERRIDE_EN; - } else { - val |= CFG_AMI_CK_DIV_OVERRIDE_EN | - CFG_AMI_CK_DIV_OVERRIDE_VAL(1); - } - intel_de_write(dev_priv, MG_TX2_DCC(ln, tc_port), val); + intel_de_rmw(dev_priv, MG_TX1_DCC(ln, tc_port), + CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK | + CFG_AMI_CK_DIV_OVERRIDE_EN, + crtc_state->port_clock > 500000 ? + CFG_AMI_CK_DIV_OVERRIDE_VAL(1) | + CFG_AMI_CK_DIV_OVERRIDE_EN : 0); + + intel_de_rmw(dev_priv, MG_TX2_DCC(ln, tc_port), + CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK | + CFG_AMI_CK_DIV_OVERRIDE_EN, + crtc_state->port_clock > 500000 ? + CFG_AMI_CK_DIV_OVERRIDE_VAL(1) | + CFG_AMI_CK_DIV_OVERRIDE_EN : 0); } /* Program MG_TX_PISO_READLOAD with values from vswing table */ for (ln = 0; ln < 2; ln++) { - val = intel_de_read(dev_priv, - MG_TX1_PISO_READLOAD(ln, tc_port)); - val |= CRI_CALCINIT; - intel_de_write(dev_priv, MG_TX1_PISO_READLOAD(ln, tc_port), - val); - - val = intel_de_read(dev_priv, - MG_TX2_PISO_READLOAD(ln, tc_port)); - val |= CRI_CALCINIT; - intel_de_write(dev_priv, MG_TX2_PISO_READLOAD(ln, tc_port), - val); + intel_de_rmw(dev_priv, MG_TX1_PISO_READLOAD(ln, tc_port), + 0, CRI_CALCINIT); + intel_de_rmw(dev_priv, MG_TX2_PISO_READLOAD(ln, tc_port), + 0, CRI_CALCINIT); } } From c1d53cbd83b87bdce318f45d4fa5505c3008389f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 6 Oct 2021 23:49:36 +0300 Subject: [PATCH 092/176] drm/i915: Use intel_de_rmw() for icl combo phy programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamline the code by using intel_de_rmw(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211006204937.30774-16-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 44 ++++++++++-------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 8e9caae2b0a0a..145d51ac43a39 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1071,14 +1071,11 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, for (ln = 0; ln < 4; ln++) { int level = intel_ddi_level(encoder, crtc_state, ln); - val = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy)); - val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | - RCOMP_SCALAR_MASK); - val |= SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel); - val |= SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel); - /* Program Rcomp scalar for every table entry */ - val |= RCOMP_SCALAR(0x98); - intel_de_write(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy), val); + intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy), + SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK | RCOMP_SCALAR_MASK, + SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel) | + SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel) | + RCOMP_SCALAR(0x98)); } /* Program PORT_TX_DW4 */ @@ -1086,23 +1083,20 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, for (ln = 0; ln < 4; ln++) { int level = intel_ddi_level(encoder, crtc_state, ln); - val = intel_de_read(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy)); - val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | - CURSOR_COEFF_MASK); - val |= POST_CURSOR_1(trans->entries[level].icl.dw4_post_cursor_1); - val |= POST_CURSOR_2(trans->entries[level].icl.dw4_post_cursor_2); - val |= CURSOR_COEFF(trans->entries[level].icl.dw4_cursor_coeff); - intel_de_write(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy), val); + intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy), + POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK, + POST_CURSOR_1(trans->entries[level].icl.dw4_post_cursor_1) | + POST_CURSOR_2(trans->entries[level].icl.dw4_post_cursor_2) | + CURSOR_COEFF(trans->entries[level].icl.dw4_cursor_coeff)); } /* Program PORT_TX_DW7 */ for (ln = 0; ln < 4; ln++) { int level = intel_ddi_level(encoder, crtc_state, ln); - val = intel_de_read(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy)); - val &= ~N_SCALAR_MASK; - val |= N_SCALAR(trans->entries[level].icl.dw7_n_scalar); - intel_de_write(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy), val); + intel_de_rmw(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy), + N_SCALAR_MASK, + N_SCALAR(trans->entries[level].icl.dw7_n_scalar)); } } @@ -1134,16 +1128,14 @@ static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder, * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0) */ for (ln = 0; ln < 4; ln++) { - val = intel_de_read(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy)); - val &= ~LOADGEN_SELECT; - val |= icl_combo_phy_loadgen_select(crtc_state, ln); - intel_de_write(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy), val); + intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy), + LOADGEN_SELECT, + icl_combo_phy_loadgen_select(crtc_state, ln)); } /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */ - val = intel_de_read(dev_priv, ICL_PORT_CL_DW5(phy)); - val |= SUS_CLOCK_CONFIG; - intel_de_write(dev_priv, ICL_PORT_CL_DW5(phy), val); + intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy), + 0, SUS_CLOCK_CONFIG); /* 4. Clear training enable to change swing values */ val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy)); From aaec72ee90bcccfffeb33feb8be826efa4065a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:22 +0300 Subject: [PATCH 093/176] drm/i915: Reject planar formats when doing async flips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Async flips are only capable of changing PLANE_SURF, hence we they can't easily be used with planar formats. Older platforms could require updating AUX_DIST as well, which is not possible. We'd have to make sure AUX_DIST doesn't change before allowing the async flip through. If we could get async flips with CCS then that might be interesting, but since the hw doesn't allow async flips with CCS I don't see much point in allowing this for planar formats either. No one renders their game content in YUV anyway. icl+ could in theory do this I suppose since each color plane has its own PLANE_SURF register, but I don't know if there is some magic to guarantee that both the Y and UV plane would async flip synchronously if you will. Ie. beyond just a clean tear we'd potentially get some kind of weird tear with some random mix of luma and chroma from the old and new frames. So let's just say no to async flips when scanning out planar formats. Cc: Karthik B S Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_display.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 29392dfc46c8d..09d19ea01cfcb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7775,6 +7775,12 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int return -EINVAL; } + if (new_plane_state->hw.fb->format->num_planes > 1) { + drm_dbg_kms(&i915->drm, + "Planar formats not supported with async flips\n"); + return -EINVAL; + } + if (old_plane_state->view.color_plane[0].mapping_stride != new_plane_state->view.color_plane[0].mapping_stride) { drm_dbg_kms(&i915->drm, "Stride cannot be changed in async flip\n"); From 50faf7a194b80c2f9a6f919b03036880e6620b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:23 +0300 Subject: [PATCH 094/176] drm/i915: Fix async flip with decryption and/or DPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're currently forgetting to set the PLANE_SURF_DECRYPT flag in the async flip path. So if the hardware were to latch that bit despite this being an async flip we'd start scanning out garbage. And if it doesn't latch it then I guess we'd just end up with a weird register value that doesn't actually match the hardware state, which isn't great for anyone staring at register dumps. Similarly the async flip path also forgets to call skl_surf_address() which means the DPT address space to GGTT address space downshift is not being applied to the offset. Which means we are pointing PLANE_SURF at some random location in GGTT instead of the correct DPT page. So let's fix two birds with one stone and extract the PLANE_SURF calculation from skl_program_plane() into a small helper and use it in the async flip path as well. Cc: Anshuman Gupta Cc: Daniele Ceraolo Spurio Cc: Juston Li Cc: Rodrigo Vivi Cc: Uma Shankar Cc: Karthik B S Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- .../drm/i915/display/skl_universal_plane.c | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 91a79b1582c9e..78da9e3464359 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -967,6 +967,20 @@ static u32 skl_surf_address(const struct intel_plane_state *plane_state, } } +static u32 skl_plane_surf(const struct intel_plane_state *plane_state, + int color_plane) +{ + u32 plane_surf; + + plane_surf = intel_plane_ggtt_offset(plane_state) + + skl_surf_address(plane_state, color_plane); + + if (plane_state->decrypt) + plane_surf |= PLANE_SURF_DECRYPT; + + return plane_surf; +} + static void icl_plane_csc_load_black(struct intel_plane *plane) { struct drm_i915_private *i915 = to_i915(plane->base.dev); @@ -1001,7 +1015,6 @@ skl_program_plane(struct intel_plane *plane, enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; - u32 surf_addr = skl_surf_address(plane_state, color_plane); u32 stride = skl_plane_stride(plane_state, color_plane); const struct drm_framebuffer *fb = plane_state->hw.fb; int aux_plane = skl_main_to_aux_plane(fb, color_plane); @@ -1014,7 +1027,7 @@ skl_program_plane(struct intel_plane *plane, u8 alpha = plane_state->hw.alpha >> 8; u32 plane_color_ctl = 0, aux_dist = 0; unsigned long irqflags; - u32 keymsk, keymax, plane_surf; + u32 keymsk, keymax; u32 plane_ctl = plane_state->ctl; plane_ctl |= skl_plane_ctl_crtc(crtc_state); @@ -1040,16 +1053,13 @@ skl_program_plane(struct intel_plane *plane, } if (aux_plane) { - aux_dist = skl_surf_address(plane_state, aux_plane) - surf_addr; + aux_dist = skl_surf_address(plane_state, aux_plane) - + skl_surf_address(plane_state, color_plane); if (DISPLAY_VER(dev_priv) < 12) aux_dist |= skl_plane_stride(plane_state, aux_plane); } - plane_surf = intel_plane_ggtt_offset(plane_state) + surf_addr; - if (plane_state->decrypt) - plane_surf |= PLANE_SURF_DECRYPT; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); /* @@ -1113,7 +1123,8 @@ skl_program_plane(struct intel_plane *plane, * the control register just before the surface register. */ intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); - intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), plane_surf); + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), + skl_plane_surf(plane_state, color_plane)); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -1128,7 +1139,6 @@ skl_plane_async_flip(struct intel_plane *plane, unsigned long irqflags; enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - u32 surf_addr = plane_state->view.color_plane[0].offset; u32 plane_ctl = plane_state->ctl; plane_ctl |= skl_plane_ctl_crtc(crtc_state); @@ -1140,7 +1150,7 @@ skl_plane_async_flip(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), - intel_plane_ggtt_offset(plane_state) + surf_addr); + skl_plane_surf(plane_state, 0)); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } From e56b80d9fd291481e55c1e7b3483db83ec44b680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:24 +0300 Subject: [PATCH 095/176] drm/i915: Fix up the sprite namespacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give all sprite exclusive functions/etc. a proper namespace. Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-4-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_sprite.c | 106 ++++++++++---------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 1d710b3e51ee7..79c57be9958d6 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -119,7 +119,7 @@ static void i9xx_plane_linear_gamma(u16 gamma[8]) } static void -chv_update_csc(const struct intel_plane_state *plane_state) +chv_sprite_update_csc(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); @@ -191,7 +191,7 @@ chv_update_csc(const struct intel_plane_state *plane_state) #define COS_0 1 static void -vlv_update_clrc(const struct intel_plane_state *plane_state) +vlv_sprite_update_clrc(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); @@ -394,7 +394,7 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, return sprctl; } -static void vlv_update_gamma(const struct intel_plane_state *plane_state) +static void vlv_sprite_update_gamma(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); @@ -418,9 +418,9 @@ static void vlv_update_gamma(const struct intel_plane_state *plane_state) } static void -vlv_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +vlv_sprite_update(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -456,7 +456,7 @@ vlv_update_plane(struct intel_plane *plane, intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0); if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) - chv_update_csc(plane_state); + chv_sprite_update_csc(plane_state); if (key->flags) { intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id), @@ -479,15 +479,15 @@ vlv_update_plane(struct intel_plane *plane, intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), intel_plane_ggtt_offset(plane_state) + sprsurf_offset); - vlv_update_clrc(plane_state); - vlv_update_gamma(plane_state); + vlv_sprite_update_clrc(plane_state); + vlv_sprite_update_gamma(plane_state); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void -vlv_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +vlv_sprite_disable(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -503,8 +503,8 @@ vlv_disable_plane(struct intel_plane *plane, } static bool -vlv_plane_get_hw_state(struct intel_plane *plane, - enum pipe *pipe) +vlv_sprite_get_hw_state(struct intel_plane *plane, + enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; @@ -806,7 +806,7 @@ static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state, i++; } -static void ivb_update_gamma(const struct intel_plane_state *plane_state) +static void ivb_sprite_update_gamma(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); @@ -836,9 +836,9 @@ static void ivb_update_gamma(const struct intel_plane_state *plane_state) } static void -ivb_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +ivb_sprite_update(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -903,14 +903,14 @@ ivb_update_plane(struct intel_plane *plane, intel_de_write_fw(dev_priv, SPRSURF(pipe), intel_plane_ggtt_offset(plane_state) + sprsurf_offset); - ivb_update_gamma(plane_state); + ivb_sprite_update_gamma(plane_state); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void -ivb_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +ivb_sprite_disable(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -928,8 +928,8 @@ ivb_disable_plane(struct intel_plane *plane, } static bool -ivb_plane_get_hw_state(struct intel_plane *plane, - enum pipe *pipe) +ivb_sprite_get_hw_state(struct intel_plane *plane, + enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; @@ -1107,7 +1107,7 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, return dvscntr; } -static void g4x_update_gamma(const struct intel_plane_state *plane_state) +static void g4x_sprite_update_gamma(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); @@ -1137,7 +1137,7 @@ static void ilk_sprite_linear_gamma(u16 gamma[17]) gamma[i] = (i << 10) / 16; } -static void ilk_update_gamma(const struct intel_plane_state *plane_state) +static void ilk_sprite_update_gamma(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); @@ -1164,9 +1164,9 @@ static void ilk_update_gamma(const struct intel_plane_state *plane_state) } static void -g4x_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +g4x_sprite_update(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -1225,16 +1225,16 @@ g4x_update_plane(struct intel_plane *plane, intel_plane_ggtt_offset(plane_state) + dvssurf_offset); if (IS_G4X(dev_priv)) - g4x_update_gamma(plane_state); + g4x_sprite_update_gamma(plane_state); else - ilk_update_gamma(plane_state); + ilk_sprite_update_gamma(plane_state); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void -g4x_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +g4x_sprite_disable(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -1251,8 +1251,8 @@ g4x_disable_plane(struct intel_plane *plane, } static bool -g4x_plane_get_hw_state(struct intel_plane *plane, - enum pipe *pipe) +g4x_sprite_get_hw_state(struct intel_plane *plane, + enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; @@ -1568,7 +1568,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, return ret; } -static const u32 g4x_plane_formats[] = { +static const u32 g4x_sprite_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_YUYV, DRM_FORMAT_YVYU, @@ -1576,7 +1576,7 @@ static const u32 g4x_plane_formats[] = { DRM_FORMAT_VYUY, }; -static const u32 snb_plane_formats[] = { +static const u32 snb_sprite_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB2101010, @@ -1589,7 +1589,7 @@ static const u32 snb_plane_formats[] = { DRM_FORMAT_VYUY, }; -static const u32 vlv_plane_formats[] = { +static const u32 vlv_sprite_formats[] = { DRM_FORMAT_C8, DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, @@ -1742,9 +1742,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, return plane; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - plane->update_plane = vlv_update_plane; - plane->disable_plane = vlv_disable_plane; - plane->get_hw_state = vlv_plane_get_hw_state; + plane->update_plane = vlv_sprite_update; + plane->disable_plane = vlv_sprite_disable; + plane->get_hw_state = vlv_sprite_get_hw_state; plane->check_plane = vlv_sprite_check; plane->max_stride = i965_plane_max_stride; plane->min_cdclk = vlv_plane_min_cdclk; @@ -1753,15 +1753,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, formats = chv_pipe_b_sprite_formats; num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats); } else { - formats = vlv_plane_formats; - num_formats = ARRAY_SIZE(vlv_plane_formats); + formats = vlv_sprite_formats; + num_formats = ARRAY_SIZE(vlv_sprite_formats); } plane_funcs = &vlv_sprite_funcs; } else if (DISPLAY_VER(dev_priv) >= 7) { - plane->update_plane = ivb_update_plane; - plane->disable_plane = ivb_disable_plane; - plane->get_hw_state = ivb_plane_get_hw_state; + plane->update_plane = ivb_sprite_update; + plane->disable_plane = ivb_sprite_disable; + plane->get_hw_state = ivb_sprite_get_hw_state; plane->check_plane = g4x_sprite_check; if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { @@ -1772,26 +1772,26 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->min_cdclk = ivb_sprite_min_cdclk; } - formats = snb_plane_formats; - num_formats = ARRAY_SIZE(snb_plane_formats); + formats = snb_sprite_formats; + num_formats = ARRAY_SIZE(snb_sprite_formats); plane_funcs = &snb_sprite_funcs; } else { - plane->update_plane = g4x_update_plane; - plane->disable_plane = g4x_disable_plane; - plane->get_hw_state = g4x_plane_get_hw_state; + plane->update_plane = g4x_sprite_update; + plane->disable_plane = g4x_sprite_disable; + plane->get_hw_state = g4x_sprite_get_hw_state; plane->check_plane = g4x_sprite_check; plane->max_stride = g4x_sprite_max_stride; plane->min_cdclk = g4x_sprite_min_cdclk; if (IS_SANDYBRIDGE(dev_priv)) { - formats = snb_plane_formats; - num_formats = ARRAY_SIZE(snb_plane_formats); + formats = snb_sprite_formats; + num_formats = ARRAY_SIZE(snb_sprite_formats); plane_funcs = &snb_sprite_funcs; } else { - formats = g4x_plane_formats; - num_formats = ARRAY_SIZE(g4x_plane_formats); + formats = g4x_sprite_formats; + num_formats = ARRAY_SIZE(g4x_sprite_formats); plane_funcs = &g4x_sprite_funcs; } From 8ac80733cf6f08b9fdac9bf6800dd81e9304b4c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:25 +0300 Subject: [PATCH 096/176] drm/i915: Split update_plane() into update_noarm() + update_arm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The amount of plane registers we have to write has been steadily increasing, putting more pressure on the vblank evasion mechanism and forcing us to increase its time budget. Let's try to take some of the pressure off by splitting plane updates into two parts: 1) write all non-self arming plane registers, ie. the registers where the write actually does nothing until a separate arming register is also written which will cause the hardware to latch the new register values at the next start of vblank 2) write all self arming plane registers, ie. registers which always just latch at the next start of vblank, and registers which also arm other registers to do so Here we just provide the mechanism, but don't actually implement the split on any platform yet. so everything stays now in the _arm() hooks. Subsequently we can move a whole bunch of stuff into the _noarm() part, especially in more modern platforms where the number of registers we have to write is also the greatest. On older platforms this is less beneficial probably, but no real reason to deviate from a common behaviour. And let's sprinkle some TODOs around the areas that will need adapting. Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/i9xx_plane.c | 15 ++-- .../gpu/drm/i915/display/intel_atomic_plane.c | 88 ++++++++++++++----- .../gpu/drm/i915/display/intel_atomic_plane.h | 23 +++-- drivers/gpu/drm/i915/display/intel_cursor.c | 44 +++++----- drivers/gpu/drm/i915/display/intel_display.c | 12 +-- .../drm/i915/display/intel_display_types.h | 12 ++- drivers/gpu/drm/i915/display/intel_sprite.c | 44 +++++----- .../drm/i915/display/skl_universal_plane.c | 15 ++-- drivers/gpu/drm/i915/i915_trace.h | 33 ++++++- 9 files changed, 192 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index c8722771aa406..d8e8a57e2cc04 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -402,9 +402,10 @@ static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state, return DIV_ROUND_UP(pixel_rate * num, den); } -static void i9xx_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +/* TODO: split into noarm+arm pair */ +static void i9xx_plane_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; @@ -477,8 +478,8 @@ static void i9xx_update_plane(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static void i9xx_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +static void i9xx_plane_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; @@ -836,8 +837,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->max_stride = ilk_primary_max_stride; } - plane->update_plane = i9xx_update_plane; - plane->disable_plane = i9xx_disable_plane; + plane->update_arm = i9xx_plane_update_arm; + plane->disable_arm = i9xx_plane_disable_arm; plane->get_hw_state = i9xx_plane_get_hw_state; plane->check_plane = i9xx_plane_check; diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index f61a48e1a562b..089fb4658b216 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -470,31 +470,72 @@ skl_next_plane_to_commit(struct intel_atomic_state *state, return NULL; } -void intel_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +void intel_plane_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - trace_intel_update_plane(&plane->base, crtc); + trace_intel_plane_update_noarm(&plane->base, crtc); + + if (plane->update_noarm) + plane->update_noarm(plane, crtc_state, plane_state); +} + +void intel_plane_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + trace_intel_plane_update_arm(&plane->base, crtc); if (crtc_state->uapi.async_flip && plane->async_flip) plane->async_flip(plane, crtc_state, plane_state, true); else - plane->update_plane(plane, crtc_state, plane_state); + plane->update_arm(plane, crtc_state, plane_state); } -void intel_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +void intel_plane_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - trace_intel_disable_plane(&plane->base, crtc); - plane->disable_plane(plane, crtc_state); + trace_intel_plane_disable_arm(&plane->base, crtc); + plane->disable_arm(plane, crtc_state); } -void skl_update_planes_on_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_update_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + u32 update_mask = new_crtc_state->update_planes; + struct intel_plane_state *new_plane_state; + struct intel_plane *plane; + int i; + + if (new_crtc_state->uapi.async_flip) + return; + + /* + * Since we only write non-arming registers here, + * the order does not matter even for skl+. + */ + for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) { + if (crtc->pipe != plane->pipe || + !(update_mask & BIT(plane->id))) + continue; + + /* TODO: for mailbox updates this should be skipped */ + if (new_plane_state->uapi.visible || + new_plane_state->planar_slave) + intel_plane_update_noarm(plane, new_crtc_state, new_plane_state); + } +} + +void skl_arm_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); @@ -516,17 +557,20 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); + /* + * TODO: for mailbox updates intel_plane_update_noarm() + * would have to be called here as well. + */ if (new_plane_state->uapi.visible || - new_plane_state->planar_slave) { - intel_update_plane(plane, new_crtc_state, new_plane_state); - } else { - intel_disable_plane(plane, new_crtc_state); - } + new_plane_state->planar_slave) + intel_plane_update_arm(plane, new_crtc_state, new_plane_state); + else + intel_plane_disable_arm(plane, new_crtc_state); } } -void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void i9xx_arm_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -540,10 +584,14 @@ void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, !(update_mask & BIT(plane->id))) continue; + /* + * TODO: for mailbox updates intel_plane_update_noarm() + * would have to be called here as well. + */ if (new_plane_state->uapi.visible) - intel_update_plane(plane, new_crtc_state, new_plane_state); + intel_plane_update_arm(plane, new_crtc_state, new_plane_state); else - intel_disable_plane(plane, new_crtc_state); + intel_plane_disable_arm(plane, new_crtc_state); } } diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 62e5a2a77fd40..7907f601598e5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -30,20 +30,25 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, struct intel_crtc *crtc); void intel_plane_copy_hw_state(struct intel_plane_state *plane_state, const struct intel_plane_state *from_plane_state); -void intel_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state); -void intel_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); +void intel_plane_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); +void intel_plane_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); +void intel_plane_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state); struct intel_plane *intel_plane_alloc(void); void intel_plane_free(struct intel_plane *plane); struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane); void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); -void skl_update_planes_on_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc); -void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc); +void intel_update_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void skl_arm_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void i9xx_arm_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc); int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *crtc_state, const struct intel_plane_state *old_plane_state, diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index e069a3fb8b995..16d34685d83f7 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -248,9 +248,10 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state, return 0; } -static void i845_update_cursor(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +/* TODO: split into noarm+arm pair */ +static void i845_cursor_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); u32 cntl = 0, base = 0, pos = 0, size = 0; @@ -293,10 +294,10 @@ static void i845_update_cursor(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static void i845_disable_cursor(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +static void i845_cursor_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { - i845_update_cursor(plane, crtc_state, NULL); + i845_cursor_update_arm(plane, crtc_state, NULL); } static bool i845_cursor_get_hw_state(struct intel_plane *plane, @@ -483,9 +484,10 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, return 0; } -static void i9xx_update_cursor(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +/* TODO: split into noarm+arm pair */ +static void i9xx_cursor_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -557,10 +559,10 @@ static void i9xx_update_cursor(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static void i9xx_disable_cursor(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +static void i9xx_cursor_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { - i9xx_update_cursor(plane, crtc_state, NULL); + i9xx_cursor_update_arm(plane, crtc_state, NULL); } static bool i9xx_cursor_get_hw_state(struct intel_plane *plane, @@ -714,10 +716,12 @@ intel_legacy_cursor_update(struct drm_plane *_plane, */ crtc_state->active_planes = new_crtc_state->active_planes; - if (new_plane_state->uapi.visible) - intel_update_plane(plane, crtc_state, new_plane_state); - else - intel_disable_plane(plane, crtc_state); + if (new_plane_state->uapi.visible) { + intel_plane_update_noarm(plane, crtc_state, new_plane_state); + intel_plane_update_arm(plane, crtc_state, new_plane_state); + } else { + intel_plane_disable_arm(plane, crtc_state); + } intel_plane_unpin_fb(old_plane_state); @@ -764,14 +768,14 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) { cursor->max_stride = i845_cursor_max_stride; - cursor->update_plane = i845_update_cursor; - cursor->disable_plane = i845_disable_cursor; + cursor->update_arm = i845_cursor_update_arm; + cursor->disable_arm = i845_cursor_disable_arm; cursor->get_hw_state = i845_cursor_get_hw_state; cursor->check_plane = i845_check_cursor; } else { cursor->max_stride = i9xx_cursor_max_stride; - cursor->update_plane = i9xx_update_cursor; - cursor->disable_plane = i9xx_disable_cursor; + cursor->update_arm = i9xx_cursor_update_arm; + cursor->disable_arm = i9xx_cursor_disable_arm; cursor->get_hw_state = i9xx_cursor_get_hw_state; cursor->check_plane = i9xx_check_cursor; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 09d19ea01cfcb..e9c29d4bb70ab 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -781,7 +781,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) == 2 && !crtc_state->active_planes) intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); - intel_disable_plane(plane, crtc_state); + intel_plane_disable_arm(plane, crtc_state); intel_wait_for_vblank(dev_priv, crtc->pipe); } @@ -1563,7 +1563,7 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state, !(update_mask & BIT(plane->id))) continue; - intel_disable_plane(plane, new_crtc_state); + intel_plane_disable_arm(plane, new_crtc_state); if (old_plane_state->uapi.visible) fb_bits |= plane->frontbuffer_bit; @@ -1808,7 +1808,7 @@ static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_stat struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_plane *plane = to_intel_plane(crtc->base.primary); - plane->disable_plane(plane, crtc_state); + plane->disable_arm(plane, crtc_state); } static void ilk_crtc_enable(struct intel_atomic_state *state, @@ -8278,15 +8278,17 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_fbc_update(state, crtc); + intel_update_planes_on_crtc(state, crtc); + /* Perform vblank evasion around commit operation */ intel_pipe_update_start(new_crtc_state); commit_pipe_pre_planes(state, crtc); if (DISPLAY_VER(dev_priv) >= 9) - skl_update_planes_on_crtc(state, crtc); + skl_arm_planes_on_crtc(state, crtc); else - i9xx_update_planes_on_crtc(state, crtc); + i9xx_arm_planes_on_crtc(state, crtc); commit_pipe_post_planes(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index a174b0b83640b..e4c3754501381 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1357,11 +1357,17 @@ struct intel_plane { unsigned int (*max_stride)(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); - void (*update_plane)(struct intel_plane *plane, + /* Write all non-self arming plane registers */ + void (*update_noarm)(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); - void (*disable_plane)(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); + /* Write all self-arming plane registers */ + void (*update_arm)(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); + /* Disable the plane, must arm */ + void (*disable_arm)(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state); bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe); int (*check_plane)(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 79c57be9958d6..fb249966e5dd8 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -417,10 +417,11 @@ static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state) gamma[i] << 16 | gamma[i] << 8 | gamma[i]); } +/* TODO: split into noarm+arm pair */ static void -vlv_sprite_update(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +vlv_sprite_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -486,8 +487,8 @@ vlv_sprite_update(struct intel_plane *plane, } static void -vlv_sprite_disable(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +vlv_sprite_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -835,10 +836,11 @@ static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state) i++; } +/* TODO: split into noarm+arm pair */ static void -ivb_sprite_update(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +ivb_sprite_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -909,8 +911,8 @@ ivb_sprite_update(struct intel_plane *plane, } static void -ivb_sprite_disable(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +ivb_sprite_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -1164,9 +1166,9 @@ static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state) } static void -g4x_sprite_update(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +g4x_sprite_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -1233,8 +1235,8 @@ g4x_sprite_update(struct intel_plane *plane, } static void -g4x_sprite_disable(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +g4x_sprite_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; @@ -1742,8 +1744,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, return plane; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - plane->update_plane = vlv_sprite_update; - plane->disable_plane = vlv_sprite_disable; + plane->update_arm = vlv_sprite_update_arm; + plane->disable_arm = vlv_sprite_disable_arm; plane->get_hw_state = vlv_sprite_get_hw_state; plane->check_plane = vlv_sprite_check; plane->max_stride = i965_plane_max_stride; @@ -1759,8 +1761,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &vlv_sprite_funcs; } else if (DISPLAY_VER(dev_priv) >= 7) { - plane->update_plane = ivb_sprite_update; - plane->disable_plane = ivb_sprite_disable; + plane->update_arm = ivb_sprite_update_arm; + plane->disable_arm = ivb_sprite_disable_arm; plane->get_hw_state = ivb_sprite_get_hw_state; plane->check_plane = g4x_sprite_check; @@ -1777,8 +1779,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &snb_sprite_funcs; } else { - plane->update_plane = g4x_sprite_update; - plane->disable_plane = g4x_sprite_disable; + plane->update_arm = g4x_sprite_update_arm; + plane->disable_arm = g4x_sprite_disable_arm; plane->get_hw_state = g4x_sprite_get_hw_state; plane->check_plane = g4x_sprite_check; plane->max_stride = g4x_sprite_max_stride; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 78da9e3464359..83ee686772ecd 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -598,8 +598,8 @@ static u32 skl_plane_stride(const struct intel_plane_state *plane_state, } static void -skl_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) +skl_plane_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; @@ -1155,10 +1155,11 @@ skl_plane_async_flip(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +/* TODO: split into noarm+arm pair */ static void -skl_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +skl_plane_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { int color_plane = 0; @@ -2093,8 +2094,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, } plane->max_stride = skl_plane_max_stride; - plane->update_plane = skl_update_plane; - plane->disable_plane = skl_disable_plane; + plane->update_arm = skl_plane_update_arm; + plane->disable_arm = skl_plane_disable_arm; plane->get_hw_state = skl_plane_get_hw_state; plane->check_plane = skl_plane_check; diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 9795f456cccfc..214696d6b270f 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -288,7 +288,7 @@ TRACE_EVENT(vlv_fifo_size, /* plane updates */ -TRACE_EVENT(intel_update_plane, +TRACE_EVENT(intel_plane_update_noarm, TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc), TP_ARGS(plane, crtc), @@ -317,7 +317,36 @@ TRACE_EVENT(intel_update_plane, DRM_RECT_ARG((const struct drm_rect *)__entry->dst)) ); -TRACE_EVENT(intel_disable_plane, +TRACE_EVENT(intel_plane_update_arm, + TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc), + TP_ARGS(plane, crtc), + + TP_STRUCT__entry( + __field(enum pipe, pipe) + __field(u32, frame) + __field(u32, scanline) + __array(int, src, 4) + __array(int, dst, 4) + __string(name, plane->name) + ), + + TP_fast_assign( + __assign_str(name, plane->name); + __entry->pipe = crtc->pipe; + __entry->frame = intel_crtc_get_vblank_counter(crtc); + __entry->scanline = intel_get_crtc_scanline(crtc); + memcpy(__entry->src, &plane->state->src, sizeof(__entry->src)); + memcpy(__entry->dst, &plane->state->dst, sizeof(__entry->dst)); + ), + + TP_printk("pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, + pipe_name(__entry->pipe), __get_str(name), + __entry->frame, __entry->scanline, + DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src), + DRM_RECT_ARG((const struct drm_rect *)__entry->dst)) +); + +TRACE_EVENT(intel_plane_disable_arm, TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc), TP_ARGS(plane, crtc), From 890b6ec4a522799d36bd10aee993059d771c06f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:26 +0300 Subject: [PATCH 097/176] drm/i915: Split skl+ plane update into noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chop skl_program_plane() into two halves. Fist half becomes the _noarm() variant, second part the _arm() variant. Fortunately I have already previously grouped the register writes into roughtly the correct order, so the split looks surprisingly clean. A few notable oddities I did not realize were self arming are AUX_DIST and COLOR_CTL. i915_update_info doesn't look too terrible on my cfl running kms_atomic_transition --r plane-all-transition --extended: w/o patch w/ patch Updates: 2178 Updates: 2018 | | 1us | 1us | | | 4us | 4us |***** |********* |********** 16us |********** 16us |******* |*** | 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 8332ns Min update: 6164ns Max update: 48758ns Max update: 31808ns Average update: 19959ns Average update: 13159ns Overruns > 100us: 0 Overruns > 100us: 0 And with lockdep enabled: w/o patch w/ patch Updates: 2177 Updates: 2172 | | 1us | 1us | | | 4us | 4us | |******* |********* 16us |********** 16us |********** |******* |* 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 12645ns Min update: 9980ns Max update: 50153ns Max update: 33533ns Average update: 25337ns Average update: 18245ns Overruns > 250us: 0 Overruns > 250us: 0 TODO: On icl+ everything seems to be armed by PLANE_SURF, so we can optimize this even further on modern platforms. But I think there's a bit of refactoring to be done first to figure out the best way to go about it (eg. just reusing the current skl+ functions, or doing a lower level split). TODO: Split scaler programming as well, but IIRC the scaler has some oddball double buffering behaviour on some platforms, so needs proper reverse engineering Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-6-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- .../drm/i915/display/skl_universal_plane.c | 113 +++++++++++------- 1 file changed, 72 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 83ee686772ecd..9eda04322a0e6 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1006,60 +1006,32 @@ static void icl_plane_csc_load_black(struct intel_plane *plane) } static void -skl_program_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state, - int color_plane) +skl_program_plane_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state, + int color_plane) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 stride = skl_plane_stride(plane_state, color_plane); const struct drm_framebuffer *fb = plane_state->hw.fb; - int aux_plane = skl_main_to_aux_plane(fb, color_plane); int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; - u32 x = plane_state->view.color_plane[color_plane].x; - u32 y = plane_state->view.color_plane[color_plane].y; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - u8 alpha = plane_state->hw.alpha >> 8; - u32 plane_color_ctl = 0, aux_dist = 0; unsigned long irqflags; - u32 keymsk, keymax; - u32 plane_ctl = plane_state->ctl; - - plane_ctl |= skl_plane_ctl_crtc(crtc_state); - - if (DISPLAY_VER(dev_priv) >= 10) - plane_color_ctl = plane_state->color_ctl | - glk_plane_color_ctl_crtc(crtc_state); /* Sizes are 0 based */ src_w--; src_h--; - keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); - - keymsk = key->channel_mask & 0x7ffffff; - if (alpha < 0xff) - keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; - /* The scaler will handle the output position */ if (plane_state->scaler_id >= 0) { crtc_x = 0; crtc_y = 0; } - if (aux_plane) { - aux_dist = skl_surf_address(plane_state, aux_plane) - - skl_surf_address(plane_state, color_plane); - - if (DISPLAY_VER(dev_priv) < 12) - aux_dist |= skl_plane_stride(plane_state, aux_plane); - } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); /* @@ -1075,16 +1047,10 @@ skl_program_plane(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); - intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist); - if (icl_is_hdr_plane(dev_priv, plane_id)) intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), plane_state->cus_ctl); - if (DISPLAY_VER(dev_priv) >= 10) - intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), - plane_color_ctl); - if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id)) icl_program_input_csc(plane, crtc_state, plane_state); @@ -1094,6 +1060,52 @@ skl_program_plane(struct intel_plane *plane, skl_write_plane_wm(plane, crtc_state); + intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +skl_program_plane_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state, + int color_plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + const struct drm_framebuffer *fb = plane_state->hw.fb; + int aux_plane = skl_main_to_aux_plane(fb, color_plane); + u32 x = plane_state->view.color_plane[color_plane].x; + u32 y = plane_state->view.color_plane[color_plane].y; + u32 keymsk, keymax, aux_dist = 0, plane_color_ctl = 0; + u8 alpha = plane_state->hw.alpha >> 8; + u32 plane_ctl = plane_state->ctl; + unsigned long irqflags; + + plane_ctl |= skl_plane_ctl_crtc(crtc_state); + + if (DISPLAY_VER(dev_priv) >= 10) + plane_color_ctl = plane_state->color_ctl | + glk_plane_color_ctl_crtc(crtc_state); + + keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); + + keymsk = key->channel_mask & 0x7ffffff; + if (alpha < 0xff) + keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; + + if (aux_plane) { + aux_dist = skl_surf_address(plane_state, aux_plane) - + skl_surf_address(plane_state, color_plane); + + if (DISPLAY_VER(dev_priv) < 12) + aux_dist |= skl_plane_stride(plane_state, aux_plane); + } + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), key->min_value); intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk); @@ -1102,17 +1114,22 @@ skl_program_plane(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id), (y << 16) | x); + intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist); + if (DISPLAY_VER(dev_priv) < 11) intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id), (plane_state->view.color_plane[1].y << 16) | plane_state->view.color_plane[1].x); - intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); + if (DISPLAY_VER(dev_priv) >= 10) + intel_de_write_fw(dev_priv, 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(plane, crtc_state, plane_state); @@ -1155,7 +1172,20 @@ skl_plane_async_flip(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -/* TODO: split into noarm+arm pair */ +static void +skl_plane_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + int color_plane = 0; + + if (plane_state->planar_linked_plane && !plane_state->planar_slave) + /* Program the UV plane on planar master */ + color_plane = 1; + + skl_program_plane_noarm(plane, crtc_state, plane_state, color_plane); +} + static void skl_plane_update_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, @@ -1167,7 +1197,7 @@ skl_plane_update_arm(struct intel_plane *plane, /* Program the UV plane on planar master */ color_plane = 1; - skl_program_plane(plane, crtc_state, plane_state, color_plane); + skl_program_plane_arm(plane, crtc_state, plane_state, color_plane); } static bool intel_format_is_p01x(u32 format) @@ -2094,6 +2124,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, } plane->max_stride = skl_plane_max_stride; + plane->update_noarm = skl_plane_update_noarm; plane->update_arm = skl_plane_update_arm; plane->disable_arm = skl_plane_disable_arm; plane->get_hw_state = skl_plane_get_hw_state; From 4d0d77de9af455aa949766ecad1ac3232e322020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 21 Oct 2021 00:27:57 +0300 Subject: [PATCH 098/176] drm/i915: Split pre-skl primary plane update into noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chop i9xx_plane_update() into two halves. Fist half becomes the _noarm() variant, second part the _arm() variant. Fortunately I have already previously grouped the register writes into roughtly the correct order, so the split looks surprisingly clean. One slightly surprising fact was that the CHV pipe B PRIMPOS/SIZE registers are self arming unlike their pre-ctg DSPPOS/SIZE counterparts. In fact all the new CHV pipe B registers are self arming. Also we must remind ourselves that i830/i845 are a bit borked in that all of their plane registers are self-arming. I didn't do any i915_update_info measurements for this one alone. I'll get total numbers with the corrsponding sprite plane changes. v2: Don't break my precious i830/i845 Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211020212757.13517-1-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/i9xx_plane.c | 81 +++++++++++++++++------ 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index d8e8a57e2cc04..ba276e8ab4f09 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -402,23 +402,49 @@ static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state, return DIV_ROUND_UP(pixel_rate * num, den); } -/* TODO: split into noarm+arm pair */ +static void i9xx_plane_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), + plane_state->view.color_plane[0].mapping_stride); + + if (DISPLAY_VER(dev_priv) < 4) { + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + int crtc_w = drm_rect_width(&plane_state->uapi.dst); + int crtc_h = drm_rect_height(&plane_state->uapi.dst); + + /* + * PLANE_A doesn't actually have a full window + * generator but let's assume we still need to + * program whatever is there. + */ + intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), + (crtc_y << 16) | crtc_x); + intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), + ((crtc_h - 1) << 16) | (crtc_w - 1)); + } + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + static void i9xx_plane_update_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - u32 linear_offset; int x = plane_state->view.color_plane[0].x; int y = plane_state->view.color_plane[0].y; - int crtc_x = plane_state->uapi.dst.x1; - int crtc_y = plane_state->uapi.dst.y1; - int crtc_w = drm_rect_width(&plane_state->uapi.dst); - int crtc_h = drm_rect_height(&plane_state->uapi.dst); + u32 dspcntr, dspaddr_offset, linear_offset; unsigned long irqflags; - u32 dspaddr_offset; - u32 dspcntr; dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); @@ -431,20 +457,12 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), - plane_state->view.color_plane[0].mapping_stride); + if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + int crtc_w = drm_rect_width(&plane_state->uapi.dst); + int crtc_h = drm_rect_height(&plane_state->uapi.dst); - if (DISPLAY_VER(dev_priv) < 4) { - /* - * PLANE_A doesn't actually have a full window - * generator but let's assume we still need to - * program whatever is there. - */ - intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), - (crtc_y << 16) | crtc_x); - intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), - ((crtc_h - 1) << 16) | (crtc_w - 1)); - } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane), (crtc_y << 16) | crtc_x); intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane), @@ -478,6 +496,20 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +static void i830_plane_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + /* + * On i830/i845 all registers are self-arming [ALM040]. + * + * Additional breakage on i830 causes register reads to return + * the last latched value instead of the last written value [ALM026]. + */ + i9xx_plane_update_noarm(plane, crtc_state, plane_state); + i9xx_plane_update_arm(plane, crtc_state, plane_state); +} + static void i9xx_plane_disable_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { @@ -837,7 +869,12 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->max_stride = ilk_primary_max_stride; } - plane->update_arm = i9xx_plane_update_arm; + if (IS_I830(dev_priv) || IS_I845G(dev_priv)) { + plane->update_arm = i830_plane_update_arm; + } else { + plane->update_noarm = i9xx_plane_update_noarm; + plane->update_arm = i9xx_plane_update_arm; + } plane->disable_arm = i9xx_plane_disable_arm; plane->get_hw_state = i9xx_plane_get_hw_state; plane->check_plane = i9xx_plane_check; From 120542e2c1d12e7d3594ceeaa6e02296af52cc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:28 +0300 Subject: [PATCH 099/176] drm/i915: Split g4x+ sprite plane update into noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chop g4x_sprite_update() into two halves. Fist half becomes the _noarm() variant, second part the _arm() variant. Fortunately I have already previously grouped the register writes into roughtly the correct order, so the split looks surprisingly clean. Not much of a change in i915_update_info on these older platforms that don't have so many planes or registers to begin with. Here are the numbers from snb (totally unpatched vs. both primary plane and sprite patched applied) running kms_atomic_transition --r plane-all-transition --extended: w/o patch w/ patch Updates: 5404 Updates: 5405 | | 1us |****** 1us |****** |********* |********* 4us |*********** 4us |*********** |********** |********** 16us |** 16us |** | | 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 1400ns Min update: 1307ns Max update: 19809ns Max update: 20194ns Average update: 6957ns Average update: 6432ns Overruns > 100us: 0 Overruns > 100us: 0 But there seems to be a slight improvement with lockdep enabled: w/o patch w/ patch Updates: 17612 Updates: 16364 | | 1us | 1us | |****** |****** 4us |********** 4us |********** |************ |************* 16us |************* 16us |************ |*** |* 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 3141ns Min update: 3562ns Max update: 126450ns Max update: 73354ns Average update: 16373ns Average update: 15153ns Overruns > 250us: 0 Overruns > 250us: 0 Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-8-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_sprite.c | 41 ++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index fb249966e5dd8..fe779b5dd6f60 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1166,28 +1166,21 @@ static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state) } static void -g4x_sprite_update_arm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +g4x_sprite_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; - u32 dvssurf_offset = plane_state->view.color_plane[0].offset; - u32 linear_offset; - const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); - u32 x = plane_state->view.color_plane[0].x; - u32 y = plane_state->view.color_plane[0].y; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - u32 dvscntr, dvsscale = 0; + u32 dvsscale = 0; unsigned long irqflags; - dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state); - /* Sizes are 0 based */ src_w--; src_h--; @@ -1197,8 +1190,6 @@ g4x_sprite_update_arm(struct intel_plane *plane, if (crtc_w != src_w || crtc_h != src_h) dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; - linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DVSSTRIDE(pipe), @@ -1207,6 +1198,29 @@ g4x_sprite_update_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w); intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +g4x_sprite_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum pipe pipe = plane->pipe; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + u32 dvssurf_offset = plane_state->view.color_plane[0].offset; + u32 x = plane_state->view.color_plane[0].x; + u32 y = plane_state->view.color_plane[0].y; + u32 dvscntr, linear_offset; + unsigned long irqflags; + + dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state); + + linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (key->flags) { intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value); intel_de_write_fw(dev_priv, DVSKEYMSK(pipe), @@ -1779,6 +1793,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &snb_sprite_funcs; } else { + plane->update_noarm = g4x_sprite_update_noarm; plane->update_arm = g4x_sprite_update_arm; plane->disable_arm = g4x_sprite_disable_arm; plane->get_hw_state = g4x_sprite_get_hw_state; From 50105a3ad16cac406494038ce4edb91769911434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:29 +0300 Subject: [PATCH 100/176] drm/i915: Split ivb+ sprite plane update into noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chop ivb_sprite_update() into two halves. Fist half becomes the _noarm() variant, second part the _arm() variant. Fortunately I have already previously grouped the register writes into roughtly the correct order, so the split looks surprisingly clean. Didn't bother with i915_update_info numbers for this one. I expect the results to be pretty much identical to the snb numbers from the corresponding g4x+ sprite modification. Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-9-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_sprite.c | 42 ++++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index fe779b5dd6f60..51ffecaa1e20e 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -836,30 +836,22 @@ static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state) i++; } -/* TODO: split into noarm+arm pair */ static void -ivb_sprite_update_arm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +ivb_sprite_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; - u32 sprsurf_offset = plane_state->view.color_plane[0].offset; - u32 linear_offset; - const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); - u32 x = plane_state->view.color_plane[0].x; - u32 y = plane_state->view.color_plane[0].y; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - u32 sprctl, sprscale = 0; + u32 sprscale = 0; unsigned long irqflags; - sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state); - /* Sizes are 0 based */ src_w--; src_h--; @@ -869,8 +861,6 @@ ivb_sprite_update_arm(struct intel_plane *plane, if (crtc_w != src_w || crtc_h != src_h) sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; - linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPRSTRIDE(pipe), @@ -880,6 +870,29 @@ ivb_sprite_update_arm(struct intel_plane *plane, if (IS_IVYBRIDGE(dev_priv)) intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +ivb_sprite_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum pipe pipe = plane->pipe; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + u32 sprsurf_offset = plane_state->view.color_plane[0].offset; + u32 x = plane_state->view.color_plane[0].x; + u32 y = plane_state->view.color_plane[0].y; + u32 sprctl, linear_offset; + unsigned long irqflags; + + sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state); + + linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (key->flags) { intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value); intel_de_write_fw(dev_priv, SPRKEYMSK(pipe), @@ -1775,6 +1788,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &vlv_sprite_funcs; } else if (DISPLAY_VER(dev_priv) >= 7) { + plane->update_noarm = ivb_sprite_update_noarm; plane->update_arm = ivb_sprite_update_arm; plane->disable_arm = ivb_sprite_disable_arm; plane->get_hw_state = ivb_sprite_get_hw_state; From a14fef80ebb3efa5755b02790e067fe259bc8c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Oct 2021 14:50:30 +0300 Subject: [PATCH 101/176] drm/i915: Split vlv/chv sprite plane update into noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chop vlv_sprite_update() into two halves. Fist half becomes the _noarm() variant, second part the _arm() variant. Fortunately I have already previously grouped the register writes into roughtly the correct order, so the split looks surprisingly clean. Looks like most of the hardware logic was copied from the pre-ctg sprite C, so SPSTRIDE/POS/SIZE are armed by SPSURF, while the rest are self arming. SPCONSTALPHA is the one entirely new register that didn't exist in the old sprite C, and looks like that one is self arming. The CHV pipe B CSC is also self arming, like the rest of the CHV pipe B additions. I didn't have time to capture i915_update_info numbers for these, but since all the other platforms generally showed improvements, and crucially no regression, I am fairly confident this should behave similarly. Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211018115030.3547-10-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_sprite.c | 45 ++++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 51ffecaa1e20e..1b99a9501a454 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -417,35 +417,24 @@ static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state) gamma[i] << 16 | gamma[i] << 8 | gamma[i]); } -/* TODO: split into noarm+arm pair */ static void -vlv_sprite_update_arm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +vlv_sprite_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id; - u32 sprsurf_offset = plane_state->view.color_plane[0].offset; - u32 linear_offset; - const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); - u32 x = plane_state->view.color_plane[0].x; - u32 y = plane_state->view.color_plane[0].y; unsigned long irqflags; - u32 sprctl; - - sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state); /* Sizes are 0 based */ crtc_w--; crtc_h--; - linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id), @@ -454,7 +443,30 @@ vlv_sprite_update_arm(struct intel_plane *plane, (crtc_y << 16) | crtc_x); intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w); - intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +vlv_sprite_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum pipe pipe = plane->pipe; + enum plane_id plane_id = plane->id; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + u32 sprsurf_offset = plane_state->view.color_plane[0].offset; + u32 x = plane_state->view.color_plane[0].x; + u32 y = plane_state->view.color_plane[0].y; + u32 sprctl, linear_offset; + unsigned long irqflags; + + sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state); + + linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) chv_sprite_update_csc(plane_state); @@ -468,6 +480,8 @@ vlv_sprite_update_arm(struct intel_plane *plane, key->max_value); } + intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0); + intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset); intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), (y << 16) | x); @@ -1771,6 +1785,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, return plane; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + plane->update_noarm = vlv_sprite_update_noarm; plane->update_arm = vlv_sprite_update_arm; plane->disable_arm = vlv_sprite_disable_arm; plane->get_hw_state = vlv_sprite_get_hw_state; From c64a9a7c05beb2b71b7496d873654f88e1a08593 Mon Sep 17 00:00:00 2001 From: Radhakrishna Sripada Date: Fri, 15 Oct 2021 14:00:41 -0700 Subject: [PATCH 102/176] drm/i915: Update memory bandwidth formulae MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The formulae has been updated to include more variables. Make sure the code carries the same. Bspec: 64631, 54023 v2: Make GEN11 follow the default route and fix calculation of maxdebw(RK) v3: Fix div by zero on default case Correct indent for fallthrough(Jani) v4: Fix div by zero on gen11. v5: Fix 0 max_numchannels case v6: - Split gen11/gen12 algorithms - Fix RKL deburst value - Fix difference b/ween ICL and TGL algorithms - Protect deinterleave from being 0 - Warn when numchannels exceeds max_numchannels - Fix scaling of clk_max from different units - s/deinterleave/channelwidth/ in calculating peakbw - Fix off by one for num_planes TGL+ - Fix SAGV check v7: Fix div by zero error on gen11 v8: Even though the algorithm for gen11 says that we need to return derated bw for a qgv point whose planes are less than no of active planes, we return 0 for deratedbw when only one plane is allowed. We modify the algorithm to accommodate the case where no of active planes are same as the min no of planes supported by a qgv point. v9: Fix dclk scaling for dg1 Cc: Ville Syrjälä Suggested-by: Matt Roper Signed-off-by: Radhakrishna Sripada Reviewed-by: Anusha Srivatsa Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20211015210041.16858-1-radhakrishna.sripada@intel.com --- drivers/gpu/drm/i915/display/intel_bw.c | 211 ++++++++++++++++++++---- 1 file changed, 179 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 8d9d888e93161..15c006194c859 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -27,6 +27,9 @@ struct intel_qgv_info { u8 num_points; u8 num_psf_points; u8 t_bl; + u8 max_numchannels; + u8 channel_width; + u8 deinterleave; }; static int dg1_mchbar_read_qgv_point_info(struct drm_i915_private *dev_priv, @@ -42,7 +45,7 @@ static int dg1_mchbar_read_qgv_point_info(struct drm_i915_private *dev_priv, dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */ else dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */ - sp->dclk = dclk_ratio * dclk_reference; + sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000); val = intel_uncore_read(&dev_priv->uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); if (val & DG1_GEAR_TYPE) @@ -69,6 +72,7 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv, int point) { u32 val = 0, val2 = 0; + u16 dclk; int ret; ret = sandybridge_pcode_read(dev_priv, @@ -78,7 +82,8 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv, if (ret) return ret; - sp->dclk = val & 0xffff; + dclk = val & 0xffff; + sp->dclk = DIV_ROUND_UP((16667 * dclk) + (DISPLAY_VER(dev_priv) > 11 ? 500 : 0), 1000); sp->t_rp = (val & 0xff0000) >> 16; sp->t_rcd = (val & 0xff000000) >> 24; @@ -133,7 +138,8 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv, } static int icl_get_qgv_points(struct drm_i915_private *dev_priv, - struct intel_qgv_info *qi) + struct intel_qgv_info *qi, + bool is_y_tile) { const struct dram_info *dram_info = &dev_priv->dram_info; int i, ret; @@ -144,17 +150,41 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, if (DISPLAY_VER(dev_priv) == 12) switch (dram_info->type) { case INTEL_DRAM_DDR4: - qi->t_bl = 4; + qi->t_bl = is_y_tile ? 8 : 4; + qi->max_numchannels = 2; + qi->channel_width = 64; + qi->deinterleave = is_y_tile ? 1 : 2; break; case INTEL_DRAM_DDR5: - qi->t_bl = 8; + qi->t_bl = is_y_tile ? 16 : 8; + qi->max_numchannels = 4; + qi->channel_width = 32; + qi->deinterleave = is_y_tile ? 1 : 2; + break; + case INTEL_DRAM_LPDDR4: + if (IS_ROCKETLAKE(dev_priv)) { + qi->t_bl = 8; + qi->max_numchannels = 4; + qi->channel_width = 32; + qi->deinterleave = 2; + break; + } + fallthrough; + case INTEL_DRAM_LPDDR5: + qi->t_bl = 16; + qi->max_numchannels = 8; + qi->channel_width = 16; + qi->deinterleave = is_y_tile ? 2 : 4; break; default: qi->t_bl = 16; + qi->max_numchannels = 1; break; } - else if (DISPLAY_VER(dev_priv) == 11) + else if (DISPLAY_VER(dev_priv) == 11) { qi->t_bl = dev_priv->dram_info.type == INTEL_DRAM_DDR4 ? 4 : 8; + qi->max_numchannels = 1; + } if (drm_WARN_ON(&dev_priv->drm, qi->num_points > ARRAY_SIZE(qi->points))) @@ -193,12 +223,6 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, return 0; } -static int icl_calc_bw(int dclk, int num, int den) -{ - /* multiples of 16.666MHz (100/6) */ - return DIV_ROUND_CLOSEST(num * dclk * 100, den * 6); -} - static int adl_calc_psf_bw(int clk) { /* @@ -240,7 +264,7 @@ static const struct intel_sa_info tgl_sa_info = { }; static const struct intel_sa_info rkl_sa_info = { - .deburst = 16, + .deburst = 8, .deprogbwlimit = 20, /* GB/s */ .displayrtids = 128, .derating = 10, @@ -265,35 +289,130 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel struct intel_qgv_info qi = {}; bool is_y_tile = true; /* assume y tile may be used */ int num_channels = max_t(u8, 1, dev_priv->dram_info.num_channels); - int deinterleave; - int ipqdepth, ipqdepthpch; + int ipqdepth, ipqdepthpch = 16; int dclk_max; int maxdebw; + int num_groups = ARRAY_SIZE(dev_priv->max_bw); int i, ret; - ret = icl_get_qgv_points(dev_priv, &qi); + ret = icl_get_qgv_points(dev_priv, &qi, is_y_tile); if (ret) { drm_dbg_kms(&dev_priv->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); return ret; } - deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2); dclk_max = icl_sagv_max_dclk(&qi); + maxdebw = min(sa->deprogbwlimit * 1000, dclk_max * 16 * 6 / 10); + ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels); + qi.deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2); + + for (i = 0; i < num_groups; i++) { + struct intel_bw_info *bi = &dev_priv->max_bw[i]; + int clpchgroup; + int j; + + clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i; + bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1; + + bi->num_qgv_points = qi.num_points; + bi->num_psf_gv_points = qi.num_psf_points; + + for (j = 0; j < qi.num_points; j++) { + const struct intel_qgv_point *sp = &qi.points[j]; + int ct, bw; + + /* + * Max row cycle time + * + * FIXME what is the logic behind the + * assumed burst length? + */ + ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd + + (clpchgroup - 1) * qi.t_bl + sp->t_rdpre); + bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct); - ipqdepthpch = 16; + bi->deratedbw[j] = min(maxdebw, + bw * (100 - sa->derating) / 100); + + drm_dbg_kms(&dev_priv->drm, + "BW%d / QGV %d: num_planes=%d deratedbw=%u\n", + i, j, bi->num_planes, bi->deratedbw[j]); + } + } + /* + * In case if SAGV is disabled in BIOS, we always get 1 + * SAGV point, but we can't send PCode commands to restrict it + * as it will fail and pointless anyway. + */ + if (qi.num_points == 1) + dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; + else + dev_priv->sagv_status = I915_SAGV_ENABLED; + + return 0; +} + +static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa) +{ + struct intel_qgv_info qi = {}; + const struct dram_info *dram_info = &dev_priv->dram_info; + bool is_y_tile = true; /* assume y tile may be used */ + int num_channels = max_t(u8, 1, dev_priv->dram_info.num_channels); + int ipqdepth, ipqdepthpch = 16; + int dclk_max; + int maxdebw, peakbw; + int clperchgroup; + int num_groups = ARRAY_SIZE(dev_priv->max_bw); + int i, ret; + + ret = icl_get_qgv_points(dev_priv, &qi, is_y_tile); + if (ret) { + drm_dbg_kms(&dev_priv->drm, + "Failed to get memory subsystem information, ignoring bandwidth limits"); + return ret; + } + + if (dram_info->type == INTEL_DRAM_LPDDR4 || dram_info->type == INTEL_DRAM_LPDDR5) + num_channels *= 2; + + qi.deinterleave = qi.deinterleave ? : DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2); + + if (num_channels < qi.max_numchannels && DISPLAY_VER(dev_priv) >= 12) + qi.deinterleave = max(DIV_ROUND_UP(qi.deinterleave, 2), 1); + + if (DISPLAY_VER(dev_priv) > 11 && num_channels > qi.max_numchannels) + drm_warn(&dev_priv->drm, "Number of channels exceeds max number of channels."); + if (qi.max_numchannels != 0) + num_channels = min_t(u8, num_channels, qi.max_numchannels); + + dclk_max = icl_sagv_max_dclk(&qi); + + peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max; + maxdebw = min(sa->deprogbwlimit * 1000, peakbw * 6 / 10); /* 60% */ - maxdebw = min(sa->deprogbwlimit * 1000, - icl_calc_bw(dclk_max, 16, 1) * 6 / 10); /* 60% */ ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels); + /* + * clperchgroup = 4kpagespermempage * clperchperblock, + * clperchperblock = 8 / num_channels * interleave + */ + clperchgroup = 4 * DIV_ROUND_UP(8, num_channels) * qi.deinterleave; - for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) { + for (i = 0; i < num_groups; i++) { struct intel_bw_info *bi = &dev_priv->max_bw[i]; + struct intel_bw_info *bi_next; int clpchgroup; int j; - clpchgroup = (sa->deburst * deinterleave / num_channels) << i; - bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1; + if (i < num_groups - 1) + bi_next = &dev_priv->max_bw[i + 1]; + + clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i; + + if (i < num_groups - 1 && clpchgroup < clperchgroup) + bi_next->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1; + else + bi_next->num_planes = 0; bi->num_qgv_points = qi.num_points; bi->num_psf_gv_points = qi.num_psf_points; @@ -310,7 +429,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel */ ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd + (clpchgroup - 1) * qi.t_bl + sp->t_rdpre); - bw = icl_calc_bw(sp->dclk, clpchgroup * 32 * num_channels, ct); + bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct); bi->deratedbw[j] = min(maxdebw, bw * (100 - sa->derating) / 100); @@ -329,9 +448,6 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel "BW%d / PSF GV %d: num_planes=%d bw=%u\n", i, j, bi->num_planes, bi->psf_bw[j]); } - - if (bi->num_planes == 1) - break; } /* @@ -395,6 +511,34 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv, return 0; } +static unsigned int tgl_max_bw(struct drm_i915_private *dev_priv, + int num_planes, int qgv_point) +{ + int i; + + /* + * Let's return max bw for 0 planes + */ + num_planes = max(1, num_planes); + + for (i = ARRAY_SIZE(dev_priv->max_bw) - 1; i >= 0; i--) { + const struct intel_bw_info *bi = + &dev_priv->max_bw[i]; + + /* + * Pcode will not expose all QGV points when + * SAGV is forced to off/min/med/max. + */ + if (qgv_point >= bi->num_qgv_points) + return UINT_MAX; + + if (num_planes <= bi->num_planes) + return bi->deratedbw[qgv_point]; + } + + return dev_priv->max_bw[0].deratedbw[qgv_point]; +} + static unsigned int adl_psf_bw(struct drm_i915_private *dev_priv, int psf_gv_point) { @@ -412,13 +556,13 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv) if (IS_DG2(dev_priv)) dg2_get_bw_info(dev_priv); else if (IS_ALDERLAKE_P(dev_priv)) - icl_get_bw_info(dev_priv, &adlp_sa_info); + tgl_get_bw_info(dev_priv, &adlp_sa_info); else if (IS_ALDERLAKE_S(dev_priv)) - icl_get_bw_info(dev_priv, &adls_sa_info); + tgl_get_bw_info(dev_priv, &adls_sa_info); else if (IS_ROCKETLAKE(dev_priv)) - icl_get_bw_info(dev_priv, &rkl_sa_info); + tgl_get_bw_info(dev_priv, &rkl_sa_info); else if (DISPLAY_VER(dev_priv) == 12) - icl_get_bw_info(dev_priv, &tgl_sa_info); + tgl_get_bw_info(dev_priv, &tgl_sa_info); else if (DISPLAY_VER(dev_priv) == 11) icl_get_bw_info(dev_priv, &icl_sa_info); } @@ -746,7 +890,10 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) for (i = 0; i < num_qgv_points; i++) { unsigned int max_data_rate; - max_data_rate = icl_max_bw(dev_priv, num_active_planes, i); + if (DISPLAY_VER(dev_priv) > 11) + max_data_rate = tgl_max_bw(dev_priv, num_active_planes, i); + else + max_data_rate = icl_max_bw(dev_priv, num_active_planes, i); /* * We need to know which qgv point gives us * maximum bandwidth in order to disable SAGV From fe9b286bd063791c7842c4caf6efb2825b537031 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Nov 2021 18:18:53 +0200 Subject: [PATCH 103/176] drm/i915/audio: group audio under anonymous struct in drm_i915_private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With an anonymous struct, this can be pure hierarchical organization without code changes. We'll follow up with adding a name to the sub-struct separately. Cc: Dave Airlie Reviewed-by: Ville Syrjälä Reviewed-by: Lucas De Marchi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211104161858.21786-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 43 +++++++++++++++++---------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 19e6700a4315b..ee210e12648ab 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -995,9 +995,6 @@ struct drm_i915_private { /* Display internal color functions */ const struct intel_color_funcs *color_funcs; - /* Display internal audio functions */ - const struct intel_audio_funcs *audio_funcs; - /* Display CDCLK functions */ const struct intel_cdclk_funcs *cdclk_funcs; @@ -1084,17 +1081,6 @@ struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; - /* hda/i915 audio component */ - struct i915_audio_component *audio_component; - bool audio_component_registered; - /** - * av_mutex - mutex for audio/video sync - * - */ - struct mutex av_mutex; - int audio_power_refcount; - u32 audio_freq_cntrl; - u32 fdi_rx_config; /* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */ @@ -1227,14 +1213,29 @@ struct drm_i915_private { bool ipc_enabled; - /* Used to save the pipe-to-encoder mapping for audio */ - struct intel_encoder *av_enc_map[I915_MAX_PIPES]; - - /* necessary resource sharing with HDMI LPE audio driver. */ struct { - struct platform_device *platdev; - int irq; - } lpe_audio; + /* Display internal audio functions */ + const struct intel_audio_funcs *audio_funcs; + + /* hda/i915 audio component */ + struct i915_audio_component *audio_component; + bool audio_component_registered; + /** + * av_mutex - mutex for audio/video sync + */ + struct mutex av_mutex; + int audio_power_refcount; + u32 audio_freq_cntrl; + + /* Used to save the pipe-to-encoder mapping for audio */ + struct intel_encoder *av_enc_map[I915_MAX_PIPES]; + + /* necessary resource sharing with HDMI LPE audio driver. */ + struct { + struct platform_device *platdev; + int irq; + } lpe_audio; + }; struct i915_pmu pmu; From ca3cfb9d9b5edffbea1464079abaa89714e7abd6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Nov 2021 18:18:54 +0200 Subject: [PATCH 104/176] drm/i915/audio: name the audio sub-struct in drm_i915_private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add name to the audio sub-struct in drm_i915_private, and remove the tautologies and other inconsistencies in the member names. v2: Call the mutex member mutex, not lock. (Ville) Cc: Dave Airlie Reviewed-by: Ville Syrjälä Reviewed-by: Lucas De Marchi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211104161858.21786-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 90 +++++++++---------- .../gpu/drm/i915/display/intel_lpe_audio.c | 42 ++++----- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 22 +++-- 4 files changed, 77 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index a96523f1b052d..6088304f82dfe 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -388,7 +388,7 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio_component; + struct i915_audio_component *acomp = dev_priv->audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; const struct dp_aud_n_m *nm; @@ -436,7 +436,7 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio_component; + struct i915_audio_component *acomp = dev_priv->audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; int n, rate; @@ -494,7 +494,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, drm_dbg_kms(&dev_priv->drm, "Disable audio codec on transcoder %s\n", transcoder_name(cpu_transcoder)); - mutex_lock(&dev_priv->av_mutex); + mutex_lock(&dev_priv->audio.mutex); /* Disable timestamps */ tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder)); @@ -512,7 +512,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, tmp &= ~AUDIO_OUTPUT_ENABLE(cpu_transcoder); intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp); - mutex_unlock(&dev_priv->av_mutex); + mutex_unlock(&dev_priv->audio.mutex); } static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, @@ -641,7 +641,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, "Enable audio codec on transcoder %s, %u bytes ELD\n", transcoder_name(cpu_transcoder), drm_eld_size(eld)); - mutex_lock(&dev_priv->av_mutex); + mutex_lock(&dev_priv->audio.mutex); /* Enable Audio WA for 4k DSC usecases */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) @@ -679,7 +679,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, /* Enable timestamps */ hsw_audio_config_update(encoder, crtc_state); - mutex_unlock(&dev_priv->av_mutex); + mutex_unlock(&dev_priv->audio.mutex); } static void ilk_audio_codec_disable(struct intel_encoder *encoder, @@ -826,7 +826,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio_component; + struct i915_audio_component *acomp = dev_priv->audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; const struct drm_display_mode *adjusted_mode = @@ -848,17 +848,17 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; - if (dev_priv->audio_funcs) - dev_priv->audio_funcs->audio_codec_enable(encoder, + if (dev_priv->audio.funcs) + dev_priv->audio.funcs->audio_codec_enable(encoder, crtc_state, conn_state); - mutex_lock(&dev_priv->av_mutex); + mutex_lock(&dev_priv->audio.mutex); encoder->audio_connector = connector; /* referred in audio callbacks */ - dev_priv->av_enc_map[pipe] = encoder; - mutex_unlock(&dev_priv->av_mutex); + dev_priv->audio.encoder_map[pipe] = encoder; + mutex_unlock(&dev_priv->audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -888,20 +888,20 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio_component; + struct i915_audio_component *acomp = dev_priv->audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; - if (dev_priv->audio_funcs) - dev_priv->audio_funcs->audio_codec_disable(encoder, + if (dev_priv->audio.funcs) + dev_priv->audio.funcs->audio_codec_disable(encoder, old_crtc_state, old_conn_state); - mutex_lock(&dev_priv->av_mutex); + mutex_lock(&dev_priv->audio.mutex); encoder->audio_connector = NULL; - dev_priv->av_enc_map[pipe] = NULL; - mutex_unlock(&dev_priv->av_mutex); + dev_priv->audio.encoder_map[pipe] = NULL; + mutex_unlock(&dev_priv->audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -937,13 +937,13 @@ static const struct intel_audio_funcs hsw_audio_funcs = { void intel_init_audio_hooks(struct drm_i915_private *dev_priv) { if (IS_G4X(dev_priv)) { - dev_priv->audio_funcs = &g4x_audio_funcs; + dev_priv->audio.funcs = &g4x_audio_funcs; } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - dev_priv->audio_funcs = &ilk_audio_funcs; + dev_priv->audio.funcs = &ilk_audio_funcs; } else if (IS_HASWELL(dev_priv) || DISPLAY_VER(dev_priv) >= 8) { - dev_priv->audio_funcs = &hsw_audio_funcs; + dev_priv->audio.funcs = &hsw_audio_funcs; } else if (HAS_PCH_SPLIT(dev_priv)) { - dev_priv->audio_funcs = &ilk_audio_funcs; + dev_priv->audio.funcs = &ilk_audio_funcs; } } @@ -1048,13 +1048,13 @@ static unsigned long i915_audio_component_get_power(struct device *kdev) ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK); - if (dev_priv->audio_power_refcount++ == 0) { + if (dev_priv->audio.power_refcount++ == 0) { if (DISPLAY_VER(dev_priv) >= 9) { intel_de_write(dev_priv, AUD_FREQ_CNTRL, - dev_priv->audio_freq_cntrl); + dev_priv->audio.freq_cntrl); drm_dbg_kms(&dev_priv->drm, "restored AUD_FREQ_CNTRL to 0x%x\n", - dev_priv->audio_freq_cntrl); + dev_priv->audio.freq_cntrl); } /* Force CDCLK to 2*BCLK as long as we need audio powered. */ @@ -1075,7 +1075,7 @@ static void i915_audio_component_put_power(struct device *kdev, struct drm_i915_private *dev_priv = kdev_to_i915(kdev); /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ - if (--dev_priv->audio_power_refcount == 0) + if (--dev_priv->audio.power_refcount == 0) if (IS_GEMINILAKE(dev_priv)) glk_force_audio_cdclk(dev_priv, false); @@ -1127,7 +1127,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) /* * get the intel_encoder according to the parameter port and pipe * intel_encoder is saved by the index of pipe - * MST & (pipe >= 0): return the av_enc_map[pipe], + * MST & (pipe >= 0): return the audio.encoder_map[pipe], * when port is matched * MST & (pipe < 0): this is invalid * Non-MST & (pipe >= 0): only pipe = 0 (the first device entry) @@ -1142,10 +1142,10 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, /* MST */ if (pipe >= 0) { if (drm_WARN_ON(&dev_priv->drm, - pipe >= ARRAY_SIZE(dev_priv->av_enc_map))) + pipe >= ARRAY_SIZE(dev_priv->audio.encoder_map))) return NULL; - encoder = dev_priv->av_enc_map[pipe]; + encoder = dev_priv->audio.encoder_map[pipe]; /* * when bootup, audio driver may not know it is * MST or not. So it will poll all the port & pipe @@ -1161,7 +1161,7 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, return NULL; for_each_pipe(dev_priv, pipe) { - encoder = dev_priv->av_enc_map[pipe]; + encoder = dev_priv->audio.encoder_map[pipe]; if (encoder == NULL) continue; @@ -1179,7 +1179,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, int pipe, int rate) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct i915_audio_component *acomp = dev_priv->audio_component; + struct i915_audio_component *acomp = dev_priv->audio.component; struct intel_encoder *encoder; struct intel_crtc *crtc; unsigned long cookie; @@ -1189,7 +1189,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, return 0; cookie = i915_audio_component_get_power(kdev); - mutex_lock(&dev_priv->av_mutex); + mutex_lock(&dev_priv->audio.mutex); /* 1. get the pipe */ encoder = get_saved_enc(dev_priv, port, pipe); @@ -1208,7 +1208,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, hsw_audio_config_update(encoder, crtc->config); unlock: - mutex_unlock(&dev_priv->av_mutex); + mutex_unlock(&dev_priv->audio.mutex); i915_audio_component_put_power(kdev, cookie); return err; } @@ -1222,13 +1222,13 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, const u8 *eld; int ret = -EINVAL; - mutex_lock(&dev_priv->av_mutex); + mutex_lock(&dev_priv->audio.mutex); intel_encoder = get_saved_enc(dev_priv, port, pipe); if (!intel_encoder) { drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n", port_name(port)); - mutex_unlock(&dev_priv->av_mutex); + mutex_unlock(&dev_priv->audio.mutex); return ret; } @@ -1240,7 +1240,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, memcpy(buf, eld, min(max_bytes, ret)); } - mutex_unlock(&dev_priv->av_mutex); + mutex_unlock(&dev_priv->audio.mutex); return ret; } @@ -1275,7 +1275,7 @@ static int i915_audio_component_bind(struct device *i915_kdev, BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; - dev_priv->audio_component = acomp; + dev_priv->audio.component = acomp; drm_modeset_unlock_all(&dev_priv->drm); return 0; @@ -1290,14 +1290,14 @@ static void i915_audio_component_unbind(struct device *i915_kdev, drm_modeset_lock_all(&dev_priv->drm); acomp->base.ops = NULL; acomp->base.dev = NULL; - dev_priv->audio_component = NULL; + dev_priv->audio.component = NULL; drm_modeset_unlock_all(&dev_priv->drm); device_link_remove(hda_kdev, i915_kdev); - if (dev_priv->audio_power_refcount) + if (dev_priv->audio.power_refcount) drm_err(&dev_priv->drm, "audio power refcount %d after unbind\n", - dev_priv->audio_power_refcount); + dev_priv->audio.power_refcount); } static const struct component_ops i915_audio_component_bind_ops = { @@ -1361,13 +1361,13 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", aud_freq, aud_freq_init); - dev_priv->audio_freq_cntrl = aud_freq; + dev_priv->audio.freq_cntrl = aud_freq; } /* init with current cdclk */ intel_audio_cdclk_change_post(dev_priv); - dev_priv->audio_component_registered = true; + dev_priv->audio.component_registered = true; } /** @@ -1379,11 +1379,11 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv) */ static void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) { - if (!dev_priv->audio_component_registered) + if (!dev_priv->audio.component_registered) return; component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops); - dev_priv->audio_component_registered = false; + dev_priv->audio.component_registered = false; } /** @@ -1405,7 +1405,7 @@ void intel_audio_init(struct drm_i915_private *dev_priv) */ void intel_audio_deinit(struct drm_i915_private *dev_priv) { - if ((dev_priv)->lpe_audio.platdev != NULL) + if ((dev_priv)->audio.lpe.platdev != NULL) intel_lpe_audio_teardown(dev_priv); else i915_audio_component_cleanup(dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 7f3c638c8950d..4970bf146c4a8 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -74,7 +74,7 @@ #include "intel_de.h" #include "intel_lpe_audio.h" -#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->lpe_audio.platdev != NULL) +#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->audio.lpe.platdev != NULL) static struct platform_device * lpe_audio_platdev_create(struct drm_i915_private *dev_priv) @@ -96,7 +96,7 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) return ERR_PTR(-ENOMEM); } - rsc[0].start = rsc[0].end = dev_priv->lpe_audio.irq; + rsc[0].start = rsc[0].end = dev_priv->audio.lpe.irq; rsc[0].flags = IORESOURCE_IRQ; rsc[0].name = "hdmi-lpe-audio-irq"; @@ -148,7 +148,7 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) * than us fiddle with its internals. */ - platform_device_unregister(dev_priv->lpe_audio.platdev); + platform_device_unregister(dev_priv->audio.lpe.platdev); } static void lpe_audio_irq_unmask(struct irq_data *d) @@ -167,7 +167,7 @@ static struct irq_chip lpe_audio_irqchip = { static int lpe_audio_irq_init(struct drm_i915_private *dev_priv) { - int irq = dev_priv->lpe_audio.irq; + int irq = dev_priv->audio.lpe.irq; drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); irq_set_chip_and_handler_name(irq, @@ -204,15 +204,15 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) { int ret; - dev_priv->lpe_audio.irq = irq_alloc_desc(0); - if (dev_priv->lpe_audio.irq < 0) { + dev_priv->audio.lpe.irq = irq_alloc_desc(0); + if (dev_priv->audio.lpe.irq < 0) { drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n", - dev_priv->lpe_audio.irq); - ret = dev_priv->lpe_audio.irq; + dev_priv->audio.lpe.irq); + ret = dev_priv->audio.lpe.irq; goto err; } - drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->lpe_audio.irq); + drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->audio.lpe.irq); ret = lpe_audio_irq_init(dev_priv); @@ -223,10 +223,10 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) goto err_free_irq; } - dev_priv->lpe_audio.platdev = lpe_audio_platdev_create(dev_priv); + dev_priv->audio.lpe.platdev = lpe_audio_platdev_create(dev_priv); - if (IS_ERR(dev_priv->lpe_audio.platdev)) { - ret = PTR_ERR(dev_priv->lpe_audio.platdev); + if (IS_ERR(dev_priv->audio.lpe.platdev)) { + ret = PTR_ERR(dev_priv->audio.lpe.platdev); drm_err(&dev_priv->drm, "Failed to create lpe audio platform device: %d\n", ret); @@ -241,10 +241,10 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) return 0; err_free_irq: - irq_free_desc(dev_priv->lpe_audio.irq); + irq_free_desc(dev_priv->audio.lpe.irq); err: - dev_priv->lpe_audio.irq = -1; - dev_priv->lpe_audio.platdev = NULL; + dev_priv->audio.lpe.irq = -1; + dev_priv->audio.lpe.platdev = NULL; return ret; } @@ -262,7 +262,7 @@ void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv) if (!HAS_LPE_AUDIO(dev_priv)) return; - ret = generic_handle_irq(dev_priv->lpe_audio.irq); + ret = generic_handle_irq(dev_priv->audio.lpe.irq); if (ret) drm_err_ratelimited(&dev_priv->drm, "error handling LPE audio irq: %d\n", ret); @@ -303,10 +303,10 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) lpe_audio_platdev_destroy(dev_priv); - irq_free_desc(dev_priv->lpe_audio.irq); + irq_free_desc(dev_priv->audio.lpe.irq); - dev_priv->lpe_audio.irq = -1; - dev_priv->lpe_audio.platdev = NULL; + dev_priv->audio.lpe.irq = -1; + dev_priv->audio.lpe.platdev = NULL; } /** @@ -333,7 +333,7 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, if (!HAS_LPE_AUDIO(dev_priv)) return; - pdata = dev_get_platdata(&dev_priv->lpe_audio.platdev->dev); + pdata = dev_get_platdata(&dev_priv->audio.lpe.platdev->dev); ppdata = &pdata->port[port - PORT_B]; spin_lock_irqsave(&pdata->lpe_audio_slock, irqflags); @@ -361,7 +361,7 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, } if (pdata->notify_audio_lpe) - pdata->notify_audio_lpe(dev_priv->lpe_audio.platdev, port - PORT_B); + pdata->notify_audio_lpe(dev_priv->audio.lpe.platdev, port - PORT_B); spin_unlock_irqrestore(&pdata->lpe_audio_slock, irqflags); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 4a054aa1860b0..d9630d79106fc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -324,7 +324,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->sb_lock); cpu_latency_qos_add_request(&dev_priv->sb_qos, PM_QOS_DEFAULT_VALUE); - mutex_init(&dev_priv->av_mutex); + mutex_init(&dev_priv->audio.mutex); mutex_init(&dev_priv->wm.wm_mutex); mutex_init(&dev_priv->pps_mutex); mutex_init(&dev_priv->hdcp_comp_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ee210e12648ab..f754c4bf75d30 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1215,27 +1215,25 @@ struct drm_i915_private { struct { /* Display internal audio functions */ - const struct intel_audio_funcs *audio_funcs; + const struct intel_audio_funcs *funcs; /* hda/i915 audio component */ - struct i915_audio_component *audio_component; - bool audio_component_registered; - /** - * av_mutex - mutex for audio/video sync - */ - struct mutex av_mutex; - int audio_power_refcount; - u32 audio_freq_cntrl; + struct i915_audio_component *component; + bool component_registered; + /* mutex for audio/video sync */ + struct mutex mutex; + int power_refcount; + u32 freq_cntrl; /* Used to save the pipe-to-encoder mapping for audio */ - struct intel_encoder *av_enc_map[I915_MAX_PIPES]; + struct intel_encoder *encoder_map[I915_MAX_PIPES]; /* necessary resource sharing with HDMI LPE audio driver. */ struct { struct platform_device *platdev; int irq; - } lpe_audio; - }; + } lpe; + } audio; struct i915_pmu pmu; From 37388c0192bf1474ffaaaf38024dab49d0150f12 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Nov 2021 18:18:55 +0200 Subject: [PATCH 105/176] drm/i915/audio: define the audio struct separately from drm_i915_private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a standalone definition of struct intel_audio_private, and note that all of it is private to intel_audio.c. v2: Rebase Cc: Dave Airlie Reviewed-by: Ville Syrjälä Reviewed-by: Lucas De Marchi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211104161858.21786-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 45 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f754c4bf75d30..8bb2275c819c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -828,6 +828,29 @@ struct i915_selftest_stash { struct ida mock_region_instances; }; +/* intel_audio.c private */ +struct intel_audio_private { + /* Display internal audio functions */ + const struct intel_audio_funcs *funcs; + + /* hda/i915 audio component */ + struct i915_audio_component *component; + bool component_registered; + /* mutex for audio/video sync */ + struct mutex mutex; + int power_refcount; + u32 freq_cntrl; + + /* Used to save the pipe-to-encoder mapping for audio */ + struct intel_encoder *encoder_map[I915_MAX_PIPES]; + + /* necessary resource sharing with HDMI LPE audio driver. */ + struct { + struct platform_device *platdev; + int irq; + } lpe; +}; + struct drm_i915_private { struct drm_device drm; @@ -1213,27 +1236,7 @@ struct drm_i915_private { bool ipc_enabled; - struct { - /* Display internal audio functions */ - const struct intel_audio_funcs *funcs; - - /* hda/i915 audio component */ - struct i915_audio_component *component; - bool component_registered; - /* mutex for audio/video sync */ - struct mutex mutex; - int power_refcount; - u32 freq_cntrl; - - /* Used to save the pipe-to-encoder mapping for audio */ - struct intel_encoder *encoder_map[I915_MAX_PIPES]; - - /* necessary resource sharing with HDMI LPE audio driver. */ - struct { - struct platform_device *platdev; - int irq; - } lpe; - } audio; + struct intel_audio_private audio; struct i915_pmu pmu; From 5d4537463fc2eb1245093e0b62e200ed9229d00b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Nov 2021 18:18:56 +0200 Subject: [PATCH 106/176] drm/i915/audio: move intel_audio_funcs internal to intel_audio.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's all internal to intel_audio.c. Cc: Dave Airlie Reviewed-by: Ville Syrjälä Reviewed-by: Lucas De Marchi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211104161858.21786-4-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 9 +++++++++ drivers/gpu/drm/i915/i915_drv.h | 10 +--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 6088304f82dfe..24e76657d5612 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -62,6 +62,15 @@ * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver. */ +struct intel_audio_funcs { + void (*audio_codec_enable)(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); + void (*audio_codec_disable)(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state); +}; + /* DP N/M table */ #define LC_810M 810000 #define LC_540M 540000 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8bb2275c819c0..cf88a47799f9f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -364,15 +364,6 @@ struct intel_color_funcs { void (*read_luts)(struct intel_crtc_state *crtc_state); }; -struct intel_audio_funcs { - void (*audio_codec_enable)(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); - void (*audio_codec_disable)(struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state); -}; - struct intel_cdclk_funcs { void (*get_cdclk)(struct drm_i915_private *dev_priv, struct intel_cdclk_config *cdclk_config); @@ -829,6 +820,7 @@ struct i915_selftest_stash { }; /* intel_audio.c private */ +struct intel_audio_funcs; struct intel_audio_private { /* Display internal audio functions */ const struct intel_audio_funcs *funcs; From f47a0e35846740ca72b8ba6be84b5b518abcebce Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Nov 2021 18:18:58 +0200 Subject: [PATCH 107/176] drm/i915/audio: rename intel_init_audio_hooks to intel_audio_hooks_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow the filename based prefix naming. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211104161858.21786-6-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 4 ++-- drivers/gpu/drm/i915/display/intel_audio.h | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 24e76657d5612..03c3111ebdf03 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -940,10 +940,10 @@ static const struct intel_audio_funcs hsw_audio_funcs = { }; /** - * intel_init_audio_hooks - Set up chip specific audio hooks + * intel_audio_hooks_init - Set up chip specific audio hooks * @dev_priv: device private */ -void intel_init_audio_hooks(struct drm_i915_private *dev_priv) +void intel_audio_hooks_init(struct drm_i915_private *dev_priv) { if (IS_G4X(dev_priv)) { dev_priv->audio.funcs = &g4x_audio_funcs; diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index dcb259dd2da74..63b22131dc456 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -11,7 +11,7 @@ struct drm_i915_private; struct intel_crtc_state; struct intel_encoder; -void intel_init_audio_hooks(struct drm_i915_private *dev_priv); +void intel_audio_hooks_init(struct drm_i915_private *dev_priv); void intel_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e9c29d4bb70ab..0b43650b0e4fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -9494,7 +9494,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) return; intel_init_cdclk_hooks(dev_priv); - intel_init_audio_hooks(dev_priv); + intel_audio_hooks_init(dev_priv); intel_dpll_init_clock_hook(dev_priv); From 4fe7907f3775034140a518d1582580926da98ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 3 Nov 2021 18:08:58 -0700 Subject: [PATCH 108/176] drm/i915/display/adlp: Disable underrun recovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was also defeatured for ADL-P and other platforms. BSpec: 55424 Signed-off-by: José Roberto de Souza Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104010858.43559-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 39 ++++---------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0b43650b0e4fe..4cd268ca52fbb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -956,26 +956,6 @@ void intel_display_finish_reset(struct drm_i915_private *dev_priv) clear_bit_unlock(I915_RESET_MODESET, &dev_priv->gt.reset.flags); } -static bool underrun_recovery_supported(const struct intel_crtc_state *crtc_state) -{ - if (crtc_state->pch_pfit.enabled && - (crtc_state->pipe_src_w > drm_rect_width(&crtc_state->pch_pfit.dst) || - crtc_state->pipe_src_h > drm_rect_height(&crtc_state->pch_pfit.dst) || - crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)) - return false; - - if (crtc_state->dsc.compression_enable) - return false; - - if (crtc_state->has_psr2) - return false; - - if (crtc_state->splitter.enable) - return false; - - return true; -} - static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -999,19 +979,14 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state) */ tmp |= PIXEL_ROUNDING_TRUNC_FB_PASSTHRU; - if (IS_DG2(dev_priv)) { - /* - * Underrun recovery must always be disabled on DG2. However - * the chicken bit meaning is inverted compared to other - * platforms. - */ + /* + * Underrun recovery must always be disabled on display 13+. + * DG2 chicken bit meaning is inverted compared to other platforms. + */ + if (IS_DG2(dev_priv)) tmp &= ~UNDERRUN_RECOVERY_ENABLE_DG2; - } else if (DISPLAY_VER(dev_priv) >= 13) { - if (underrun_recovery_supported(crtc_state)) - tmp &= ~UNDERRUN_RECOVERY_DISABLE_ADLP; - else - tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP; - } + else if (DISPLAY_VER(dev_priv) >= 13) + tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP; intel_de_write(dev_priv, PIPE_CHICKEN(pipe), tmp); } From cf9420cb122d055840848b039cbbc303882bc445 Mon Sep 17 00:00:00 2001 From: Radhakrishna Sripada Date: Fri, 5 Nov 2021 17:37:14 -0700 Subject: [PATCH 109/176] drm/i915: Fix Memory BW formulae for ADL-P MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The earlier update to BW formulae broke ADL-P. Include display 13 to use TGL path for BW parameters. Fixes: c64a9a7c05be ("drm/i915: Update memory bandwidth formulae") Cc: Matt Roper Reported-by: José Roberto de Souza Signed-off-by: Radhakrishna Sripada Reviewed-by: Caz Yokoyama Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20211106003714.17894-1-radhakrishna.sripada@intel.com --- drivers/gpu/drm/i915/display/intel_bw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 15c006194c859..abec394f6869e 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -147,7 +147,7 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, qi->num_points = dram_info->num_qgv_points; qi->num_psf_points = dram_info->num_psf_gv_points; - if (DISPLAY_VER(dev_priv) == 12) + if (DISPLAY_VER(dev_priv) >= 12) switch (dram_info->type) { case INTEL_DRAM_DDR4: qi->t_bl = is_y_tile ? 8 : 4; From 38a1b50c0389f1ae385d007b02dec5f812b3e5ef Mon Sep 17 00:00:00 2001 From: William Tseng Date: Tue, 9 Nov 2021 11:41:25 +0800 Subject: [PATCH 110/176] drm/i915/dsi: disable lpdt if it is not enabled Avoid setting LP_DATA_TRANSFER when enable_lpdt is false Cc: Ville Syrjala Cc: Jani Nikula Cc: Vandita Kulkarni Cc: Lee Shawn C Cc: Cooper Chiou Signed-off-by: William Tseng Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211109034125.11291-1-william.tseng@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 19167efae07ab..26fd35cb5921d 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -183,6 +183,8 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host, if (enable_lpdt) tmp |= LP_DATA_TRANSFER; + else + tmp &= ~LP_DATA_TRANSFER; tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK); tmp |= ((packet->header[0] & VC_MASK) << VC_SHIFT); From 6f9976bd1310d123921ba2c20e8c101057087285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 21 Oct 2021 01:33:37 +0300 Subject: [PATCH 111/176] drm/i915: Do vrr push before sampling the frame counter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do the vrr push before we sample the frame counter to know when the commit has been latched. Doing these in the wrong order could lead us to complete the flip before it has actually happened. Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211020223339.669-3-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 254e67141a776..0f8b48b6911cc 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -542,6 +542,9 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end); + /* Send VRR Push to terminate Vblank */ + intel_vrr_send_push(new_crtc_state); + /* * Incase of mipi dsi command mode, we need to set frame update * request for every commit. @@ -568,9 +571,6 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) local_irq_enable(); - /* Send VRR Push to terminate Vblank */ - intel_vrr_send_push(new_crtc_state); - if (intel_vgpu_active(dev_priv)) return; From 2bbc6fcaf8c58a7a59900512be11b1775a611381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 21 Oct 2021 01:33:38 +0300 Subject: [PATCH 112/176] drm/i915: Use vblank workers for gamma updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pipe gamma registers are single buffered so they should only be updated during the vblank to avoid screen tearing. In fact they really should only be updated between start of vblank and frame start because that is the only time the pipe is guaranteed to be empty. Already at frame start the pipe begins to fill up with data for the next frame. Unfortunately frame start happens ~1 scanline after the start of vblank which in practice doesn't always leave us enough time to finish the gamma update in time (gamma LUTs can be several KiB of data we have to bash into the registers). However we must try our best and so we'll add a vblank work for each pipe from where we can do the gamma update. Additionally we could consider pushing frame start forward to the max of ~4 scanlines after start of vblank. But not sure that's exactly a validated configuration. As it stands the ~100 first pixels tend to make it through with the old gamma values. Even though the vblank worker is running on a high prority thread we still have to contend with C-states. If the CPU happens be in a deep C-state when the vblank interrupt arrives even the irq handler gets delayed massively (I've observed dozens of scanlines worth of latency). To avoid that problem we'll use the qos mechanism to keep the CPU awake while the vblank work is scheduled. With all this hooked up we can finally enjoy near atomic gamma updates. It even works across several pipes from the same atomic commit which previously was a total fail because we did the gamma updates for each pipe serially after waiting for all pipes to have latched the double buffered registers. In the future the DSB should take over this responsibility which will hopefully avoid some of these issues. Kudos to Lyude for finishing the actual vblank workers. Works like the proverbial train toilet. v2: Add missing intel_atomic_state fwd declaration v3: Clean up properly when not scheduling the worker v4: Clean up the rest and add tracepoints v5: s/intel_wait_for_vblank_works/intel_wait_for_vblank_workers/ (Jani,Uma) CC: Lyude Paul Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211020223339.669-4-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_crtc.c | 76 ++++++++++++++++++- drivers/gpu/drm/i915/display/intel_crtc.h | 4 +- drivers/gpu/drm/i915/display/intel_display.c | 9 +-- .../drm/i915/display/intel_display_types.h | 8 ++ drivers/gpu/drm/i915/i915_trace.h | 42 ++++++++++ 5 files changed, 129 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 0f8b48b6911cc..f09df2cf052b8 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -3,12 +3,14 @@ * Copyright © 2020 Intel Corporation */ #include +#include #include #include #include #include #include +#include #include "i915_trace.h" #include "i915_vgpu.h" @@ -167,6 +169,8 @@ static void intel_crtc_destroy(struct drm_crtc *_crtc) { struct intel_crtc *crtc = to_intel_crtc(_crtc); + cpu_latency_qos_remove_request(&crtc->vblank_pm_qos); + drm_crtc_cleanup(&crtc->base); kfree(crtc); } @@ -344,6 +348,8 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) intel_crtc_crc_init(crtc); + cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE); + drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe); return 0; @@ -354,6 +360,65 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) return ret; } +static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->hw.active && + !intel_crtc_needs_modeset(crtc_state) && + !crtc_state->preload_luts && + (crtc_state->uapi.color_mgmt_changed || + crtc_state->update_pipe); +} + +static void intel_crtc_vblank_work(struct kthread_work *base) +{ + struct drm_vblank_work *work = to_drm_vblank_work(base); + struct intel_crtc_state *crtc_state = + container_of(work, typeof(*crtc_state), vblank_work); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + trace_intel_crtc_vblank_work_start(crtc); + + intel_color_load_luts(crtc_state); + + if (crtc_state->uapi.event) { + spin_lock_irq(&crtc->base.dev->event_lock); + drm_crtc_send_vblank_event(&crtc->base, crtc_state->uapi.event); + crtc_state->uapi.event = NULL; + spin_unlock_irq(&crtc->base.dev->event_lock); + } + + trace_intel_crtc_vblank_work_end(crtc); +} + +static void intel_crtc_vblank_work_init(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + drm_vblank_work_init(&crtc_state->vblank_work, &crtc->base, + intel_crtc_vblank_work); + /* + * Interrupt latency is critical for getting the vblank + * work executed as early as possible during the vblank. + */ + cpu_latency_qos_update_request(&crtc->vblank_pm_qos, 0); +} + +void intel_wait_for_vblank_workers(struct intel_atomic_state *state) +{ + struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + if (!intel_crtc_needs_vblank_work(crtc_state)) + continue; + + drm_vblank_work_flush(&crtc_state->vblank_work); + cpu_latency_qos_update_request(&crtc->vblank_pm_qos, + PM_QOS_DEFAULT_VALUE); + } +} + int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int usecs) { @@ -387,7 +452,7 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode) * until a subsequent call to intel_pipe_update_end(). That is done to * avoid random delays. */ -void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) +void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -402,6 +467,9 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) if (new_crtc_state->uapi.async_flip) return; + if (intel_crtc_needs_vblank_work(new_crtc_state)) + intel_crtc_vblank_work_init(new_crtc_state); + if (new_crtc_state->vrr.enable) vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state); else @@ -557,7 +625,11 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) * Would be slightly nice to just grab the vblank count and arm the * event outside of the critical section - the spinlock might spin for a * while ... */ - if (new_crtc_state->uapi.event) { + if (intel_crtc_needs_vblank_work(new_crtc_state)) { + drm_vblank_work_schedule(&new_crtc_state->vblank_work, + drm_crtc_accurate_vblank_count(&crtc->base) + 1, + false); + } else if (new_crtc_state->uapi.event) { drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc->base) != 0); diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h index 22363fbbc9255..a0039fdb1eb08 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.h +++ b/drivers/gpu/drm/i915/display/intel_crtc.h @@ -11,6 +11,7 @@ enum pipe; struct drm_display_mode; struct drm_i915_private; +struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; @@ -24,7 +25,8 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc); void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state); void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state); -void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); +void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state); void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); +void intel_wait_for_vblank_workers(struct intel_atomic_state *state); #endif diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4cd268ca52fbb..40efd5ad029a4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8689,6 +8689,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_set_cdclk_post_plane_update(state); } + intel_wait_for_vblank_workers(state); + /* FIXME: We should call drm_atomic_helper_commit_hw_done() here * already, but still need the state for the delayed optimization. To * fix this: @@ -8703,13 +8705,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->uapi.async_flip) intel_crtc_disable_flip_done(state, crtc); - - if (new_crtc_state->hw.active && - !intel_crtc_needs_modeset(new_crtc_state) && - !new_crtc_state->preload_luts && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe)) - intel_color_load_luts(new_crtc_state); } /* diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e4c3754501381..7771716a26ad6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include @@ -1237,6 +1239,9 @@ struct intel_crtc_state { u8 link_count; u8 pixel_overlap; } splitter; + + /* for loading single buffered registers during vblank */ + struct drm_vblank_work vblank_work; }; enum intel_pipe_crc_source { @@ -1321,6 +1326,9 @@ struct intel_crtc { /* scalers available on this crtc */ int num_scalers; + /* for loading single buffered registers during vblank */ + struct pm_qos_request vblank_pm_qos; + #ifdef CONFIG_DEBUG_FS struct intel_pipe_crc pipe_crc; #endif diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 214696d6b270f..9f00690ba0608 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -433,6 +433,48 @@ TRACE_EVENT(intel_fbc_nuke, /* pipe updates */ +TRACE_EVENT(intel_crtc_vblank_work_start, + TP_PROTO(struct intel_crtc *crtc), + TP_ARGS(crtc), + + TP_STRUCT__entry( + __field(enum pipe, pipe) + __field(u32, frame) + __field(u32, scanline) + ), + + TP_fast_assign( + __entry->pipe = crtc->pipe; + __entry->frame = intel_crtc_get_vblank_counter(crtc); + __entry->scanline = intel_get_crtc_scanline(crtc); + ), + + TP_printk("pipe %c, frame=%u, scanline=%u", + pipe_name(__entry->pipe), __entry->frame, + __entry->scanline) +); + +TRACE_EVENT(intel_crtc_vblank_work_end, + TP_PROTO(struct intel_crtc *crtc), + TP_ARGS(crtc), + + TP_STRUCT__entry( + __field(enum pipe, pipe) + __field(u32, frame) + __field(u32, scanline) + ), + + TP_fast_assign( + __entry->pipe = crtc->pipe; + __entry->frame = intel_crtc_get_vblank_counter(crtc); + __entry->scanline = intel_get_crtc_scanline(crtc); + ), + + TP_printk("pipe %c, frame=%u, scanline=%u", + pipe_name(__entry->pipe), __entry->frame, + __entry->scanline) +); + TRACE_EVENT(intel_pipe_update_start, TP_PROTO(struct intel_crtc *crtc), TP_ARGS(crtc), From 115e0f687d29649b8805e3417e089e785b0ea61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 21 Oct 2021 01:33:39 +0300 Subject: [PATCH 113/176] drm/i915: Use unlocked register accesses for LUT loads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have to bash in a lot of registers to load the higher precision LUT modes. The locking overhead is significant, especially as we have to get this done as quickly as possible during vblank. So let's switch to unlocked accesses for these. Fortunately the LUT registers are mostly spread around such that two pipes do not have any registers on the same cacheline. So as long as commits on the same pipe are serialized (which they are) we should get away with this without angering the hardware. The only exceptions are the PREC_PIPEGCMAX registers on ilk/snb which we don't use atm as they are only used in the 12bit gamma mode. If/when we add support for that we may need to remember to still serialize those registers, though I'm not sure ilk/snb are actually affected by the same cacheline issue. I think ivb/hsw at least were, but they use a different set of registers for the precision LUT. I have a test case which is updating the LUTs on two pipes from a single atomic commit. Running that in a loop for a minute I get the following worst case with the locks in place: intel_crtc_vblank_work_start: pipe B, frame=10037, scanline=1081 intel_crtc_vblank_work_start: pipe A, frame=12274, scanline=769 intel_crtc_vblank_work_end: pipe A, frame=12274, scanline=58 intel_crtc_vblank_work_end: pipe B, frame=10037, scanline=74 And here's the worst case with the locks removed: intel_crtc_vblank_work_start: pipe B, frame=5869, scanline=1081 intel_crtc_vblank_work_start: pipe A, frame=7616, scanline=769 intel_crtc_vblank_work_end: pipe B, frame=5869, scanline=1096 intel_crtc_vblank_work_end: pipe A, frame=7616, scanline=777 The test was done on a snb using the 10bit 1024 entry LUT mode. The vtotals for the two displays are 793 and 1125. So we can see that with the locks ripped out the LUT updates are pretty nicely confined within the vblank, whereas with the locks in place we're routinely blasting past the vblank end which causes visual artifacts near the top of the screen. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211020223339.669-5-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 128 ++++++++++----------- drivers/gpu/drm/i915/display/intel_dsb.c | 4 +- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 5359b7305a782..c870a0e50cb11 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -552,8 +552,8 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc, lut = blob->data; for (i = 0; i < 256; i++) - intel_de_write(dev_priv, PALETTE(pipe, i), - i9xx_lut_8(&lut[i])); + intel_de_write_fw(dev_priv, PALETTE(pipe, i), + i9xx_lut_8(&lut[i])); } static void i9xx_load_luts(const struct intel_crtc_state *crtc_state) @@ -576,15 +576,15 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc, enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size - 1; i++) { - intel_de_write(dev_priv, PALETTE(pipe, 2 * i + 0), - i965_lut_10p6_ldw(&lut[i])); - intel_de_write(dev_priv, PALETTE(pipe, 2 * i + 1), - i965_lut_10p6_udw(&lut[i])); + intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 0), + i965_lut_10p6_ldw(&lut[i])); + intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 1), + i965_lut_10p6_udw(&lut[i])); } - intel_de_write(dev_priv, PIPEGCMAX(pipe, 0), lut[i].red); - intel_de_write(dev_priv, PIPEGCMAX(pipe, 1), lut[i].green); - intel_de_write(dev_priv, PIPEGCMAX(pipe, 2), lut[i].blue); + intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 0), lut[i].red); + intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 1), lut[i].green); + intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 2), lut[i].blue); } static void i965_load_luts(const struct intel_crtc_state *crtc_state) @@ -618,8 +618,8 @@ static void ilk_load_lut_8(struct intel_crtc *crtc, lut = blob->data; for (i = 0; i < 256; i++) - intel_de_write(dev_priv, LGC_PALETTE(pipe, i), - i9xx_lut_8(&lut[i])); + intel_de_write_fw(dev_priv, LGC_PALETTE(pipe, i), + i9xx_lut_8(&lut[i])); } static void ilk_load_lut_10(struct intel_crtc *crtc, @@ -631,8 +631,8 @@ static void ilk_load_lut_10(struct intel_crtc *crtc, enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) - intel_de_write(dev_priv, PREC_PALETTE(pipe, i), - ilk_lut_10(&lut[i])); + intel_de_write_fw(dev_priv, PREC_PALETTE(pipe, i), + ilk_lut_10(&lut[i])); } static void ilk_load_luts(const struct intel_crtc_state *crtc_state) @@ -681,16 +681,16 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, const struct drm_color_lut *entry = &lut[i * (lut_size - 1) / (hw_lut_size - 1)]; - intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), prec_index++); - intel_de_write(dev_priv, PREC_PAL_DATA(pipe), - ilk_lut_10(entry)); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), prec_index++); + intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe), + ilk_lut_10(entry)); } /* * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); } /* On BDW+ the index auto increment mode actually works */ @@ -704,23 +704,23 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; - intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), - prec_index | PAL_PREC_AUTO_INCREMENT); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + prec_index | PAL_PREC_AUTO_INCREMENT); for (i = 0; i < hw_lut_size; i++) { /* We discard half the user entries in split gamma mode */ const struct drm_color_lut *entry = &lut[i * (lut_size - 1) / (hw_lut_size - 1)]; - intel_de_write(dev_priv, PREC_PAL_DATA(pipe), - ilk_lut_10(entry)); + intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe), + ilk_lut_10(entry)); } /* * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); } static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) @@ -821,9 +821,9 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); - intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT); for (i = 0; i < lut_size; i++) { /* @@ -839,15 +839,15 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), + lut[i].green); } /* Clamp values > 1.0. */ while (i++ < 35) - intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16); - intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); } static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_state) @@ -862,21 +862,21 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); - intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT); for (i = 0; i < lut_size; i++) { u32 v = (i << 16) / (lut_size - 1); - intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), v); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), v); } /* Clamp values > 1.0. */ while (i++ < 35) - intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16); - intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); } static void glk_load_luts(const struct intel_crtc_state *crtc_state) @@ -1071,10 +1071,10 @@ static void chv_load_cgm_degamma(struct intel_crtc *crtc, enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0), - chv_cgm_degamma_ldw(&lut[i])); - intel_de_write(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1), - chv_cgm_degamma_udw(&lut[i])); + intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0), + chv_cgm_degamma_ldw(&lut[i])); + intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1), + chv_cgm_degamma_udw(&lut[i])); } } @@ -1105,10 +1105,10 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc, enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0), - chv_cgm_gamma_ldw(&lut[i])); - intel_de_write(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1), - chv_cgm_gamma_udw(&lut[i])); + intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0), + chv_cgm_gamma_ldw(&lut[i])); + intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1), + chv_cgm_gamma_udw(&lut[i])); } } @@ -1131,8 +1131,8 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state) else i965_load_luts(crtc_state); - intel_de_write(dev_priv, CGM_PIPE_MODE(crtc->pipe), - crtc_state->cgm_mode); + intel_de_write_fw(dev_priv, CGM_PIPE_MODE(crtc->pipe), + crtc_state->cgm_mode); } void intel_color_load_luts(const struct intel_crtc_state *crtc_state) @@ -1808,7 +1808,7 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < LEGACY_LUT_LENGTH; i++) { - u32 val = intel_de_read(dev_priv, PALETTE(pipe, i)); + u32 val = intel_de_read_fw(dev_priv, PALETTE(pipe, i)); i9xx_lut_8_pack(&lut[i], val); } @@ -1843,15 +1843,15 @@ static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < lut_size - 1; i++) { - u32 ldw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0)); - u32 udw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1)); + u32 ldw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 0)); + u32 udw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 1)); i965_lut_10p6_pack(&lut[i], ldw, udw); } - lut[i].red = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 0))); - lut[i].green = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 1))); - lut[i].blue = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 2))); + lut[i].red = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 0))); + lut[i].green = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 1))); + lut[i].blue = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 2))); return blob; } @@ -1886,8 +1886,8 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < lut_size; i++) { - u32 ldw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0)); - u32 udw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1)); + u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0)); + u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1)); chv_cgm_gamma_pack(&lut[i], ldw, udw); } @@ -1922,7 +1922,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < LEGACY_LUT_LENGTH; i++) { - u32 val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i)); + u32 val = intel_de_read_fw(dev_priv, LGC_PALETTE(pipe, i)); i9xx_lut_8_pack(&lut[i], val); } @@ -1947,7 +1947,7 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < lut_size; i++) { - u32 val = intel_de_read(dev_priv, PREC_PALETTE(pipe, i)); + u32 val = intel_de_read_fw(dev_priv, PREC_PALETTE(pipe, i)); ilk_lut_10_pack(&lut[i], val); } @@ -1999,16 +1999,16 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, lut = blob->data; - intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), - prec_index | PAL_PREC_AUTO_INCREMENT); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + prec_index | PAL_PREC_AUTO_INCREMENT); for (i = 0; i < lut_size; i++) { - u32 val = intel_de_read(dev_priv, PREC_PAL_DATA(pipe)); + u32 val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe)); ilk_lut_10_pack(&lut[i], val); } - intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); return blob; } @@ -2050,17 +2050,17 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) lut = blob->data; - intel_de_write(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT); for (i = 0; i < 9; i++) { - u32 ldw = intel_de_read(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe)); - u32 udw = intel_de_read(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe)); + u32 ldw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe)); + u32 udw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe)); icl_lut_multi_seg_pack(&lut[i], ldw, udw); } - intel_de_write(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); /* * FIXME readouts from PAL_PREC_DATA register aren't giving diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 62a8a69f9f5d2..83a69a4a4fea8 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -100,7 +100,7 @@ void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, u32 reg_val; if (!dsb) { - intel_de_write(dev_priv, reg, val); + intel_de_write_fw(dev_priv, reg, val); return; } buf = dsb->cmd_buf; @@ -177,7 +177,7 @@ void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, dsb = crtc_state->dsb; if (!dsb) { - intel_de_write(dev_priv, reg, val); + intel_de_write_fw(dev_priv, reg, val); return; } From c68dac968c460b89a4f6e3617ee5defbcd96eead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 5 Nov 2021 23:21:56 +0200 Subject: [PATCH 114/176] drm/i915: Call intel_update_active_dpll() for both bigjoiner pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we're only calling intel_update_active_dpll() for the bigjoiner master pipe but not for the slave. With TC ports this leads to the two pipes end up trying to use different PLLs (TC vs. TBT). What's worse we're enabling the PLL that didn't get intel_update_active_dpll() called on it at the spot where we need the clocks turned on. So we turn on the wrong PLL and the DDI is now trying to source its clock from the other PLL which is still disabled. Naturally that doesn't end so well and the DDI fails to start up. The state checker also gets a bit unhappy (which is a good thing) when it notices that one of the pipes was using the wrong PLL. Let's fix this by remembering to call intel_update_active_dpll() for both pipes. That should get the correct PLL turned on when we need it, and the state checker should also be happy. Cc: Imre Deak Cc: Manasi Navare Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4434 Fixes: e12d6218fda2 ("drm/i915: Reduce bigjoiner special casing") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211105212156.5697-1-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 145d51ac43a39..f9e7e3d1c7d0e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3140,8 +3140,14 @@ intel_ddi_update_prepare(struct intel_atomic_state *state, intel_tc_port_get_link(enc_to_dig_port(encoder), required_lanes); - if (crtc_state && crtc_state->hw.active) + if (crtc_state && crtc_state->hw.active) { + struct intel_crtc *slave_crtc = crtc_state->bigjoiner_linked_crtc; + intel_update_active_dpll(state, crtc, encoder); + + if (slave_crtc) + intel_update_active_dpll(state, slave_crtc, encoder); + } } static void From 6cff894e4991a5e80324ba39369288fad1e3ed1a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Nov 2021 14:48:50 +0300 Subject: [PATCH 115/176] drm/i915: pin: delete duplicate check in intel_pin_and_fence_fb_obj() The "ret" variable is checked on the previous line so we know it's zero. No need to check again. Signed-off-by: Dan Carpenter Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20211109114850.GB16587@kili --- drivers/gpu/drm/i915/display/intel_fb_pin.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index 3f77f30135845..3b20f69e02401 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -142,13 +142,11 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, if (ret) goto err; - if (!ret) { - vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment, - view, pinctl); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto err_unpin; - } + vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment, + view, pinctl); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err_unpin; } if (uses_fence && i915_vma_is_map_and_fenceable(vma)) { From 4579509ef181480f4e4510d436c691519167c5c2 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 9 Nov 2021 17:34:28 +0530 Subject: [PATCH 116/176] Revert "drm/i915/tgl/dsi: Gate the ddi clocks after pll mapping" This reverts commit 991d9557b0c4 ("drm/i915/tgl/dsi: Gate the ddi clocks after pll mapping"). The Bspec was updated recently with the pll ungate sequence similar to that of icl dsi enable sequence. Hence reverting. Bspec: 49187 Fixes: 991d9557b0c4 ("drm/i915/tgl/dsi: Gate the ddi clocks after pll mapping") Cc: # v5.4+ Signed-off-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211109120428.15211-1-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 26fd35cb5921d..c05fb861f10c6 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -698,10 +698,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); for_each_dsi_phy(phy, intel_dsi->phys) { - if (DISPLAY_VER(dev_priv) >= 12) - val |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); - else - val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); } intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); @@ -1137,8 +1134,6 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - /* step 4a: power up all lanes of the DDI used by DSI */ gen11_dsi_power_up_lanes(encoder); @@ -1164,8 +1159,7 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, gen11_dsi_configure_transcoder(encoder, crtc_state); /* Step 4l: Gate DDI clocks */ - if (DISPLAY_VER(dev_priv) == 11) - gen11_dsi_gate_clocks(encoder); + gen11_dsi_gate_clocks(encoder); } static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) From 078e2bb2585a05df787be74642f12354a66a0534 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Wed, 10 Nov 2021 12:59:46 +0530 Subject: [PATCH 117/176] drm/i915/dp: Optimize the FRL configuration for HDMI2.1 PCON Currently the HDMI2.1 PCON's frl link config DPCD registers are reset and configured even if they are already configured. Also the HDMI Link Mode does not settle to FRL MODE immediately after HDMI Link Status is active. This patch: -Checks if the PCON is already configured for FRL. -Include HDMI Link Mode in wait for loop along with HDMI Link status DPCD. v2: Rebase Signed-off-by: Ankit Nautiyal Reviewed-by: Uma Shankar Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20211110072947.171659-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 37 +++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6d5988f0f067c..f5fd106e555c9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2198,6 +2198,18 @@ static int intel_dp_hdmi_sink_max_frl(struct intel_dp *intel_dp) return max_frl_rate; } +static bool +intel_dp_pcon_is_frl_trained(struct intel_dp *intel_dp, + u8 max_frl_bw_mask, u8 *frl_trained_mask) +{ + if (drm_dp_pcon_hdmi_link_active(&intel_dp->aux) && + drm_dp_pcon_hdmi_link_mode(&intel_dp->aux, frl_trained_mask) == DP_PCON_HDMI_MODE_FRL && + *frl_trained_mask >= max_frl_bw_mask) + return true; + + return false; +} + static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) { #define TIMEOUT_FRL_READY_MS 500 @@ -2208,10 +2220,6 @@ static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) u8 max_frl_bw_mask = 0, frl_trained_mask; bool is_active; - ret = drm_dp_pcon_reset_frl_config(&intel_dp->aux); - if (ret < 0) - return ret; - max_pcon_frl_bw = intel_dp->dfp.pcon_max_frl_bw; drm_dbg(&i915->drm, "PCON max rate = %d Gbps\n", max_pcon_frl_bw); @@ -2223,6 +2231,12 @@ static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) if (max_frl_bw <= 0) return -EINVAL; + max_frl_bw_mask = intel_dp_pcon_set_frl_mask(max_frl_bw); + drm_dbg(&i915->drm, "MAX_FRL_BW_MASK = %u\n", max_frl_bw_mask); + + if (intel_dp_pcon_is_frl_trained(intel_dp, max_frl_bw_mask, &frl_trained_mask)) + goto frl_trained; + ret = drm_dp_pcon_frl_prepare(&intel_dp->aux, false); if (ret < 0) return ret; @@ -2232,7 +2246,6 @@ static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) if (!is_active) return -ETIMEDOUT; - max_frl_bw_mask = intel_dp_pcon_set_frl_mask(max_frl_bw); ret = drm_dp_pcon_frl_configure_1(&intel_dp->aux, max_frl_bw, DP_PCON_ENABLE_SEQUENTIAL_LINK); if (ret < 0) @@ -2248,19 +2261,15 @@ static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) * Wait for FRL to be completed * Check if the HDMI Link is up and active. */ - wait_for(is_active = drm_dp_pcon_hdmi_link_active(&intel_dp->aux) == true, TIMEOUT_HDMI_LINK_ACTIVE_MS); + wait_for(is_active = + intel_dp_pcon_is_frl_trained(intel_dp, max_frl_bw_mask, &frl_trained_mask), + TIMEOUT_HDMI_LINK_ACTIVE_MS); if (!is_active) return -ETIMEDOUT; - /* Verify HDMI Link configuration shows FRL Mode */ - if (drm_dp_pcon_hdmi_link_mode(&intel_dp->aux, &frl_trained_mask) != - DP_PCON_HDMI_MODE_FRL) { - drm_dbg(&i915->drm, "HDMI couldn't be trained in FRL Mode\n"); - return -EINVAL; - } - drm_dbg(&i915->drm, "MAX_FRL_MASK = %u, FRL_TRAINED_MASK = %u\n", max_frl_bw_mask, frl_trained_mask); - +frl_trained: + drm_dbg(&i915->drm, "FRL_TRAINED_MASK = %u\n", frl_trained_mask); intel_dp->frl.trained_rate_gbps = intel_dp_pcon_get_frl_mask(frl_trained_mask); intel_dp->frl.is_trained = true; drm_dbg(&i915->drm, "FRL trained with : %d Gbps\n", intel_dp->frl.trained_rate_gbps); From f35294e13c19bf890f26bc1ec964b2d29c82f0ec Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Wed, 10 Nov 2021 12:59:47 +0530 Subject: [PATCH 118/176] drm/i915/dp: For PCON TMDS mode set only the relavant bits in config DPCD Currently we reset the whole PCON linkConfig DPCD to set the TMDS mode. This also resets the Source control bit and HDMI link enable bit and goes to autonomous mode of operation, which is seen to spoil the PCONs internal state. This patch avoids resetting the PCON link config register and sets only the source control bit, with FRL Enable bit set to 0 (TMDS mode) in the configuration DPCD. It then enables the HDMI Link Enable bit. v2: Removed the redundant resetting of the bits as the buffer is already initialized to 0. (Uma) Updated comments and commit message. v3: Rebase Signed-off-by: Ankit Nautiyal Reviewed-by: Uma Shankar Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20211110072947.171659-3-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f5fd106e555c9..a0ff16bc18f56 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2287,6 +2287,28 @@ static bool intel_dp_is_hdmi_2_1_sink(struct intel_dp *intel_dp) return false; } +static +int intel_dp_pcon_set_tmds_mode(struct intel_dp *intel_dp) +{ + int ret; + u8 buf = 0; + + /* Set PCON source control mode */ + buf |= DP_PCON_ENABLE_SOURCE_CTL_MODE; + + ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + if (ret < 0) + return ret; + + /* Set HDMI LINK ENABLE */ + buf |= DP_PCON_ENABLE_HDMI_LINK; + ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + if (ret < 0) + return ret; + + return 0; +} + void intel_dp_check_frl_training(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -2305,7 +2327,7 @@ void intel_dp_check_frl_training(struct intel_dp *intel_dp) int ret, mode; drm_dbg(&dev_priv->drm, "Couldn't set FRL mode, continuing with TMDS mode\n"); - ret = drm_dp_pcon_reset_frl_config(&intel_dp->aux); + ret = intel_dp_pcon_set_tmds_mode(intel_dp); mode = drm_dp_pcon_hdmi_link_mode(&intel_dp->aux, NULL); if (ret < 0 || mode != DP_PCON_HDMI_MODE_TMDS) From d1260be706752dc01699b72222bbba48f42adabf Mon Sep 17 00:00:00 2001 From: William Tseng Date: Wed, 10 Nov 2021 09:02:17 +0800 Subject: [PATCH 119/176] drm/i915/dsi: transmit brightness command in HS state In Video Mode, if DSI transcoder is set to transmit packets in LP Escape mode, screen flickering would be obseved when brightness commands are continuously and quickly transmitted to a panel. The problem may be resolved by changing the mode to transmit packets from Low Power to HS. Cc: Ville Syrjala Cc: Jani Nikula Cc: Vandita Kulkarni Cc: Lee Shawn C Cc: Cooper Chiou Signed-off-by: William Tseng Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211110010217.26759-1-william.tseng@intel.com --- drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c b/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c index f61ed82e88671..7d234429e71ef 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c @@ -71,6 +71,7 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 u8 data[2] = {}; enum port port; size_t len = panel->backlight.max > U8_MAX ? 2 : 1; + unsigned long mode_flags; if (len == 1) { data[0] = level; @@ -81,8 +82,11 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) { dsi_device = intel_dsi->dsi_hosts[port]->device; + mode_flags = dsi_device->mode_flags; + dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM; mipi_dsi_dcs_write(dsi_device, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, &data, len); + dsi_device->mode_flags = mode_flags; } } From b50364af7af47bd2107394b8faabffab59329af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:04 +0200 Subject: [PATCH 120/176] drm/i915/fbc: Extract snb_fbc_program_fence() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have two identical copies of the snb+ system agent CPU fence programming code. Extract into a helper. Also there's no real point in insisting that we program 0 into DPFC_CPU_FENCE_OFFSET when the fence is disabled. So just always stick the computed Y offset there whether or not the fence is actually used or not. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-2-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 39 ++++++++++++------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 834eb4cc7c105..6bd952a379015 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -307,6 +307,18 @@ static void intel_fbc_recompress(struct drm_i915_private *dev_priv) i8xx_fbc_recompress(dev_priv); } +static void snb_fbc_program_fence(struct drm_i915_private *i915) +{ + const struct intel_fbc_reg_params *params = &i915->fbc.params; + u32 ctl = 0; + + if (params->fence_id >= 0) + ctl = SNB_CPU_FENCE_ENABLE | params->fence_id; + + intel_de_write(i915, SNB_DPFC_CTL_SA, ctl); + intel_de_write(i915, DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); +} + static void ilk_fbc_activate(struct drm_i915_private *dev_priv) { struct intel_fbc_reg_params *params = &dev_priv->fbc.params; @@ -320,19 +332,11 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) dpfc_ctl |= DPFC_CTL_FENCE_EN; if (IS_IRONLAKE(dev_priv)) dpfc_ctl |= params->fence_id; - if (IS_SANDYBRIDGE(dev_priv)) { - intel_de_write(dev_priv, SNB_DPFC_CTL_SA, - SNB_CPU_FENCE_ENABLE | params->fence_id); - intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, - params->fence_y_offset); - } - } else { - if (IS_SANDYBRIDGE(dev_priv)) { - intel_de_write(dev_priv, SNB_DPFC_CTL_SA, 0); - intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 0); - } } + if (IS_SANDYBRIDGE(dev_priv)) + snb_fbc_program_fence(dev_priv); + intel_de_write(dev_priv, ILK_DPFC_FENCE_YOFF, params->fence_y_offset); /* enable it... */ @@ -389,20 +393,15 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv); - if (params->fence_id >= 0) { + if (params->fence_id >= 0) dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; - intel_de_write(dev_priv, SNB_DPFC_CTL_SA, - SNB_CPU_FENCE_ENABLE | params->fence_id); - intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, - params->fence_y_offset); - } else if (dev_priv->ggtt.num_fences) { - intel_de_write(dev_priv, SNB_DPFC_CTL_SA, 0); - intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 0); - } if (dev_priv->fbc.false_color) dpfc_ctl |= FBC_CTL_FALSE_COLOR; + if (dev_priv->ggtt.num_fences) + snb_fbc_program_fence(dev_priv); + intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); } From 2013ab184971c4a92c42f2bc401163e5b105abf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:05 +0200 Subject: [PATCH 121/176] drm/i915/fbc: Extract {skl,glk}_fbc_program_cfb_stride() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declutter gen7_fbc_activate() by sucking the override stride programming stuff into helpers. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-3-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 51 +++++++++++++++--------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 6bd952a379015..c95a32f1985a5 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -360,32 +360,45 @@ static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv) return intel_de_read(dev_priv, ILK_DPFC_CONTROL) & DPFC_CTL_EN; } -static void gen7_fbc_activate(struct drm_i915_private *dev_priv) +static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_reg_params *params = &fbc->params; - u32 dpfc_ctl; + u32 val = 0; - if (DISPLAY_VER(dev_priv) >= 10) { - u32 val = 0; + if (params->override_cfb_stride) + val |= FBC_STRIDE_OVERRIDE | + FBC_STRIDE(params->override_cfb_stride / fbc->limit); - if (params->override_cfb_stride) - val |= FBC_STRIDE_OVERRIDE | - FBC_STRIDE(params->override_cfb_stride / fbc->limit); + intel_de_write(i915, GLK_FBC_STRIDE, val); +} - intel_de_write(dev_priv, GLK_FBC_STRIDE, val); - } else if (DISPLAY_VER(dev_priv) == 9) { - u32 val = 0; +static void skl_fbc_program_cfb_stride(struct drm_i915_private *i915) +{ + struct intel_fbc *fbc = &i915->fbc; + const struct intel_fbc_reg_params *params = &fbc->params; + u32 val = 0; - /* Display WA #0529: skl, kbl, bxt. */ - if (params->override_cfb_stride) - val |= CHICKEN_FBC_STRIDE_OVERRIDE | - CHICKEN_FBC_STRIDE(params->override_cfb_stride / fbc->limit); + /* Display WA #0529: skl, kbl, bxt. */ + if (params->override_cfb_stride) + val |= CHICKEN_FBC_STRIDE_OVERRIDE | + CHICKEN_FBC_STRIDE(params->override_cfb_stride / fbc->limit); - intel_de_rmw(dev_priv, CHICKEN_MISC_4, - CHICKEN_FBC_STRIDE_OVERRIDE | - CHICKEN_FBC_STRIDE_MASK, val); - } + intel_de_rmw(i915, CHICKEN_MISC_4, + CHICKEN_FBC_STRIDE_OVERRIDE | + CHICKEN_FBC_STRIDE_MASK, val); +} + +static void gen7_fbc_activate(struct drm_i915_private *dev_priv) +{ + struct intel_fbc *fbc = &dev_priv->fbc; + const struct intel_fbc_reg_params *params = &fbc->params; + u32 dpfc_ctl; + + if (DISPLAY_VER(dev_priv) >= 10) + glk_fbc_program_cfb_stride(dev_priv); + else if (DISPLAY_VER(dev_priv) == 9) + skl_fbc_program_cfb_stride(dev_priv); dpfc_ctl = 0; if (IS_IVYBRIDGE(dev_priv)) From ef9600ffd447ca3da6660b1f5932179a67292e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:06 +0200 Subject: [PATCH 122/176] drm/i915/fbc: Just use params->fence_y_offset always MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to tiptoe around programming DPFC_FENCE_YOFF with params->fence_y_offset vs. 0. If the fence is not enabled it doesn't even matter what we program here. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-4-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index c95a32f1985a5..8f51af2b4ebc0 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -235,13 +235,11 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv); - if (params->fence_id >= 0) { + if (params->fence_id >= 0) dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fence_id; - intel_de_write(dev_priv, DPFC_FENCE_YOFF, - params->fence_y_offset); - } else { - intel_de_write(dev_priv, DPFC_FENCE_YOFF, 0); - } + + intel_de_write(dev_priv, DPFC_FENCE_YOFF, + params->fence_y_offset); /* enable it... */ intel_de_write(dev_priv, DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); From 74e0457a62c697d388b832b0a52dd1e716204019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:07 +0200 Subject: [PATCH 123/176] drm/i915/fbc: Introduce intel_fbc_is_compressing() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the direct FBC status register reads from the debugfs code behind an abstract api. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-5-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- .../drm/i915/display/intel_display_debugfs.c | 23 +++--------- drivers/gpu/drm/i915/display/intel_fbc.c | 36 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fbc.h | 1 + 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index d7d6dde518a31..19bc148e168ce 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -52,27 +52,12 @@ static int i915_fbc_status(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); mutex_lock(&fbc->lock); - if (intel_fbc_is_active(dev_priv)) + if (intel_fbc_is_active(dev_priv)) { seq_puts(m, "FBC enabled\n"); - else + seq_printf(m, "Compressing: %s\n", + yesno(intel_fbc_is_compressing(dev_priv))); + } else { seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); - - if (intel_fbc_is_active(dev_priv)) { - u32 mask; - - if (DISPLAY_VER(dev_priv) >= 8) - mask = intel_de_read(dev_priv, IVB_FBC_STATUS2) & BDW_FBC_COMP_SEG_MASK; - else if (DISPLAY_VER(dev_priv) >= 7) - mask = intel_de_read(dev_priv, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; - else if (DISPLAY_VER(dev_priv) >= 5) - mask = intel_de_read(dev_priv, ILK_DPFC_STATUS) & ILK_DPFC_COMP_SEG_MASK; - else if (IS_G4X(dev_priv)) - mask = intel_de_read(dev_priv, DPFC_STATUS) & DPFC_COMP_SEG_MASK; - else - mask = intel_de_read(dev_priv, FBC_STATUS) & - (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); - - seq_printf(m, "Compressing: %s\n", yesno(mask)); } mutex_unlock(&fbc->lock); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 8f51af2b4ebc0..4d7b156e46dbd 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -211,6 +211,12 @@ static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv) return intel_de_read(dev_priv, FBC_CONTROL) & FBC_CTL_EN; } +static bool i8xx_fbc_is_compressing(struct drm_i915_private *i915) +{ + return intel_de_read(i915, FBC_STATUS) & + (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); +} + static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) { switch (i915->fbc.limit) { @@ -262,6 +268,11 @@ static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv) return intel_de_read(dev_priv, DPFC_CONTROL) & DPFC_CTL_EN; } +static bool g4x_fbc_is_compressing(struct drm_i915_private *i915) +{ + return intel_de_read(i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; +} + static void i8xx_fbc_recompress(struct drm_i915_private *dev_priv) { struct intel_fbc_reg_params *params = &dev_priv->fbc.params; @@ -358,6 +369,11 @@ static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv) return intel_de_read(dev_priv, ILK_DPFC_CONTROL) & DPFC_CTL_EN; } +static bool ilk_fbc_is_compressing(struct drm_i915_private *i915) +{ + return intel_de_read(i915, ILK_DPFC_STATUS) & ILK_DPFC_COMP_SEG_MASK; +} + static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) { struct intel_fbc *fbc = &i915->fbc; @@ -416,6 +432,14 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); } +static bool gen7_fbc_is_compressing(struct drm_i915_private *i915) +{ + if (DISPLAY_VER(i915) >= 8) + return intel_de_read(i915, IVB_FBC_STATUS2) & BDW_FBC_COMP_SEG_MASK; + else + return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; +} + static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) { if (DISPLAY_VER(dev_priv) >= 5) @@ -461,6 +485,18 @@ static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv) i8xx_fbc_deactivate(dev_priv); } +bool intel_fbc_is_compressing(struct drm_i915_private *i915) +{ + if (DISPLAY_VER(i915) >= 7) + return gen7_fbc_is_compressing(i915); + else if (DISPLAY_VER(i915) >= 5) + return ilk_fbc_is_compressing(i915); + else if (IS_G4X(i915)) + return g4x_fbc_is_compressing(i915); + else + return i8xx_fbc_is_compressing(i915); +} + /** * intel_fbc_is_active - Is FBC active? * @dev_priv: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index b97d908738e62..b2c9e441edbdc 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -19,6 +19,7 @@ struct intel_plane_state; void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, struct intel_atomic_state *state); bool intel_fbc_is_active(struct drm_i915_private *dev_priv); +bool intel_fbc_is_compressing(struct drm_i915_private *dev_priv); bool intel_fbc_pre_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_atomic_state *state, From 6874f95816da4af4eb6a395ae434b823c4d7d356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:08 +0200 Subject: [PATCH 124/176] drm/i915/fbc: Extract helpers to compute FBC control register values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declutter the *_fbc_activate() functions by pulling all the control register value computations into helpers. I left the enable bit in *_fbc_activate() in the hopes of maybe using the helpers in the *_fbc_deactivate() paths as well instead of the current rmw approach. That won't be possible at least quite yet since we clobber the fbc->params before deactivating FBC so we could end up changing some of the values live, which given FBC's lack of/poor double buffering would likely not go so well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-6-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 148 +++++++++++++---------- 1 file changed, 87 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 4d7b156e46dbd..fbb96f6aaacd9 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -142,6 +142,48 @@ static unsigned int intel_fbc_cfb_size(struct drm_i915_private *dev_priv, return lines * intel_fbc_cfb_stride(dev_priv, cache); } +static u32 i8xx_fbc_ctl(struct drm_i915_private *i915) +{ + struct intel_fbc *fbc = &i915->fbc; + const struct intel_fbc_reg_params *params = &fbc->params; + unsigned int cfb_stride; + u32 fbc_ctl; + + cfb_stride = params->cfb_stride / fbc->limit; + + /* FBC_CTL wants 32B or 64B units */ + if (DISPLAY_VER(i915) == 2) + cfb_stride = (cfb_stride / 32) - 1; + else + cfb_stride = (cfb_stride / 64) - 1; + + fbc_ctl = FBC_CTL_PERIODIC | + FBC_CTL_INTERVAL(params->interval) | + FBC_CTL_STRIDE(cfb_stride); + + if (IS_I945GM(i915)) + fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ + + if (params->fence_id >= 0) + fbc_ctl |= FBC_CTL_FENCENO(params->fence_id); + + return fbc_ctl; +} + +static u32 i965_fbc_ctl2(struct drm_i915_private *i915) +{ + const struct intel_fbc_reg_params *params = &i915->fbc.params; + u32 fbc_ctl2; + + fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | + FBC_CTL_PLANE(params->crtc.i9xx_plane); + + if (params->fence_id >= 0) + fbc_ctl2 |= FBC_CTL_CPU_FENCE; + + return fbc_ctl2; +} + static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 fbc_ctl; @@ -166,44 +208,21 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) { struct intel_fbc *fbc = &dev_priv->fbc; const struct intel_fbc_reg_params *params = &fbc->params; - int cfb_pitch; int i; - u32 fbc_ctl; - - cfb_pitch = params->cfb_stride / fbc->limit; - - /* FBC_CTL wants 32B or 64B units */ - if (DISPLAY_VER(dev_priv) == 2) - cfb_pitch = (cfb_pitch / 32) - 1; - else - cfb_pitch = (cfb_pitch / 64) - 1; /* Clear old tags */ for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) intel_de_write(dev_priv, FBC_TAG(i), 0); if (DISPLAY_VER(dev_priv) == 4) { - u32 fbc_ctl2; - - /* Set it up... */ - fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM; - fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.i9xx_plane); - if (params->fence_id >= 0) - fbc_ctl2 |= FBC_CTL_CPU_FENCE; - intel_de_write(dev_priv, FBC_CONTROL2, fbc_ctl2); + intel_de_write(dev_priv, FBC_CONTROL2, + i965_fbc_ctl2(dev_priv)); intel_de_write(dev_priv, FBC_FENCE_OFF, params->fence_y_offset); } - /* enable it... */ - fbc_ctl = FBC_CTL_INTERVAL(params->interval); - fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC; - if (IS_I945GM(dev_priv)) - fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ - fbc_ctl |= FBC_CTL_STRIDE(cfb_pitch & 0xff); - if (params->fence_id >= 0) - fbc_ctl |= FBC_CTL_FENCENO(params->fence_id); - intel_de_write(dev_priv, FBC_CONTROL, fbc_ctl); + intel_de_write(dev_priv, FBC_CONTROL, + FBC_CTL_EN | i8xx_fbc_ctl(dev_priv)); } static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv) @@ -232,23 +251,36 @@ static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) } } -static void g4x_fbc_activate(struct drm_i915_private *dev_priv) +static u32 g4x_dpfc_ctl(struct drm_i915_private *i915) { - struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + const struct intel_fbc_reg_params *params = &i915->fbc.params; u32 dpfc_ctl; - dpfc_ctl = DPFC_CTL_PLANE(params->crtc.i9xx_plane) | DPFC_SR_EN; + dpfc_ctl = g4x_dpfc_ctl_limit(i915) | + DPFC_CTL_PLANE(params->crtc.i9xx_plane); - dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv); + if (IS_G4X(i915)) + dpfc_ctl |= DPFC_SR_EN; - if (params->fence_id >= 0) - dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fence_id; + if (params->fence_id >= 0) { + dpfc_ctl |= DPFC_CTL_FENCE_EN; + + if (DISPLAY_VER(i915) < 6) + dpfc_ctl |= params->fence_id; + } + + return dpfc_ctl; +} + +static void g4x_fbc_activate(struct drm_i915_private *dev_priv) +{ + const struct intel_fbc_reg_params *params = &dev_priv->fbc.params; intel_de_write(dev_priv, DPFC_FENCE_YOFF, params->fence_y_offset); - /* enable it... */ - intel_de_write(dev_priv, DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + intel_de_write(dev_priv, DPFC_CONTROL, + DPFC_CTL_EN | g4x_dpfc_ctl(dev_priv)); } static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv) @@ -331,25 +363,15 @@ static void snb_fbc_program_fence(struct drm_i915_private *i915) static void ilk_fbc_activate(struct drm_i915_private *dev_priv) { struct intel_fbc_reg_params *params = &dev_priv->fbc.params; - u32 dpfc_ctl; - - dpfc_ctl = DPFC_CTL_PLANE(params->crtc.i9xx_plane); - - dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv); - - if (params->fence_id >= 0) { - dpfc_ctl |= DPFC_CTL_FENCE_EN; - if (IS_IRONLAKE(dev_priv)) - dpfc_ctl |= params->fence_id; - } if (IS_SANDYBRIDGE(dev_priv)) snb_fbc_program_fence(dev_priv); intel_de_write(dev_priv, ILK_DPFC_FENCE_YOFF, params->fence_y_offset); - /* enable it... */ - intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + + intel_de_write(dev_priv, ILK_DPFC_CONTROL, + DPFC_CTL_EN | g4x_dpfc_ctl(dev_priv)); } static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv) @@ -403,33 +425,37 @@ static void skl_fbc_program_cfb_stride(struct drm_i915_private *i915) CHICKEN_FBC_STRIDE_MASK, val); } -static void gen7_fbc_activate(struct drm_i915_private *dev_priv) +static u32 gen7_dpfc_ctl(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; - const struct intel_fbc_reg_params *params = &fbc->params; + const struct intel_fbc_reg_params *params = &i915->fbc.params; u32 dpfc_ctl; - if (DISPLAY_VER(dev_priv) >= 10) - glk_fbc_program_cfb_stride(dev_priv); - else if (DISPLAY_VER(dev_priv) == 9) - skl_fbc_program_cfb_stride(dev_priv); + dpfc_ctl = g4x_dpfc_ctl_limit(i915); - dpfc_ctl = 0; - if (IS_IVYBRIDGE(dev_priv)) + if (IS_IVYBRIDGE(i915)) dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.i9xx_plane); - dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv); - if (params->fence_id >= 0) dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; - if (dev_priv->fbc.false_color) + if (i915->fbc.false_color) dpfc_ctl |= FBC_CTL_FALSE_COLOR; + return dpfc_ctl; +} + +static void gen7_fbc_activate(struct drm_i915_private *dev_priv) +{ + if (DISPLAY_VER(dev_priv) >= 10) + glk_fbc_program_cfb_stride(dev_priv); + else if (DISPLAY_VER(dev_priv) == 9) + skl_fbc_program_cfb_stride(dev_priv); + if (dev_priv->ggtt.num_fences) snb_fbc_program_fence(dev_priv); - intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + intel_de_write(dev_priv, ILK_DPFC_CONTROL, + DPFC_CTL_EN | gen7_dpfc_ctl(dev_priv)); } static bool gen7_fbc_is_compressing(struct drm_i915_private *i915) From 41b85a5202b775ce7eece34648a4b592ed18f5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:09 +0200 Subject: [PATCH 125/176] drm/i915/fbc: Introduce intel_fbc_funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the "if-ladders everywhere" approach with vfuncs. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-7-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 80 +++++++++++++++--------- drivers/gpu/drm/i915/i915_drv.h | 3 + 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index fbb96f6aaacd9..a2e09b6d21c73 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -48,6 +48,13 @@ #include "intel_fbc.h" #include "intel_frontbuffer.h" +struct intel_fbc_funcs { + void (*activate)(struct drm_i915_private *i915); + void (*deactivate)(struct drm_i915_private *i915); + bool (*is_active)(struct drm_i915_private *i915); + bool (*is_compressing)(struct drm_i915_private *i915); +}; + /* * For SKL+, the plane source size used by the hardware is based on the value we * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value @@ -236,6 +243,13 @@ static bool i8xx_fbc_is_compressing(struct drm_i915_private *i915) (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); } +static const struct intel_fbc_funcs i8xx_fbc_funcs = { + .activate = i8xx_fbc_activate, + .deactivate = i8xx_fbc_deactivate, + .is_active = i8xx_fbc_is_active, + .is_compressing = i8xx_fbc_is_compressing, +}; + static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) { switch (i915->fbc.limit) { @@ -305,6 +319,13 @@ static bool g4x_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; } +static const struct intel_fbc_funcs g4x_fbc_funcs = { + .activate = g4x_fbc_activate, + .deactivate = g4x_fbc_deactivate, + .is_active = g4x_fbc_is_active, + .is_compressing = g4x_fbc_is_compressing, +}; + static void i8xx_fbc_recompress(struct drm_i915_private *dev_priv) { struct intel_fbc_reg_params *params = &dev_priv->fbc.params; @@ -396,6 +417,13 @@ static bool ilk_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, ILK_DPFC_STATUS) & ILK_DPFC_COMP_SEG_MASK; } +static const struct intel_fbc_funcs ilk_fbc_funcs = { + .activate = ilk_fbc_activate, + .deactivate = ilk_fbc_deactivate, + .is_active = ilk_fbc_is_active, + .is_compressing = ilk_fbc_is_compressing, +}; + static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) { struct intel_fbc *fbc = &i915->fbc; @@ -466,14 +494,18 @@ static bool gen7_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; } +static const struct intel_fbc_funcs gen7_fbc_funcs = { + .activate = gen7_fbc_activate, + .deactivate = ilk_fbc_deactivate, + .is_active = ilk_fbc_is_active, + .is_compressing = gen7_fbc_is_compressing, +}; + static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) { - if (DISPLAY_VER(dev_priv) >= 5) - return ilk_fbc_is_active(dev_priv); - else if (IS_GM45(dev_priv)) - return g4x_fbc_is_active(dev_priv); - else - return i8xx_fbc_is_active(dev_priv); + struct intel_fbc *fbc = &dev_priv->fbc; + + return fbc->funcs->is_active(dev_priv); } static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) @@ -485,14 +517,7 @@ static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) fbc->active = true; fbc->activated = true; - if (DISPLAY_VER(dev_priv) >= 7) - gen7_fbc_activate(dev_priv); - else if (DISPLAY_VER(dev_priv) >= 5) - ilk_fbc_activate(dev_priv); - else if (IS_GM45(dev_priv)) - g4x_fbc_activate(dev_priv); - else - i8xx_fbc_activate(dev_priv); + fbc->funcs->activate(dev_priv); } static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv) @@ -503,24 +528,14 @@ static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv) fbc->active = false; - if (DISPLAY_VER(dev_priv) >= 5) - ilk_fbc_deactivate(dev_priv); - else if (IS_GM45(dev_priv)) - g4x_fbc_deactivate(dev_priv); - else - i8xx_fbc_deactivate(dev_priv); + fbc->funcs->deactivate(dev_priv); } bool intel_fbc_is_compressing(struct drm_i915_private *i915) { - if (DISPLAY_VER(i915) >= 7) - return gen7_fbc_is_compressing(i915); - else if (DISPLAY_VER(i915) >= 5) - return ilk_fbc_is_compressing(i915); - else if (IS_G4X(i915)) - return g4x_fbc_is_compressing(i915); - else - return i8xx_fbc_is_compressing(i915); + struct intel_fbc *fbc = &i915->fbc; + + return fbc->funcs->is_compressing(i915); } /** @@ -1650,6 +1665,15 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) return; } + if (DISPLAY_VER(dev_priv) >= 7) + fbc->funcs = &gen7_fbc_funcs; + else if (DISPLAY_VER(dev_priv) >= 5) + fbc->funcs = &ilk_fbc_funcs; + else if (IS_G4X(dev_priv)) + fbc->funcs = &g4x_fbc_funcs; + else + fbc->funcs = &i8xx_fbc_funcs; + /* We still don't have any sort of hardware state readout for FBC, so * deactivate it in case the BIOS activated it to make sure software * matches the hardware state. */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cf88a47799f9f..6d091187ecd80 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -402,10 +402,13 @@ struct drm_i915_display_funcs { void (*commit_modeset_enables)(struct intel_atomic_state *state); }; +struct intel_fbc_funcs; #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ struct intel_fbc { + const struct intel_fbc_funcs *funcs; + /* This is always the inner lock when overlapping with struct_mutex and * it's the outer lock when overlapping with stolen_lock. */ struct mutex lock; From 0242cd3a538f8393cb811d79806ab519228e7cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:10 +0200 Subject: [PATCH 126/176] drm/i915/fbc: Introduce .nuke() vfunc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate yet another if-ladder by adding .nuke() vfunc. We also rename all *_recompress() stuff to *_nuke() since that's the terminology the spec uses. Also "recompress" is a bit confusing by perhaps implying that this triggers an immediate recompression. Depending on the hardware that may definitely not be the case, and in general we don't specifically know when the hardware decides to compress. So all we do is "nuke" the current compressed framebuffer and leave it up to the hardware to recompress later if it so chooses. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-8-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 145 +++++++++++++---------- 1 file changed, 84 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index a2e09b6d21c73..be89404840d2c 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -53,6 +53,7 @@ struct intel_fbc_funcs { void (*deactivate)(struct drm_i915_private *i915); bool (*is_active)(struct drm_i915_private *i915); bool (*is_compressing)(struct drm_i915_private *i915); + void (*nuke)(struct drm_i915_private *i915); }; /* @@ -243,11 +244,42 @@ static bool i8xx_fbc_is_compressing(struct drm_i915_private *i915) (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); } +static void i8xx_fbc_nuke(struct drm_i915_private *dev_priv) +{ + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; + + spin_lock_irq(&dev_priv->uncore.lock); + intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), + intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane))); + spin_unlock_irq(&dev_priv->uncore.lock); +} + static const struct intel_fbc_funcs i8xx_fbc_funcs = { .activate = i8xx_fbc_activate, .deactivate = i8xx_fbc_deactivate, .is_active = i8xx_fbc_is_active, .is_compressing = i8xx_fbc_is_compressing, + .nuke = i8xx_fbc_nuke, +}; + +static void i965_fbc_nuke(struct drm_i915_private *dev_priv) +{ + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; + + spin_lock_irq(&dev_priv->uncore.lock); + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), + intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane))); + spin_unlock_irq(&dev_priv->uncore.lock); +} + +static const struct intel_fbc_funcs i965_fbc_funcs = { + .activate = i8xx_fbc_activate, + .deactivate = i8xx_fbc_deactivate, + .is_active = i8xx_fbc_is_active, + .is_compressing = i8xx_fbc_is_compressing, + .nuke = i965_fbc_nuke, }; static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) @@ -324,70 +356,13 @@ static const struct intel_fbc_funcs g4x_fbc_funcs = { .deactivate = g4x_fbc_deactivate, .is_active = g4x_fbc_is_active, .is_compressing = g4x_fbc_is_compressing, + .nuke = i965_fbc_nuke, }; -static void i8xx_fbc_recompress(struct drm_i915_private *dev_priv) -{ - struct intel_fbc_reg_params *params = &dev_priv->fbc.params; - enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; - - spin_lock_irq(&dev_priv->uncore.lock); - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), - intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane))); - spin_unlock_irq(&dev_priv->uncore.lock); -} - -static void i965_fbc_recompress(struct drm_i915_private *dev_priv) -{ - struct intel_fbc_reg_params *params = &dev_priv->fbc.params; - enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; - - spin_lock_irq(&dev_priv->uncore.lock); - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), - intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane))); - spin_unlock_irq(&dev_priv->uncore.lock); -} - -/* This function forces a CFB recompression through the nuke operation. */ -static void snb_fbc_recompress(struct drm_i915_private *dev_priv) -{ - intel_de_write(dev_priv, MSG_FBC_REND_STATE, FBC_REND_NUKE); - intel_de_posting_read(dev_priv, MSG_FBC_REND_STATE); -} - -static void intel_fbc_recompress(struct drm_i915_private *dev_priv) -{ - struct intel_fbc *fbc = &dev_priv->fbc; - - trace_intel_fbc_nuke(fbc->crtc); - - if (DISPLAY_VER(dev_priv) >= 6) - snb_fbc_recompress(dev_priv); - else if (DISPLAY_VER(dev_priv) >= 4) - i965_fbc_recompress(dev_priv); - else - i8xx_fbc_recompress(dev_priv); -} - -static void snb_fbc_program_fence(struct drm_i915_private *i915) -{ - const struct intel_fbc_reg_params *params = &i915->fbc.params; - u32 ctl = 0; - - if (params->fence_id >= 0) - ctl = SNB_CPU_FENCE_ENABLE | params->fence_id; - - intel_de_write(i915, SNB_DPFC_CTL_SA, ctl); - intel_de_write(i915, DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); -} - static void ilk_fbc_activate(struct drm_i915_private *dev_priv) { struct intel_fbc_reg_params *params = &dev_priv->fbc.params; - if (IS_SANDYBRIDGE(dev_priv)) - snb_fbc_program_fence(dev_priv); - intel_de_write(dev_priv, ILK_DPFC_FENCE_YOFF, params->fence_y_offset); @@ -422,6 +397,40 @@ static const struct intel_fbc_funcs ilk_fbc_funcs = { .deactivate = ilk_fbc_deactivate, .is_active = ilk_fbc_is_active, .is_compressing = ilk_fbc_is_compressing, + .nuke = i965_fbc_nuke, +}; + +static void snb_fbc_program_fence(struct drm_i915_private *i915) +{ + const struct intel_fbc_reg_params *params = &i915->fbc.params; + u32 ctl = 0; + + if (params->fence_id >= 0) + ctl = SNB_CPU_FENCE_ENABLE | params->fence_id; + + intel_de_write(i915, SNB_DPFC_CTL_SA, ctl); + intel_de_write(i915, DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); +} + +static void snb_fbc_activate(struct drm_i915_private *dev_priv) +{ + snb_fbc_program_fence(dev_priv); + + ilk_fbc_activate(dev_priv); +} + +static void snb_fbc_nuke(struct drm_i915_private *dev_priv) +{ + intel_de_write(dev_priv, MSG_FBC_REND_STATE, FBC_REND_NUKE); + intel_de_posting_read(dev_priv, MSG_FBC_REND_STATE); +} + +static const struct intel_fbc_funcs snb_fbc_funcs = { + .activate = snb_fbc_activate, + .deactivate = ilk_fbc_deactivate, + .is_active = ilk_fbc_is_active, + .is_compressing = ilk_fbc_is_compressing, + .nuke = snb_fbc_nuke, }; static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) @@ -499,6 +508,7 @@ static const struct intel_fbc_funcs gen7_fbc_funcs = { .deactivate = ilk_fbc_deactivate, .is_active = ilk_fbc_is_active, .is_compressing = gen7_fbc_is_compressing, + .nuke = snb_fbc_nuke, }; static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) @@ -538,6 +548,15 @@ bool intel_fbc_is_compressing(struct drm_i915_private *i915) return fbc->funcs->is_compressing(i915); } +static void intel_fbc_nuke(struct drm_i915_private *i915) +{ + struct intel_fbc *fbc = &i915->fbc; + + trace_intel_fbc_nuke(fbc->crtc); + + fbc->funcs->nuke(i915); +} + /** * intel_fbc_is_active - Is FBC active? * @dev_priv: i915 device instance @@ -555,7 +574,7 @@ bool intel_fbc_is_active(struct drm_i915_private *dev_priv) static void intel_fbc_activate(struct drm_i915_private *dev_priv) { intel_fbc_hw_activate(dev_priv); - intel_fbc_recompress(dev_priv); + intel_fbc_nuke(dev_priv); } static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, @@ -1318,7 +1337,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (!fbc->busy_bits && fbc->crtc && (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) { if (fbc->active) - intel_fbc_recompress(dev_priv); + intel_fbc_nuke(dev_priv); else if (!fbc->flip_pending) __intel_fbc_post_update(fbc->crtc); } @@ -1667,10 +1686,14 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) if (DISPLAY_VER(dev_priv) >= 7) fbc->funcs = &gen7_fbc_funcs; - else if (DISPLAY_VER(dev_priv) >= 5) + else if (DISPLAY_VER(dev_priv) == 6) + fbc->funcs = &snb_fbc_funcs; + else if (DISPLAY_VER(dev_priv) == 5) fbc->funcs = &ilk_fbc_funcs; else if (IS_G4X(dev_priv)) fbc->funcs = &g4x_fbc_funcs; + else if (DISPLAY_VER(dev_priv) == 4) + fbc->funcs = &i965_fbc_funcs; else fbc->funcs = &i8xx_fbc_funcs; From 11a6b88b8cf2ff6e93a5b136ac04fd851a2d935d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:11 +0200 Subject: [PATCH 127/176] drm/i915/fbc: s/gen7/ivb/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "gen7" in display code is not really sensible. We shall call these things "ivb". Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-9-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index be89404840d2c..1df5a08d3457d 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -462,7 +462,7 @@ static void skl_fbc_program_cfb_stride(struct drm_i915_private *i915) CHICKEN_FBC_STRIDE_MASK, val); } -static u32 gen7_dpfc_ctl(struct drm_i915_private *i915) +static u32 ivb_dpfc_ctl(struct drm_i915_private *i915) { const struct intel_fbc_reg_params *params = &i915->fbc.params; u32 dpfc_ctl; @@ -481,7 +481,7 @@ static u32 gen7_dpfc_ctl(struct drm_i915_private *i915) return dpfc_ctl; } -static void gen7_fbc_activate(struct drm_i915_private *dev_priv) +static void ivb_fbc_activate(struct drm_i915_private *dev_priv) { if (DISPLAY_VER(dev_priv) >= 10) glk_fbc_program_cfb_stride(dev_priv); @@ -492,10 +492,10 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) snb_fbc_program_fence(dev_priv); intel_de_write(dev_priv, ILK_DPFC_CONTROL, - DPFC_CTL_EN | gen7_dpfc_ctl(dev_priv)); + DPFC_CTL_EN | ivb_dpfc_ctl(dev_priv)); } -static bool gen7_fbc_is_compressing(struct drm_i915_private *i915) +static bool ivb_fbc_is_compressing(struct drm_i915_private *i915) { if (DISPLAY_VER(i915) >= 8) return intel_de_read(i915, IVB_FBC_STATUS2) & BDW_FBC_COMP_SEG_MASK; @@ -503,11 +503,11 @@ static bool gen7_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; } -static const struct intel_fbc_funcs gen7_fbc_funcs = { - .activate = gen7_fbc_activate, +static const struct intel_fbc_funcs ivb_fbc_funcs = { + .activate = ivb_fbc_activate, .deactivate = ilk_fbc_deactivate, .is_active = ilk_fbc_is_active, - .is_compressing = gen7_fbc_is_compressing, + .is_compressing = ivb_fbc_is_compressing, .nuke = snb_fbc_nuke, }; @@ -1685,7 +1685,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) } if (DISPLAY_VER(dev_priv) >= 7) - fbc->funcs = &gen7_fbc_funcs; + fbc->funcs = &ivb_fbc_funcs; else if (DISPLAY_VER(dev_priv) == 6) fbc->funcs = &snb_fbc_funcs; else if (DISPLAY_VER(dev_priv) == 5) From 8f8c61038768526d894e02b10ee1e4ace94e55df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:12 +0200 Subject: [PATCH 128/176] drm/i915/fbc: Introduce .program_cfb() vfunc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate the last if-ladder by pulling the CFB/LLB programming into a vfunc as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-10-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 56 ++++++++++++++++-------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 1df5a08d3457d..0cbd0e302320b 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -54,6 +54,7 @@ struct intel_fbc_funcs { bool (*is_active)(struct drm_i915_private *i915); bool (*is_compressing)(struct drm_i915_private *i915); void (*nuke)(struct drm_i915_private *i915); + void (*program_cfb)(struct drm_i915_private *i915); }; /* @@ -255,12 +256,28 @@ static void i8xx_fbc_nuke(struct drm_i915_private *dev_priv) spin_unlock_irq(&dev_priv->uncore.lock); } +static void i8xx_fbc_program_cfb(struct drm_i915_private *i915) +{ + struct intel_fbc *fbc = &i915->fbc; + + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + fbc->compressed_fb.start, U32_MAX)); + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + fbc->compressed_llb.start, U32_MAX)); + + intel_de_write(i915, FBC_CFB_BASE, + i915->dsm.start + fbc->compressed_fb.start); + intel_de_write(i915, FBC_LL_BASE, + i915->dsm.start + fbc->compressed_llb.start); +} + static const struct intel_fbc_funcs i8xx_fbc_funcs = { .activate = i8xx_fbc_activate, .deactivate = i8xx_fbc_deactivate, .is_active = i8xx_fbc_is_active, .is_compressing = i8xx_fbc_is_compressing, .nuke = i8xx_fbc_nuke, + .program_cfb = i8xx_fbc_program_cfb, }; static void i965_fbc_nuke(struct drm_i915_private *dev_priv) @@ -280,6 +297,7 @@ static const struct intel_fbc_funcs i965_fbc_funcs = { .is_active = i8xx_fbc_is_active, .is_compressing = i8xx_fbc_is_compressing, .nuke = i965_fbc_nuke, + .program_cfb = i8xx_fbc_program_cfb, }; static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) @@ -351,12 +369,20 @@ static bool g4x_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; } +static void g4x_fbc_program_cfb(struct drm_i915_private *i915) +{ + struct intel_fbc *fbc = &i915->fbc; + + intel_de_write(i915, DPFC_CB_BASE, fbc->compressed_fb.start); +} + static const struct intel_fbc_funcs g4x_fbc_funcs = { .activate = g4x_fbc_activate, .deactivate = g4x_fbc_deactivate, .is_active = g4x_fbc_is_active, .is_compressing = g4x_fbc_is_compressing, .nuke = i965_fbc_nuke, + .program_cfb = g4x_fbc_program_cfb, }; static void ilk_fbc_activate(struct drm_i915_private *dev_priv) @@ -392,12 +418,20 @@ static bool ilk_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, ILK_DPFC_STATUS) & ILK_DPFC_COMP_SEG_MASK; } +static void ilk_fbc_program_cfb(struct drm_i915_private *i915) +{ + struct intel_fbc *fbc = &i915->fbc; + + intel_de_write(i915, ILK_DPFC_CB_BASE, fbc->compressed_fb.start); +} + static const struct intel_fbc_funcs ilk_fbc_funcs = { .activate = ilk_fbc_activate, .deactivate = ilk_fbc_deactivate, .is_active = ilk_fbc_is_active, .is_compressing = ilk_fbc_is_compressing, .nuke = i965_fbc_nuke, + .program_cfb = ilk_fbc_program_cfb, }; static void snb_fbc_program_fence(struct drm_i915_private *i915) @@ -431,6 +465,7 @@ static const struct intel_fbc_funcs snb_fbc_funcs = { .is_active = ilk_fbc_is_active, .is_compressing = ilk_fbc_is_compressing, .nuke = snb_fbc_nuke, + .program_cfb = ilk_fbc_program_cfb, }; static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) @@ -509,6 +544,7 @@ static const struct intel_fbc_funcs ivb_fbc_funcs = { .is_active = ilk_fbc_is_active, .is_compressing = ivb_fbc_is_compressing, .nuke = snb_fbc_nuke, + .program_cfb = ilk_fbc_program_cfb, }; static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) @@ -704,25 +740,7 @@ static void intel_fbc_program_cfb(struct drm_i915_private *dev_priv) { struct intel_fbc *fbc = &dev_priv->fbc; - if (DISPLAY_VER(dev_priv) >= 5) { - intel_de_write(dev_priv, ILK_DPFC_CB_BASE, - fbc->compressed_fb.start); - } else if (IS_GM45(dev_priv)) { - intel_de_write(dev_priv, DPFC_CB_BASE, - fbc->compressed_fb.start); - } else { - GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start, - fbc->compressed_fb.start, - U32_MAX)); - GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start, - fbc->compressed_llb.start, - U32_MAX)); - - intel_de_write(dev_priv, FBC_CFB_BASE, - dev_priv->dsm.start + fbc->compressed_fb.start); - intel_de_write(dev_priv, FBC_LL_BASE, - dev_priv->dsm.start + fbc->compressed_llb.start); - } + fbc->funcs->program_cfb(dev_priv); } static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) From a61cf3883c83d02cc27b18c4cf8f639279587bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:13 +0200 Subject: [PATCH 129/176] drm/i915/fbc: Introduce intel_fbc_set_false_color() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the direct FBC register frobbing out from the debugfs code into the fbc code. Also add a vfunc for this so we don't need extra platforms checks. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-11-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- .../drm/i915/display/intel_display_debugfs.c | 18 +------------ drivers/gpu/drm/i915/display/intel_fbc.c | 27 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fbc.h | 2 ++ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 19bc148e168ce..1a92107397273 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -70,9 +70,6 @@ static int i915_fbc_false_color_get(void *data, u64 *val) { struct drm_i915_private *dev_priv = data; - if (DISPLAY_VER(dev_priv) < 7 || !HAS_FBC(dev_priv)) - return -ENODEV; - *val = dev_priv->fbc.false_color; return 0; @@ -81,21 +78,8 @@ static int i915_fbc_false_color_get(void *data, u64 *val) static int i915_fbc_false_color_set(void *data, u64 val) { struct drm_i915_private *dev_priv = data; - u32 reg; - - if (DISPLAY_VER(dev_priv) < 7 || !HAS_FBC(dev_priv)) - return -ENODEV; - mutex_lock(&dev_priv->fbc.lock); - - reg = intel_de_read(dev_priv, ILK_DPFC_CONTROL); - dev_priv->fbc.false_color = val; - - intel_de_write(dev_priv, ILK_DPFC_CONTROL, - val ? (reg | FBC_CTL_FALSE_COLOR) : (reg & ~FBC_CTL_FALSE_COLOR)); - - mutex_unlock(&dev_priv->fbc.lock); - return 0; + return intel_fbc_set_false_color(dev_priv, val); } DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_false_color_fops, diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 0cbd0e302320b..b13a776cb3dcd 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -55,6 +55,7 @@ struct intel_fbc_funcs { bool (*is_compressing)(struct drm_i915_private *i915); void (*nuke)(struct drm_i915_private *i915); void (*program_cfb)(struct drm_i915_private *i915); + void (*set_false_color)(struct drm_i915_private *i915, bool enable); }; /* @@ -538,6 +539,13 @@ static bool ivb_fbc_is_compressing(struct drm_i915_private *i915) return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; } +static void ivb_fbc_set_false_color(struct drm_i915_private *i915, + bool enable) +{ + intel_de_rmw(i915, ILK_DPFC_CONTROL, + FBC_CTL_FALSE_COLOR, enable ? FBC_CTL_FALSE_COLOR : 0); +} + static const struct intel_fbc_funcs ivb_fbc_funcs = { .activate = ivb_fbc_activate, .deactivate = ilk_fbc_deactivate, @@ -545,6 +553,7 @@ static const struct intel_fbc_funcs ivb_fbc_funcs = { .is_compressing = ivb_fbc_is_compressing, .nuke = snb_fbc_nuke, .program_cfb = ilk_fbc_program_cfb, + .set_false_color = ivb_fbc_set_false_color, }; static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) @@ -593,6 +602,24 @@ static void intel_fbc_nuke(struct drm_i915_private *i915) fbc->funcs->nuke(i915); } +int intel_fbc_set_false_color(struct drm_i915_private *i915, bool enable) +{ + struct intel_fbc *fbc = &i915->fbc; + + if (!fbc->funcs || !fbc->funcs->set_false_color) + return -ENODEV; + + mutex_lock(&fbc->lock); + + fbc->false_color = enable; + + fbc->funcs->set_false_color(i915, enable); + + mutex_unlock(&fbc->lock); + + return 0; +} + /** * intel_fbc_is_active - Is FBC active? * @dev_priv: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index b2c9e441edbdc..4d1f2a76ccb49 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -37,5 +37,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv); +int intel_fbc_set_false_color(struct drm_i915_private *i915, + bool enable); #endif /* __INTEL_FBC_H__ */ From a46553837056d3a6119f4ac350afff8c2a99daf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:14 +0200 Subject: [PATCH 130/176] drm/i915/fbc: Nuke BDW_FBC_COMP_SEG_MASK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just use a same mask for ivb/hsw as for bdw+. The extra bit in the bdw mask is mbz on ivb/hsw anyway so this is just pointless complexity. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-12-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 5 +---- drivers/gpu/drm/i915/i915_reg.h | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index b13a776cb3dcd..1193e86690e5b 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -533,10 +533,7 @@ static void ivb_fbc_activate(struct drm_i915_private *dev_priv) static bool ivb_fbc_is_compressing(struct drm_i915_private *i915) { - if (DISPLAY_VER(i915) >= 8) - return intel_de_read(i915, IVB_FBC_STATUS2) & BDW_FBC_COMP_SEG_MASK; - else - return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; + return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; } static void ivb_fbc_set_false_color(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index beeffbff6cf9d..ad9fd91a7c69b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3380,8 +3380,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define ILK_DPFC_STATUS _MMIO(0x43210) #define ILK_DPFC_COMP_SEG_MASK 0x7ff #define IVB_FBC_STATUS2 _MMIO(0x43214) -#define IVB_FBC_COMP_SEG_MASK 0x7ff -#define BDW_FBC_COMP_SEG_MASK 0xfff +#define IVB_FBC_COMP_SEG_MASK 0xfff #define ILK_DPFC_FENCE_YOFF _MMIO(0x43218) #define ILK_DPFC_CHICKEN _MMIO(0x43224) #define ILK_DPFC_DISABLE_DUMMY0 (1 << 8) From 73ab6ec90922f50b99c189088f100025a44d8ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:15 +0200 Subject: [PATCH 131/176] drm/i915/fbc: Clean up all register defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FBC register defines are a mess: - namespace changes between DPFC_, FBC_, and some platform specific prefix at a whim - ilk+ reuses most g4x bits but still has some separate bit defines elsewhere - it's not clear from the defines that the bit defines are shared So let's clean it up: - both g4x and ilk register share the same defines now - only defines which conflict have a _PLATFORM suffix, everyone else just gets comments to indicate which platforms do what - namespace is consistent DPFC_ now - SNB system agent fence registers also get a consistent namespace - REG_BIT() & co. for everything Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-13-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 24 +++---- drivers/gpu/drm/i915/i915_reg.h | 85 ++++++++++++------------ drivers/gpu/drm/i915/intel_pm.c | 14 ++-- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 1193e86690e5b..1c9ada22b4de2 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -322,16 +322,16 @@ static u32 g4x_dpfc_ctl(struct drm_i915_private *i915) u32 dpfc_ctl; dpfc_ctl = g4x_dpfc_ctl_limit(i915) | - DPFC_CTL_PLANE(params->crtc.i9xx_plane); + DPFC_CTL_PLANE_G4X(params->crtc.i9xx_plane); if (IS_G4X(i915)) - dpfc_ctl |= DPFC_SR_EN; + dpfc_ctl |= DPFC_CTL_SR_EN; if (params->fence_id >= 0) { - dpfc_ctl |= DPFC_CTL_FENCE_EN; + dpfc_ctl |= DPFC_CTL_FENCE_EN_G4X; if (DISPLAY_VER(i915) < 6) - dpfc_ctl |= params->fence_id; + dpfc_ctl |= DPFC_CTL_FENCENO(params->fence_id); } return dpfc_ctl; @@ -416,7 +416,7 @@ static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv) static bool ilk_fbc_is_compressing(struct drm_i915_private *i915) { - return intel_de_read(i915, ILK_DPFC_STATUS) & ILK_DPFC_COMP_SEG_MASK; + return intel_de_read(i915, ILK_DPFC_STATUS) & DPFC_COMP_SEG_MASK; } static void ilk_fbc_program_cfb(struct drm_i915_private *i915) @@ -441,10 +441,10 @@ static void snb_fbc_program_fence(struct drm_i915_private *i915) u32 ctl = 0; if (params->fence_id >= 0) - ctl = SNB_CPU_FENCE_ENABLE | params->fence_id; + ctl = SNB_DPFC_FENCE_EN | SNB_DPFC_FENCENO(params->fence_id); intel_de_write(i915, SNB_DPFC_CTL_SA, ctl); - intel_de_write(i915, DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); + intel_de_write(i915, SNB_DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); } static void snb_fbc_activate(struct drm_i915_private *dev_priv) @@ -506,13 +506,13 @@ static u32 ivb_dpfc_ctl(struct drm_i915_private *i915) dpfc_ctl = g4x_dpfc_ctl_limit(i915); if (IS_IVYBRIDGE(i915)) - dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.i9xx_plane); + dpfc_ctl |= DPFC_CTL_PLANE_IVB(params->crtc.i9xx_plane); if (params->fence_id >= 0) - dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; + dpfc_ctl |= DPFC_CTL_FENCE_EN_IVB; if (i915->fbc.false_color) - dpfc_ctl |= FBC_CTL_FALSE_COLOR; + dpfc_ctl |= DPFC_CTL_FALSE_COLOR; return dpfc_ctl; } @@ -533,14 +533,14 @@ static void ivb_fbc_activate(struct drm_i915_private *dev_priv) static bool ivb_fbc_is_compressing(struct drm_i915_private *i915) { - return intel_de_read(i915, IVB_FBC_STATUS2) & IVB_FBC_COMP_SEG_MASK; + return intel_de_read(i915, ILK_DPFC_STATUS2) & DPFC_COMP_SEG_MASK_IVB; } static void ivb_fbc_set_false_color(struct drm_i915_private *i915, bool enable) { intel_de_rmw(i915, ILK_DPFC_CONTROL, - FBC_CTL_FALSE_COLOR, enable ? FBC_CTL_FALSE_COLOR : 0); + DPFC_CTL_FALSE_COLOR, enable ? DPFC_CTL_FALSE_COLOR : 0); } static const struct intel_fbc_funcs ivb_fbc_funcs = { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ad9fd91a7c69b..bffb2ac09f610 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3343,56 +3343,55 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) /* Framebuffer compression for GM45+ */ #define DPFC_CB_BASE _MMIO(0x3200) +#define ILK_DPFC_CB_BASE _MMIO(0x43200) #define DPFC_CONTROL _MMIO(0x3208) -#define DPFC_CTL_EN (1 << 31) -#define DPFC_CTL_PLANE(plane) ((plane) << 30) -#define IVB_DPFC_CTL_PLANE(plane) ((plane) << 29) -#define DPFC_CTL_FENCE_EN (1 << 29) -#define IVB_DPFC_CTL_FENCE_EN (1 << 28) -#define DPFC_CTL_PERSISTENT_MODE (1 << 25) -#define DPFC_SR_EN (1 << 10) -#define DPFC_CTL_LIMIT_1X (0 << 6) -#define DPFC_CTL_LIMIT_2X (1 << 6) -#define DPFC_CTL_LIMIT_4X (2 << 6) +#define ILK_DPFC_CONTROL _MMIO(0x43208) +#define DPFC_CTL_EN REG_BIT(31) +#define DPFC_CTL_PLANE_MASK_G4X REG_BIT(30) /* g4x-snb */ +#define DPFC_CTL_PLANE_G4X(i9xx_plane) REG_FIELD_PREP(DPFC_CTL_PLANE_MASK_G4X, (i9xx_plane)) +#define DPFC_CTL_FENCE_EN_G4X REG_BIT(29) /* g4x-snb */ +#define DPFC_CTL_PLANE_MASK_IVB REG_GENMASK(30, 29) /* ivb only */ +#define DPFC_CTL_PLANE_IVB(i9xx_plane) REG_FIELD_PREP(DPFC_CTL_PLANE_MASK_IVB, (i9xx_plane)) +#define DPFC_CTL_FENCE_EN_IVB REG_BIT(28) /* ivb+ */ +#define DPFC_CTL_PERSISTENT_MODE REG_BIT(25) /* g4x-snb */ +#define DPFC_CTL_FALSE_COLOR REG_BIT(10) /* ivb+ */ +#define DPFC_CTL_SR_EN REG_BIT(10) /* g4x only */ +#define DPFC_CTL_SR_EXIT_DIS REG_BIT(9) /* g4x only */ +#define DPFC_CTL_LIMIT_MASK REG_GENMASK(7, 6) +#define DPFC_CTL_LIMIT_1X REG_FIELD_PREP(DPFC_CTL_LIMIT_MASK, 0) +#define DPFC_CTL_LIMIT_2X REG_FIELD_PREP(DPFC_CTL_LIMIT_MASK, 1) +#define DPFC_CTL_LIMIT_4X REG_FIELD_PREP(DPFC_CTL_LIMIT_MASK, 2) +#define DPFC_CTL_FENCENO_MASK REG_GENMASK(3, 0) +#define DPFC_CTL_FENCENO(fence) REG_FIELD_PREP(DPFC_CTL_FENCENO_MASK, (fence)) #define DPFC_RECOMP_CTL _MMIO(0x320c) -#define DPFC_RECOMP_STALL_EN (1 << 27) -#define DPFC_RECOMP_STALL_WM_SHIFT (16) -#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000) -#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0) -#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f) +#define ILK_DPFC_RECOMP_CTL _MMIO(0x4320c) +#define DPFC_RECOMP_STALL_EN REG_BIT(27) +#define DPFC_RECOMP_STALL_WM_MASK REG_GENMASK(26, 16) +#define DPFC_RECOMP_TIMER_COUNT_MASK REG_GENMASK(5, 0) #define DPFC_STATUS _MMIO(0x3210) -#define DPFC_INVAL_SEG_SHIFT (16) -#define DPFC_INVAL_SEG_MASK (0x07ff0000) -#define DPFC_COMP_SEG_SHIFT (0) -#define DPFC_COMP_SEG_MASK (0x000007ff) +#define ILK_DPFC_STATUS _MMIO(0x43210) +#define DPFC_INVAL_SEG_MASK REG_GENMASK(26, 16) +#define DPFC_COMP_SEG_MASK REG_GENMASK(10, 0) #define DPFC_STATUS2 _MMIO(0x3214) +#define ILK_DPFC_STATUS2 _MMIO(0x43214) +#define DPFC_COMP_SEG_MASK_IVB REG_GENMASK(11, 0) #define DPFC_FENCE_YOFF _MMIO(0x3218) -#define DPFC_CHICKEN _MMIO(0x3224) -#define DPFC_HT_MODIFY (1 << 31) - -/* Framebuffer compression for Ironlake */ -#define ILK_DPFC_CB_BASE _MMIO(0x43200) -#define ILK_DPFC_CONTROL _MMIO(0x43208) -#define FBC_CTL_FALSE_COLOR (1 << 10) -/* The bit 28-8 is reserved */ -#define DPFC_RESERVED (0x1FFFFF00) -#define ILK_DPFC_RECOMP_CTL _MMIO(0x4320c) -#define ILK_DPFC_STATUS _MMIO(0x43210) -#define ILK_DPFC_COMP_SEG_MASK 0x7ff -#define IVB_FBC_STATUS2 _MMIO(0x43214) -#define IVB_FBC_COMP_SEG_MASK 0xfff #define ILK_DPFC_FENCE_YOFF _MMIO(0x43218) +#define DPFC_CHICKEN _MMIO(0x3224) #define ILK_DPFC_CHICKEN _MMIO(0x43224) -#define ILK_DPFC_DISABLE_DUMMY0 (1 << 8) -#define ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL (1 << 14) -#define ILK_DPFC_NUKE_ON_ANY_MODIFICATION (1 << 23) +#define DPFC_HT_MODIFY REG_BIT(31) /* pre-ivb */ +#define DPFC_NUKE_ON_ANY_MODIFICATION REG_BIT(23) /* bdw+ */ +#define DPFC_CHICKEN_COMP_DUMMY_PIXEL REG_BIT(14) /* glk+ */ +#define DPFC_DISABLE_DUMMY0 REG_BIT(8) /* ivb+ */ + #define GLK_FBC_STRIDE _MMIO(0x43228) #define FBC_STRIDE_OVERRIDE REG_BIT(15) #define FBC_STRIDE_MASK REG_GENMASK(14, 0) #define FBC_STRIDE(x) REG_FIELD_PREP(FBC_STRIDE_MASK, (x)) + #define ILK_FBC_RT_BASE _MMIO(0x2128) -#define ILK_FBC_RT_VALID (1 << 0) -#define SNB_FBC_FRONT_BUFFER (1 << 1) +#define ILK_FBC_RT_VALID REG_BIT(0) +#define SNB_FBC_FRONT_BUFFER REG_BIT(1) #define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000) #define ILK_FBCQ_DIS (1 << 22) @@ -3416,8 +3415,10 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) * The following two registers are of type GTTMMADR */ #define SNB_DPFC_CTL_SA _MMIO(0x100100) -#define SNB_CPU_FENCE_ENABLE (1 << 29) -#define DPFC_CPU_FENCE_OFFSET _MMIO(0x100104) +#define SNB_DPFC_FENCE_EN REG_BIT(29) +#define SNB_DPFC_FENCENO_MASK REG_GENMASK(4, 0) +#define SNB_DPFC_FENCENO(fence) REG_FIELD_PREP(SNB_DPFC_FENCENO_MASK, (fence)) +#define SNB_DPFC_CPU_FENCE_OFFSET _MMIO(0x100104) /* Framebuffer compression for Ivybridge */ #define IVB_FBC_RT_BASE _MMIO(0x7020) @@ -3427,8 +3428,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define IPS_ENABLE (1 << 31) #define MSG_FBC_REND_STATE _MMIO(0x50380) -#define FBC_REND_NUKE (1 << 2) -#define FBC_REND_CACHE_CLEAN (1 << 1) +#define FBC_REND_NUKE REG_BIT(2) +#define FBC_REND_CACHE_CLEAN REG_BIT(1) /* * GPIO regs diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cffb3df35a636..2796f32d72ad0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -161,7 +161,7 @@ static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) * Display WA #0883: bxt */ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN) | - ILK_DPFC_DISABLE_DUMMY0); + DPFC_DISABLE_DUMMY0); } static void glk_init_clock_gating(struct drm_i915_private *dev_priv) @@ -7435,7 +7435,7 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv) { /* Wa_1409120013:icl,ehl */ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, - ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL); + DPFC_CHICKEN_COMP_DUMMY_PIXEL); /*Wa_14010594013:icl, ehl */ intel_uncore_rmw(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1, @@ -7448,7 +7448,7 @@ static void gen12lp_init_clock_gating(struct drm_i915_private *dev_priv) if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv) || IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv)) intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, - ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL); + DPFC_CHICKEN_COMP_DUMMY_PIXEL); /* Wa_1409825376:tgl (pre-prod)*/ if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0)) @@ -7510,7 +7510,7 @@ static void cfl_init_clock_gating(struct drm_i915_private *dev_priv) * Display WA #0873: cfl */ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN) | - ILK_DPFC_NUKE_ON_ANY_MODIFICATION); + DPFC_NUKE_ON_ANY_MODIFICATION); } static void kbl_init_clock_gating(struct drm_i915_private *dev_priv) @@ -7543,7 +7543,7 @@ static void kbl_init_clock_gating(struct drm_i915_private *dev_priv) * Display WA #0873: kbl */ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN) | - ILK_DPFC_NUKE_ON_ANY_MODIFICATION); + DPFC_NUKE_ON_ANY_MODIFICATION); } static void skl_init_clock_gating(struct drm_i915_private *dev_priv) @@ -7570,14 +7570,14 @@ static void skl_init_clock_gating(struct drm_i915_private *dev_priv) * Display WA #0873: skl */ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN) | - ILK_DPFC_NUKE_ON_ANY_MODIFICATION); + DPFC_NUKE_ON_ANY_MODIFICATION); /* * WaFbcHighMemBwCorruptionAvoidance:skl * Display WA #0883: skl */ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN, intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN) | - ILK_DPFC_DISABLE_DUMMY0); + DPFC_DISABLE_DUMMY0); } static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) From a4b17f757d0b6b4cd4aa2fdc88ae7458235806f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:16 +0200 Subject: [PATCH 132/176] drm/i915/fbc: Finish polishing FBC1 registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch all the FBC1 registers over to REG_BTT()/etc. And while at it add a few more registers/bits that escaped the net previously. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-14-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 62 ++++++++++++++---------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 1c9ada22b4de2..888ee814e8bb3 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -189,7 +189,7 @@ static u32 i965_fbc_ctl2(struct drm_i915_private *i915) FBC_CTL_PLANE(params->crtc.i9xx_plane); if (params->fence_id >= 0) - fbc_ctl2 |= FBC_CTL_CPU_FENCE; + fbc_ctl2 |= FBC_CTL_CPU_FENCE_EN; return fbc_ctl2; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bffb2ac09f610..9a8c294912880 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3307,34 +3307,44 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define FBC_CFB_BASE _MMIO(0x3200) /* 4k page aligned */ #define FBC_LL_BASE _MMIO(0x3204) /* 4k page aligned */ #define FBC_CONTROL _MMIO(0x3208) -#define FBC_CTL_EN REG_BIT(31) -#define FBC_CTL_PERIODIC REG_BIT(30) -#define FBC_CTL_INTERVAL_MASK REG_GENMASK(29, 16) -#define FBC_CTL_INTERVAL(x) REG_FIELD_PREP(FBC_CTL_INTERVAL_MASK, (x)) -#define FBC_CTL_STOP_ON_MOD REG_BIT(15) -#define FBC_CTL_UNCOMPRESSIBLE REG_BIT(14) /* i915+ */ -#define FBC_CTL_C3_IDLE REG_BIT(13) /* i945gm */ -#define FBC_CTL_STRIDE_MASK REG_GENMASK(12, 5) -#define FBC_CTL_STRIDE(x) REG_FIELD_PREP(FBC_CTL_STRIDE_MASK, (x)) -#define FBC_CTL_FENCENO_MASK REG_GENMASK(3, 0) -#define FBC_CTL_FENCENO(x) REG_FIELD_PREP(FBC_CTL_FENCENO_MASK, (x)) +#define FBC_CTL_EN REG_BIT(31) +#define FBC_CTL_PERIODIC REG_BIT(30) +#define FBC_CTL_INTERVAL_MASK REG_GENMASK(29, 16) +#define FBC_CTL_INTERVAL(x) REG_FIELD_PREP(FBC_CTL_INTERVAL_MASK, (x)) +#define FBC_CTL_STOP_ON_MOD REG_BIT(15) +#define FBC_CTL_UNCOMPRESSIBLE REG_BIT(14) /* i915+ */ +#define FBC_CTL_C3_IDLE REG_BIT(13) /* i945gm only */ +#define FBC_CTL_STRIDE_MASK REG_GENMASK(12, 5) +#define FBC_CTL_STRIDE(x) REG_FIELD_PREP(FBC_CTL_STRIDE_MASK, (x)) +#define FBC_CTL_FENCENO_MASK REG_GENMASK(3, 0) +#define FBC_CTL_FENCENO(x) REG_FIELD_PREP(FBC_CTL_FENCENO_MASK, (x)) #define FBC_COMMAND _MMIO(0x320c) -#define FBC_CMD_COMPRESS (1 << 0) +#define FBC_CMD_COMPRESS REG_BIT(0) #define FBC_STATUS _MMIO(0x3210) -#define FBC_STAT_COMPRESSING (1 << 31) -#define FBC_STAT_COMPRESSED (1 << 30) -#define FBC_STAT_MODIFIED (1 << 29) -#define FBC_STAT_CURRENT_LINE_SHIFT (0) -#define FBC_CONTROL2 _MMIO(0x3214) -#define FBC_CTL_FENCE_DBL (0 << 4) -#define FBC_CTL_IDLE_IMM (0 << 2) -#define FBC_CTL_IDLE_FULL (1 << 2) -#define FBC_CTL_IDLE_LINE (2 << 2) -#define FBC_CTL_IDLE_DEBUG (3 << 2) -#define FBC_CTL_CPU_FENCE (1 << 1) -#define FBC_CTL_PLANE(plane) ((plane) << 0) -#define FBC_FENCE_OFF _MMIO(0x3218) /* BSpec typo has 321Bh */ -#define FBC_TAG(i) _MMIO(0x3300 + (i) * 4) +#define FBC_STAT_COMPRESSING REG_BIT(31) +#define FBC_STAT_COMPRESSED REG_BIT(30) +#define FBC_STAT_MODIFIED REG_BIT(29) +#define FBC_STAT_CURRENT_LINE_MASK REG_GENMASK(10, 0) +#define FBC_CONTROL2 _MMIO(0x3214) /* i965gm only */ +#define FBC_CTL_FENCE_DBL REG_BIT(4) +#define FBC_CTL_IDLE_MASK REG_GENMASK(3, 2) +#define FBC_CTL_IDLE_IMM REG_FIELD_PREP(FBC_CTL_IDLE_MASK, 0) +#define FBC_CTL_IDLE_FULL REG_FIELD_PREP(FBC_CTL_IDLE_MASK, 1) +#define FBC_CTL_IDLE_LINE REG_FIELD_PREP(FBC_CTL_IDLE_MASK, 2) +#define FBC_CTL_IDLE_DEBUG REG_FIELD_PREP(FBC_CTL_IDLE_MASK, 3) +#define FBC_CTL_CPU_FENCE_EN REG_BIT(1) +#define FBC_CTL_PLANE_MASK REG_GENMASK(1, 0) +#define FBC_CTL_PLANE(i9xx_plane) REG_FIELD_PREP(FBC_CTL_PLANE_MASK, (i9xx_plane)) +#define FBC_FENCE_OFF _MMIO(0x3218) /* i965gm only, BSpec typo has 321Bh */ +#define FBC_MOD_NUM _MMIO(0x3220) /* i965gm only */ +#define FBC_MOD_NUM_MASK REG_GENMASK(31, 1) +#define FBC_MOD_NUM_VALID REG_BIT(0) +#define FBC_TAG(i) _MMIO(0x3300 + (i) * 4) /* 49 reisters */ +#define FBC_TAG_MASK REG_GENMASK(1, 0) /* 16 tags per register */ +#define FBC_TAG_MODIFIED REG_FIELD_PREP(FBC_TAG_MASK, 0) +#define FBC_TAG_UNCOMPRESSED REG_FIELD_PREP(FBC_TAG_MASK, 1) +#define FBC_TAG_UNCOMPRESSIBLE REG_FIELD_PREP(FBC_TAG_MASK, 2) +#define FBC_TAG_COMPRESSED REG_FIELD_PREP(FBC_TAG_MASK, 3) #define FBC_LL_SIZE (1536) From 9ddfa5a084f65115844e9248903be547a7610a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:17 +0200 Subject: [PATCH 133/176] drm/i915: Relocate FBC_LLC_READ_CTRL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case of FBC_LLC_READ_CTRL the "FBC" stands for frame buffer _caching_, not frame buffer compression. Move the register definition out from the middle of the frame buffer compression register definitions. Let's just stick it somewhere with similar looking register offsets. And while at it switch it over to REG_BIT(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-15-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/i915_reg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9a8c294912880..7d182d2ca7e69 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -371,6 +371,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VLV_G3DCTL _MMIO(0x9024) #define VLV_GSCKGCTL _MMIO(0x9028) +#define FBC_LLC_READ_CTRL _MMIO(0x9044) +#define FBC_LLC_FULLY_OPEN REG_BIT(30) + #define GEN6_MBCTL _MMIO(0x0907c) #define GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4) #define GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3) @@ -3348,9 +3351,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define FBC_LL_SIZE (1536) -#define FBC_LLC_READ_CTRL _MMIO(0x9044) -#define FBC_LLC_FULLY_OPEN (1 << 30) - /* Framebuffer compression for GM45+ */ #define DPFC_CB_BASE _MMIO(0x3200) #define ILK_DPFC_CB_BASE _MMIO(0x43200) From d061882344279ebedb343d463a885118d7dc8978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:18 +0200 Subject: [PATCH 134/176] drm/i915/fbc: s/dev_priv/i915/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename 'dev_priv' to 'i915' to match modern style. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-16-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_fbc.c | 526 +++++++++++------------ 1 file changed, 263 insertions(+), 263 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 888ee814e8bb3..ea3968001c4b7 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -139,17 +139,17 @@ static unsigned int intel_fbc_cfb_stride(struct drm_i915_private *i915, return stride; } -static unsigned int intel_fbc_cfb_size(struct drm_i915_private *dev_priv, +static unsigned int intel_fbc_cfb_size(struct drm_i915_private *i915, const struct intel_fbc_state_cache *cache) { int lines = cache->plane.src_h; - if (DISPLAY_VER(dev_priv) == 7) + if (DISPLAY_VER(i915) == 7) lines = min(lines, 2048); - else if (DISPLAY_VER(dev_priv) >= 8) + else if (DISPLAY_VER(i915) >= 8) lines = min(lines, 2560); - return lines * intel_fbc_cfb_stride(dev_priv, cache); + return lines * intel_fbc_cfb_stride(i915, cache); } static u32 i8xx_fbc_ctl(struct drm_i915_private *i915) @@ -194,50 +194,50 @@ static u32 i965_fbc_ctl2(struct drm_i915_private *i915) return fbc_ctl2; } -static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv) +static void i8xx_fbc_deactivate(struct drm_i915_private *i915) { u32 fbc_ctl; /* Disable compression */ - fbc_ctl = intel_de_read(dev_priv, FBC_CONTROL); + fbc_ctl = intel_de_read(i915, FBC_CONTROL); if ((fbc_ctl & FBC_CTL_EN) == 0) return; fbc_ctl &= ~FBC_CTL_EN; - intel_de_write(dev_priv, FBC_CONTROL, fbc_ctl); + intel_de_write(i915, FBC_CONTROL, fbc_ctl); /* Wait for compressing bit to clear */ - if (intel_de_wait_for_clear(dev_priv, FBC_STATUS, + if (intel_de_wait_for_clear(i915, FBC_STATUS, FBC_STAT_COMPRESSING, 10)) { - drm_dbg_kms(&dev_priv->drm, "FBC idle timed out\n"); + drm_dbg_kms(&i915->drm, "FBC idle timed out\n"); return; } } -static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) +static void i8xx_fbc_activate(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_reg_params *params = &fbc->params; int i; /* Clear old tags */ for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) - intel_de_write(dev_priv, FBC_TAG(i), 0); + intel_de_write(i915, FBC_TAG(i), 0); - if (DISPLAY_VER(dev_priv) == 4) { - intel_de_write(dev_priv, FBC_CONTROL2, - i965_fbc_ctl2(dev_priv)); - intel_de_write(dev_priv, FBC_FENCE_OFF, + if (DISPLAY_VER(i915) == 4) { + intel_de_write(i915, FBC_CONTROL2, + i965_fbc_ctl2(i915)); + intel_de_write(i915, FBC_FENCE_OFF, params->fence_y_offset); } - intel_de_write(dev_priv, FBC_CONTROL, - FBC_CTL_EN | i8xx_fbc_ctl(dev_priv)); + intel_de_write(i915, FBC_CONTROL, + FBC_CTL_EN | i8xx_fbc_ctl(i915)); } -static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv) +static bool i8xx_fbc_is_active(struct drm_i915_private *i915) { - return intel_de_read(dev_priv, FBC_CONTROL) & FBC_CTL_EN; + return intel_de_read(i915, FBC_CONTROL) & FBC_CTL_EN; } static bool i8xx_fbc_is_compressing(struct drm_i915_private *i915) @@ -337,32 +337,32 @@ static u32 g4x_dpfc_ctl(struct drm_i915_private *i915) return dpfc_ctl; } -static void g4x_fbc_activate(struct drm_i915_private *dev_priv) +static void g4x_fbc_activate(struct drm_i915_private *i915) { - const struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + const struct intel_fbc_reg_params *params = &i915->fbc.params; - intel_de_write(dev_priv, DPFC_FENCE_YOFF, + intel_de_write(i915, DPFC_FENCE_YOFF, params->fence_y_offset); - intel_de_write(dev_priv, DPFC_CONTROL, - DPFC_CTL_EN | g4x_dpfc_ctl(dev_priv)); + intel_de_write(i915, DPFC_CONTROL, + DPFC_CTL_EN | g4x_dpfc_ctl(i915)); } -static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv) +static void g4x_fbc_deactivate(struct drm_i915_private *i915) { u32 dpfc_ctl; /* Disable compression */ - dpfc_ctl = intel_de_read(dev_priv, DPFC_CONTROL); + dpfc_ctl = intel_de_read(i915, DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { dpfc_ctl &= ~DPFC_CTL_EN; - intel_de_write(dev_priv, DPFC_CONTROL, dpfc_ctl); + intel_de_write(i915, DPFC_CONTROL, dpfc_ctl); } } -static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv) +static bool g4x_fbc_is_active(struct drm_i915_private *i915) { - return intel_de_read(dev_priv, DPFC_CONTROL) & DPFC_CTL_EN; + return intel_de_read(i915, DPFC_CONTROL) & DPFC_CTL_EN; } static bool g4x_fbc_is_compressing(struct drm_i915_private *i915) @@ -386,32 +386,32 @@ static const struct intel_fbc_funcs g4x_fbc_funcs = { .program_cfb = g4x_fbc_program_cfb, }; -static void ilk_fbc_activate(struct drm_i915_private *dev_priv) +static void ilk_fbc_activate(struct drm_i915_private *i915) { - struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + struct intel_fbc_reg_params *params = &i915->fbc.params; - intel_de_write(dev_priv, ILK_DPFC_FENCE_YOFF, + intel_de_write(i915, ILK_DPFC_FENCE_YOFF, params->fence_y_offset); - intel_de_write(dev_priv, ILK_DPFC_CONTROL, - DPFC_CTL_EN | g4x_dpfc_ctl(dev_priv)); + intel_de_write(i915, ILK_DPFC_CONTROL, + DPFC_CTL_EN | g4x_dpfc_ctl(i915)); } -static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv) +static void ilk_fbc_deactivate(struct drm_i915_private *i915) { u32 dpfc_ctl; /* Disable compression */ - dpfc_ctl = intel_de_read(dev_priv, ILK_DPFC_CONTROL); + dpfc_ctl = intel_de_read(i915, ILK_DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { dpfc_ctl &= ~DPFC_CTL_EN; - intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl); + intel_de_write(i915, ILK_DPFC_CONTROL, dpfc_ctl); } } -static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv) +static bool ilk_fbc_is_active(struct drm_i915_private *i915) { - return intel_de_read(dev_priv, ILK_DPFC_CONTROL) & DPFC_CTL_EN; + return intel_de_read(i915, ILK_DPFC_CONTROL) & DPFC_CTL_EN; } static bool ilk_fbc_is_compressing(struct drm_i915_private *i915) @@ -447,17 +447,17 @@ static void snb_fbc_program_fence(struct drm_i915_private *i915) intel_de_write(i915, SNB_DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); } -static void snb_fbc_activate(struct drm_i915_private *dev_priv) +static void snb_fbc_activate(struct drm_i915_private *i915) { - snb_fbc_program_fence(dev_priv); + snb_fbc_program_fence(i915); - ilk_fbc_activate(dev_priv); + ilk_fbc_activate(i915); } -static void snb_fbc_nuke(struct drm_i915_private *dev_priv) +static void snb_fbc_nuke(struct drm_i915_private *i915) { - intel_de_write(dev_priv, MSG_FBC_REND_STATE, FBC_REND_NUKE); - intel_de_posting_read(dev_priv, MSG_FBC_REND_STATE); + intel_de_write(i915, MSG_FBC_REND_STATE, FBC_REND_NUKE); + intel_de_posting_read(i915, MSG_FBC_REND_STATE); } static const struct intel_fbc_funcs snb_fbc_funcs = { @@ -517,18 +517,18 @@ static u32 ivb_dpfc_ctl(struct drm_i915_private *i915) return dpfc_ctl; } -static void ivb_fbc_activate(struct drm_i915_private *dev_priv) +static void ivb_fbc_activate(struct drm_i915_private *i915) { - if (DISPLAY_VER(dev_priv) >= 10) - glk_fbc_program_cfb_stride(dev_priv); - else if (DISPLAY_VER(dev_priv) == 9) - skl_fbc_program_cfb_stride(dev_priv); + if (DISPLAY_VER(i915) >= 10) + glk_fbc_program_cfb_stride(i915); + else if (DISPLAY_VER(i915) == 9) + skl_fbc_program_cfb_stride(i915); - if (dev_priv->ggtt.num_fences) - snb_fbc_program_fence(dev_priv); + if (i915->ggtt.num_fences) + snb_fbc_program_fence(i915); - intel_de_write(dev_priv, ILK_DPFC_CONTROL, - DPFC_CTL_EN | ivb_dpfc_ctl(dev_priv)); + intel_de_write(i915, ILK_DPFC_CONTROL, + DPFC_CTL_EN | ivb_dpfc_ctl(i915)); } static bool ivb_fbc_is_compressing(struct drm_i915_private *i915) @@ -553,34 +553,34 @@ static const struct intel_fbc_funcs ivb_fbc_funcs = { .set_false_color = ivb_fbc_set_false_color, }; -static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) +static bool intel_fbc_hw_is_active(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - return fbc->funcs->is_active(dev_priv); + return fbc->funcs->is_active(i915); } -static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) +static void intel_fbc_hw_activate(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; trace_intel_fbc_activate(fbc->crtc); fbc->active = true; fbc->activated = true; - fbc->funcs->activate(dev_priv); + fbc->funcs->activate(i915); } -static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv) +static void intel_fbc_hw_deactivate(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; trace_intel_fbc_deactivate(fbc->crtc); fbc->active = false; - fbc->funcs->deactivate(dev_priv); + fbc->funcs->deactivate(i915); } bool intel_fbc_is_compressing(struct drm_i915_private *i915) @@ -619,33 +619,33 @@ int intel_fbc_set_false_color(struct drm_i915_private *i915, bool enable) /** * intel_fbc_is_active - Is FBC active? - * @dev_priv: i915 device instance + * @i915: i915 device instance * * This function is used to verify the current state of FBC. * * FIXME: This should be tracked in the plane config eventually * instead of queried at runtime for most callers. */ -bool intel_fbc_is_active(struct drm_i915_private *dev_priv) +bool intel_fbc_is_active(struct drm_i915_private *i915) { - return dev_priv->fbc.active; + return i915->fbc.active; } -static void intel_fbc_activate(struct drm_i915_private *dev_priv) +static void intel_fbc_activate(struct drm_i915_private *i915) { - intel_fbc_hw_activate(dev_priv); - intel_fbc_nuke(dev_priv); + intel_fbc_hw_activate(i915); + intel_fbc_nuke(i915); } -static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, +static void intel_fbc_deactivate(struct drm_i915_private *i915, const char *reason) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - drm_WARN_ON(&dev_priv->drm, !mutex_is_locked(&fbc->lock)); + drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); if (fbc->active) - intel_fbc_hw_deactivate(dev_priv); + intel_fbc_hw_deactivate(i915); fbc->no_fbc_reason = reason; } @@ -658,7 +658,7 @@ static u64 intel_fbc_cfb_base_max(struct drm_i915_private *i915) return BIT_ULL(32); } -static u64 intel_fbc_stolen_end(struct drm_i915_private *dev_priv) +static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) { u64 end; @@ -666,13 +666,13 @@ static u64 intel_fbc_stolen_end(struct drm_i915_private *dev_priv) * reserved range size, so it always assumes the maximum (8mb) is used. * If we enable FBC using a CFB on that memory range we'll get FIFO * underruns, even if that range is not reserved by the BIOS. */ - if (IS_BROADWELL(dev_priv) || (DISPLAY_VER(dev_priv) == 9 && - !IS_BROXTON(dev_priv))) - end = resource_size(&dev_priv->dsm) - 8 * 1024 * 1024; + if (IS_BROADWELL(i915) || + (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) + end = resource_size(&i915->dsm) - 8 * 1024 * 1024; else end = U64_MAX; - return min(end, intel_fbc_cfb_base_max(dev_priv)); + return min(end, intel_fbc_cfb_base_max(i915)); } static int intel_fbc_min_limit(int fb_cpp) @@ -680,10 +680,10 @@ static int intel_fbc_min_limit(int fb_cpp) return fb_cpp == 2 ? 2 : 1; } -static int intel_fbc_max_limit(struct drm_i915_private *dev_priv) +static int intel_fbc_max_limit(struct drm_i915_private *i915) { /* WaFbcOnly1to1Ratio:ctg */ - if (IS_G4X(dev_priv)) + if (IS_G4X(i915)) return 1; /* @@ -693,23 +693,23 @@ static int intel_fbc_max_limit(struct drm_i915_private *dev_priv) return 4; } -static int find_compression_limit(struct drm_i915_private *dev_priv, +static int find_compression_limit(struct drm_i915_private *i915, unsigned int size, int min_limit) { - struct intel_fbc *fbc = &dev_priv->fbc; - u64 end = intel_fbc_stolen_end(dev_priv); + struct intel_fbc *fbc = &i915->fbc; + u64 end = intel_fbc_stolen_end(i915); int ret, limit = min_limit; size /= limit; /* Try to over-allocate to reduce reallocations and fragmentation. */ - ret = i915_gem_stolen_insert_node_in_range(dev_priv, &fbc->compressed_fb, + ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb, size <<= 1, 4096, 0, end); if (ret == 0) return limit; - for (; limit <= intel_fbc_max_limit(dev_priv); limit <<= 1) { - ret = i915_gem_stolen_insert_node_in_range(dev_priv, &fbc->compressed_fb, + for (; limit <= intel_fbc_max_limit(i915); limit <<= 1) { + ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb, size >>= 1, 4096, 0, end); if (ret == 0) return limit; @@ -718,34 +718,34 @@ static int find_compression_limit(struct drm_i915_private *dev_priv, return 0; } -static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, +static int intel_fbc_alloc_cfb(struct drm_i915_private *i915, unsigned int size, int min_limit) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; int ret; - drm_WARN_ON(&dev_priv->drm, + drm_WARN_ON(&i915->drm, drm_mm_node_allocated(&fbc->compressed_fb)); - drm_WARN_ON(&dev_priv->drm, + drm_WARN_ON(&i915->drm, drm_mm_node_allocated(&fbc->compressed_llb)); - if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) { - ret = i915_gem_stolen_insert_node(dev_priv, &fbc->compressed_llb, + if (DISPLAY_VER(i915) < 5 && !IS_G4X(i915)) { + ret = i915_gem_stolen_insert_node(i915, &fbc->compressed_llb, 4096, 4096); if (ret) goto err; } - ret = find_compression_limit(dev_priv, size, min_limit); + ret = find_compression_limit(i915, size, min_limit); if (!ret) goto err_llb; else if (ret > min_limit) - drm_info_once(&dev_priv->drm, + drm_info_once(&i915->drm, "Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n"); fbc->limit = ret; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n", fbc->compressed_fb.size, fbc->limit); @@ -753,64 +753,64 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, err_llb: if (drm_mm_node_allocated(&fbc->compressed_llb)) - i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_llb); + i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); err: - if (drm_mm_initialized(&dev_priv->mm.stolen)) - drm_info_once(&dev_priv->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); + if (drm_mm_initialized(&i915->mm.stolen)) + drm_info_once(&i915->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); return -ENOSPC; } -static void intel_fbc_program_cfb(struct drm_i915_private *dev_priv) +static void intel_fbc_program_cfb(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - fbc->funcs->program_cfb(dev_priv); + fbc->funcs->program_cfb(i915); } -static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) +static void __intel_fbc_cleanup_cfb(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (WARN_ON(intel_fbc_hw_is_active(dev_priv))) + if (WARN_ON(intel_fbc_hw_is_active(i915))) return; if (drm_mm_node_allocated(&fbc->compressed_llb)) - i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_llb); + i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); if (drm_mm_node_allocated(&fbc->compressed_fb)) - i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb); + i915_gem_stolen_remove_node(i915, &fbc->compressed_fb); } -void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) +void intel_fbc_cleanup_cfb(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(i915)) return; mutex_lock(&fbc->lock); - __intel_fbc_cleanup_cfb(dev_priv); + __intel_fbc_cleanup_cfb(i915); mutex_unlock(&fbc->lock); } -static bool stride_is_valid(struct drm_i915_private *dev_priv, +static bool stride_is_valid(struct drm_i915_private *i915, u64 modifier, unsigned int stride) { /* This should have been caught earlier. */ - if (drm_WARN_ON_ONCE(&dev_priv->drm, (stride & (64 - 1)) != 0)) + if (drm_WARN_ON_ONCE(&i915->drm, (stride & (64 - 1)) != 0)) return false; /* Below are the additional FBC restrictions. */ if (stride < 512) return false; - if (DISPLAY_VER(dev_priv) == 2 || DISPLAY_VER(dev_priv) == 3) + if (DISPLAY_VER(i915) == 2 || DISPLAY_VER(i915) == 3) return stride == 4096 || stride == 8192; - if (DISPLAY_VER(dev_priv) == 4 && !IS_G4X(dev_priv) && stride < 2048) + if (DISPLAY_VER(i915) == 4 && !IS_G4X(i915) && stride < 2048) return false; /* Display WA #1105: skl,bxt,kbl,cfl,glk */ - if ((DISPLAY_VER(dev_priv) == 9 || IS_GEMINILAKE(dev_priv)) && + if ((DISPLAY_VER(i915) == 9 || IS_GEMINILAKE(i915)) && modifier == DRM_FORMAT_MOD_LINEAR && stride & 511) return false; @@ -820,7 +820,7 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv, return true; } -static bool pixel_format_is_valid(struct drm_i915_private *dev_priv, +static bool pixel_format_is_valid(struct drm_i915_private *i915, u32 pixel_format) { switch (pixel_format) { @@ -830,10 +830,10 @@ static bool pixel_format_is_valid(struct drm_i915_private *dev_priv, case DRM_FORMAT_XRGB1555: case DRM_FORMAT_RGB565: /* 16bpp not supported on gen2 */ - if (DISPLAY_VER(dev_priv) == 2) + if (DISPLAY_VER(i915) == 2) return false; /* WaFbcOnly1to1Ratio:ctg */ - if (IS_G4X(dev_priv)) + if (IS_G4X(i915)) return false; return true; default: @@ -841,13 +841,13 @@ static bool pixel_format_is_valid(struct drm_i915_private *dev_priv, } } -static bool rotation_is_valid(struct drm_i915_private *dev_priv, +static bool rotation_is_valid(struct drm_i915_private *i915, u32 pixel_format, unsigned int rotation) { - if (DISPLAY_VER(dev_priv) >= 9 && pixel_format == DRM_FORMAT_RGB565 && + if (DISPLAY_VER(i915) >= 9 && pixel_format == DRM_FORMAT_RGB565 && drm_rotation_90_or_270(rotation)) return false; - else if (DISPLAY_VER(dev_priv) <= 4 && !IS_G4X(dev_priv) && + else if (DISPLAY_VER(i915) <= 4 && !IS_G4X(i915) && rotation != DRM_MODE_ROTATE_0) return false; @@ -862,17 +862,17 @@ static bool rotation_is_valid(struct drm_i915_private *dev_priv, */ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_fbc *fbc = &i915->fbc; unsigned int effective_w, effective_h, max_w, max_h; - if (DISPLAY_VER(dev_priv) >= 10) { + if (DISPLAY_VER(i915) >= 10) { max_w = 5120; max_h = 4096; - } else if (DISPLAY_VER(dev_priv) >= 8 || IS_HASWELL(dev_priv)) { + } else if (DISPLAY_VER(i915) >= 8 || IS_HASWELL(i915)) { max_w = 4096; max_h = 4096; - } else if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5) { + } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { max_w = 4096; max_h = 2048; } else { @@ -888,14 +888,14 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) return effective_w <= max_w && effective_h <= max_h; } -static bool tiling_is_valid(struct drm_i915_private *dev_priv, +static bool tiling_is_valid(struct drm_i915_private *i915, u64 modifier) { switch (modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: - return DISPLAY_VER(dev_priv) >= 9; + return DISPLAY_VER(i915) >= 9; case I915_FORMAT_MOD_X_TILED: return true; default: @@ -907,8 +907,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_fbc *fbc = &i915->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; struct drm_framebuffer *fb = plane_state->hw.fb; @@ -917,7 +917,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, return; cache->crtc.mode_flags = crtc_state->hw.adjusted_mode.flags; - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + if (IS_HASWELL(i915) || IS_BROADWELL(i915)) cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate; cache->plane.rotation = plane_state->hw.rotation; @@ -942,7 +942,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->fence_y_offset = intel_plane_fence_y_offset(plane_state); - drm_WARN_ON(&dev_priv->drm, plane_state->flags & PLANE_HAS_FENCE && + drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE && !plane_state->ggtt_vma->fence); if (plane_state->flags & PLANE_HAS_FENCE && @@ -954,19 +954,19 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->psr2_active = crtc_state->has_psr2; } -static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv) +static bool intel_fbc_cfb_size_changed(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - return intel_fbc_cfb_size(dev_priv, &fbc->state_cache) > + return intel_fbc_cfb_size(i915, &fbc->state_cache) > fbc->compressed_fb.size * fbc->limit; } -static u16 intel_fbc_override_cfb_stride(struct drm_i915_private *dev_priv, +static u16 intel_fbc_override_cfb_stride(struct drm_i915_private *i915, const struct intel_fbc_state_cache *cache) { unsigned int stride = _intel_fbc_cfb_stride(cache); - unsigned int stride_aligned = intel_fbc_cfb_stride(dev_priv, cache); + unsigned int stride_aligned = intel_fbc_cfb_stride(i915, cache); /* * Override stride in 64 byte units per 4 line segment. @@ -976,23 +976,23 @@ static u16 intel_fbc_override_cfb_stride(struct drm_i915_private *dev_priv, * we always need to use the override there. */ if (stride != stride_aligned || - (DISPLAY_VER(dev_priv) == 9 && + (DISPLAY_VER(i915) == 9 && cache->fb.modifier == DRM_FORMAT_MOD_LINEAR)) return stride_aligned * 4 / 64; return 0; } -static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv) +static bool intel_fbc_can_enable(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (intel_vgpu_active(dev_priv)) { + if (intel_vgpu_active(i915)) { fbc->no_fbc_reason = "VGPU is active"; return false; } - if (!dev_priv->params.enable_fbc) { + if (!i915->params.enable_fbc) { fbc->no_fbc_reason = "disabled per module param or by default"; return false; } @@ -1007,11 +1007,11 @@ static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv) static bool intel_fbc_can_activate(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_fbc *fbc = &i915->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; - if (!intel_fbc_can_enable(dev_priv)) + if (!intel_fbc_can_enable(i915)) return false; if (!cache->plane.visible) { @@ -1054,28 +1054,28 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * For now this will effectively disable FBC with 90/270 degree * rotation. */ - if (DISPLAY_VER(dev_priv) < 9 && cache->fence_id < 0) { + if (DISPLAY_VER(i915) < 9 && cache->fence_id < 0) { fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } - if (!pixel_format_is_valid(dev_priv, cache->fb.format->format)) { + if (!pixel_format_is_valid(i915, cache->fb.format->format)) { fbc->no_fbc_reason = "pixel format is invalid"; return false; } - if (!rotation_is_valid(dev_priv, cache->fb.format->format, + if (!rotation_is_valid(i915, cache->fb.format->format, cache->plane.rotation)) { fbc->no_fbc_reason = "rotation unsupported"; return false; } - if (!tiling_is_valid(dev_priv, cache->fb.modifier)) { + if (!tiling_is_valid(i915, cache->fb.modifier)) { fbc->no_fbc_reason = "tiling unsupported"; return false; } - if (!stride_is_valid(dev_priv, cache->fb.modifier, + if (!stride_is_valid(i915, cache->fb.modifier, cache->fb.stride * cache->fb.format->cpp[0])) { fbc->no_fbc_reason = "framebuffer stride not supported"; return false; @@ -1088,8 +1088,8 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) } /* WaFbcExceedCdClockThreshold:hsw,bdw */ - if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && - cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) { + if ((IS_HASWELL(i915) || IS_BROADWELL(i915)) && + cache->crtc.hsw_bdw_pixel_rate >= i915->cdclk.hw.cdclk * 95 / 100) { fbc->no_fbc_reason = "pixel rate is too big"; return false; } @@ -1104,7 +1104,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * we didn't get any invalidate/deactivate calls, but this would require * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ - if (intel_fbc_cfb_size_changed(dev_priv)) { + if (intel_fbc_cfb_size_changed(i915)) { fbc->no_fbc_reason = "CFB requirements changed"; return false; } @@ -1114,14 +1114,14 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * having a Y offset that isn't divisible by 4 causes FIFO underrun * and screen flicker. */ - if (DISPLAY_VER(dev_priv) >= 9 && + if (DISPLAY_VER(i915) >= 9 && (fbc->state_cache.plane.adjusted_y & 3)) { fbc->no_fbc_reason = "plane Y offset is misaligned"; return false; } /* Wa_22010751166: icl, ehl, tgl, dg1, rkl */ - if (DISPLAY_VER(dev_priv) >= 11 && + if (DISPLAY_VER(i915) >= 11 && (cache->plane.src_h + cache->plane.adjusted_y) % 4) { fbc->no_fbc_reason = "plane height + offset is non-modulo of 4"; return false; @@ -1132,7 +1132,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * Recommendation is to keep this combination disabled * Bspec: 50422 HSD: 14010260002 */ - if (fbc->state_cache.psr2_active && DISPLAY_VER(dev_priv) >= 12) { + if (fbc->state_cache.psr2_active && DISPLAY_VER(i915) >= 12) { fbc->no_fbc_reason = "not supported with PSR2"; return false; } @@ -1143,8 +1143,8 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) static void intel_fbc_get_reg_params(struct intel_crtc *crtc, struct intel_fbc_reg_params *params) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_fbc *fbc = &i915->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; /* Since all our fields are integer types, use memset here so the @@ -1164,9 +1164,9 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->fb.modifier = cache->fb.modifier; params->fb.stride = cache->fb.stride; - params->cfb_stride = intel_fbc_cfb_stride(dev_priv, cache); - params->cfb_size = intel_fbc_cfb_size(dev_priv, cache); - params->override_cfb_stride = intel_fbc_override_cfb_stride(dev_priv, cache); + params->cfb_stride = intel_fbc_cfb_stride(i915, cache); + params->cfb_size = intel_fbc_cfb_size(i915, cache); + params->override_cfb_stride = intel_fbc_override_cfb_stride(i915, cache); params->plane_visible = cache->plane.visible; } @@ -1174,8 +1174,8 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + const struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_state_cache *cache = &fbc->state_cache; const struct intel_fbc_reg_params *params = &fbc->params; @@ -1197,13 +1197,13 @@ static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) if (params->fb.stride != cache->fb.stride) return false; - if (params->cfb_stride != intel_fbc_cfb_stride(dev_priv, cache)) + if (params->cfb_stride != intel_fbc_cfb_stride(i915, cache)) return false; - if (params->cfb_size != intel_fbc_cfb_size(dev_priv, cache)) + if (params->cfb_size != intel_fbc_cfb_size(i915, cache)) return false; - if (params->override_cfb_stride != intel_fbc_override_cfb_stride(dev_priv, cache)) + if (params->override_cfb_stride != intel_fbc_override_cfb_stride(i915, cache)) return false; return true; @@ -1217,8 +1217,8 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_fbc *fbc = &i915->fbc; const char *reason = "update pending"; bool need_vblank_wait = false; @@ -1234,7 +1234,7 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, fbc->flip_pending = true; if (!intel_fbc_can_flip_nuke(crtc_state)) { - intel_fbc_deactivate(dev_priv, reason); + intel_fbc_deactivate(i915, reason); /* * Display WA #1198: glk+ @@ -1250,7 +1250,7 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, * if at least one frame has already passed. */ if (fbc->activated && - DISPLAY_VER(dev_priv) >= 10) + DISPLAY_VER(i915) >= 10) need_vblank_wait = true; fbc->activated = false; } @@ -1262,43 +1262,43 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, /** * __intel_fbc_disable - disable FBC - * @dev_priv: i915 device instance + * @i915: i915 device instance * * This is the low level function that actually disables FBC. Callers should * grab the FBC lock. */ -static void __intel_fbc_disable(struct drm_i915_private *dev_priv) +static void __intel_fbc_disable(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; struct intel_crtc *crtc = fbc->crtc; - drm_WARN_ON(&dev_priv->drm, !mutex_is_locked(&fbc->lock)); - drm_WARN_ON(&dev_priv->drm, !fbc->crtc); - drm_WARN_ON(&dev_priv->drm, fbc->active); + drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); + drm_WARN_ON(&i915->drm, !fbc->crtc); + drm_WARN_ON(&i915->drm, fbc->active); - drm_dbg_kms(&dev_priv->drm, "Disabling FBC on pipe %c\n", + drm_dbg_kms(&i915->drm, "Disabling FBC on pipe %c\n", pipe_name(crtc->pipe)); - __intel_fbc_cleanup_cfb(dev_priv); + __intel_fbc_cleanup_cfb(i915); fbc->crtc = NULL; } static void __intel_fbc_post_update(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_fbc *fbc = &i915->fbc; - drm_WARN_ON(&dev_priv->drm, !mutex_is_locked(&fbc->lock)); + drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); if (fbc->crtc != crtc) return; fbc->flip_pending = false; - if (!dev_priv->params.enable_fbc) { - intel_fbc_deactivate(dev_priv, "disabled at runtime per module param"); - __intel_fbc_disable(dev_priv); + if (!i915->params.enable_fbc) { + intel_fbc_deactivate(i915, "disabled at runtime per module param"); + __intel_fbc_disable(i915); return; } @@ -1309,19 +1309,19 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) return; if (!fbc->busy_bits) - intel_fbc_activate(dev_priv); + intel_fbc_activate(i915); else - intel_fbc_deactivate(dev_priv, "frontbuffer write"); + intel_fbc_deactivate(i915, "frontbuffer write"); } void intel_fbc_post_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; if (!plane->has_fbc || !plane_state) return; @@ -1339,13 +1339,13 @@ static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc) return fbc->possible_framebuffer_bits; } -void intel_fbc_invalidate(struct drm_i915_private *dev_priv, +void intel_fbc_invalidate(struct drm_i915_private *i915, unsigned int frontbuffer_bits, enum fb_op_origin origin) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(i915)) return; if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE) @@ -1356,17 +1356,17 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; if (fbc->crtc && fbc->busy_bits) - intel_fbc_deactivate(dev_priv, "frontbuffer write"); + intel_fbc_deactivate(i915, "frontbuffer write"); mutex_unlock(&fbc->lock); } -void intel_fbc_flush(struct drm_i915_private *dev_priv, +void intel_fbc_flush(struct drm_i915_private *i915, unsigned int frontbuffer_bits, enum fb_op_origin origin) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(i915)) return; mutex_lock(&fbc->lock); @@ -1379,7 +1379,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (!fbc->busy_bits && fbc->crtc && (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) { if (fbc->active) - intel_fbc_nuke(dev_priv); + intel_fbc_nuke(i915); else if (!fbc->flip_pending) __intel_fbc_post_update(fbc->crtc); } @@ -1390,7 +1390,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, /** * intel_fbc_choose_crtc - select a CRTC to enable FBC on - * @dev_priv: i915 device instance + * @i915: i915 device instance * @state: the atomic state structure * * This function looks at the proposed state for CRTCs and planes, then chooses @@ -1398,12 +1398,12 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, * true. * * Later, intel_fbc_enable is going to look for state->enable_fbc and then maybe - * enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc. + * enable FBC for the chosen CRTC. If it does, it will set i915->fbc.crtc. */ -void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, +void intel_fbc_choose_crtc(struct drm_i915_private *i915, struct intel_atomic_state *state) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; struct intel_plane *plane; struct intel_plane_state *plane_state; bool crtc_chosen = false; @@ -1416,7 +1416,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, !intel_atomic_get_new_crtc_state(state, fbc->crtc)) goto out; - if (!intel_fbc_can_enable(dev_priv)) + if (!intel_fbc_can_enable(i915)) goto out; /* Simply choose the first CRTC that is compatible and has a visible @@ -1460,13 +1460,13 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, static void intel_fbc_enable(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; int min_limit; @@ -1483,13 +1483,13 @@ static void intel_fbc_enable(struct intel_atomic_state *state, goto out; if (fbc->limit >= min_limit && - !intel_fbc_cfb_size_changed(dev_priv)) + !intel_fbc_cfb_size_changed(i915)) goto out; - __intel_fbc_disable(dev_priv); + __intel_fbc_disable(i915); } - drm_WARN_ON(&dev_priv->drm, fbc->active); + drm_WARN_ON(&i915->drm, fbc->active); intel_fbc_update_state_cache(crtc, crtc_state, plane_state); @@ -1497,20 +1497,20 @@ static void intel_fbc_enable(struct intel_atomic_state *state, if (!cache->plane.visible) goto out; - if (intel_fbc_alloc_cfb(dev_priv, - intel_fbc_cfb_size(dev_priv, cache), min_limit)) { + if (intel_fbc_alloc_cfb(i915, + intel_fbc_cfb_size(i915, cache), min_limit)) { cache->plane.visible = false; fbc->no_fbc_reason = "not enough stolen memory"; goto out; } - drm_dbg_kms(&dev_priv->drm, "Enabling FBC on pipe %c\n", + drm_dbg_kms(&i915->drm, "Enabling FBC on pipe %c\n", pipe_name(crtc->pipe)); fbc->no_fbc_reason = "FBC enabled but not active yet\n"; fbc->crtc = crtc; - intel_fbc_program_cfb(dev_priv); + intel_fbc_program_cfb(i915); out: mutex_unlock(&fbc->lock); } @@ -1523,16 +1523,16 @@ static void intel_fbc_enable(struct intel_atomic_state *state, */ void intel_fbc_disable(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; if (!plane->has_fbc) return; mutex_lock(&fbc->lock); if (fbc->crtc == crtc) - __intel_fbc_disable(dev_priv); + __intel_fbc_disable(i915); mutex_unlock(&fbc->lock); } @@ -1560,30 +1560,30 @@ void intel_fbc_update(struct intel_atomic_state *state, /** * intel_fbc_global_disable - globally disable FBC - * @dev_priv: i915 device instance + * @i915: i915 device instance * * This function disables FBC regardless of which CRTC is associated with it. */ -void intel_fbc_global_disable(struct drm_i915_private *dev_priv) +void intel_fbc_global_disable(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(i915)) return; mutex_lock(&fbc->lock); if (fbc->crtc) { - drm_WARN_ON(&dev_priv->drm, fbc->crtc->active); - __intel_fbc_disable(dev_priv); + drm_WARN_ON(&i915->drm, fbc->crtc->active); + __intel_fbc_disable(i915); } mutex_unlock(&fbc->lock); } static void intel_fbc_underrun_work_fn(struct work_struct *work) { - struct drm_i915_private *dev_priv = + struct drm_i915_private *i915 = container_of(work, struct drm_i915_private, fbc.underrun_work); - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; mutex_lock(&fbc->lock); @@ -1591,46 +1591,46 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) if (fbc->underrun_detected || !fbc->crtc) goto out; - drm_dbg_kms(&dev_priv->drm, "Disabling FBC due to FIFO underrun.\n"); + drm_dbg_kms(&i915->drm, "Disabling FBC due to FIFO underrun.\n"); fbc->underrun_detected = true; - intel_fbc_deactivate(dev_priv, "FIFO underrun"); + intel_fbc_deactivate(i915, "FIFO underrun"); out: mutex_unlock(&fbc->lock); } /* * intel_fbc_reset_underrun - reset FBC fifo underrun status. - * @dev_priv: i915 device instance + * @i915: i915 device instance * * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we * want to re-enable FBC after an underrun to increase test coverage. */ -int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv) +int intel_fbc_reset_underrun(struct drm_i915_private *i915) { int ret; - cancel_work_sync(&dev_priv->fbc.underrun_work); + cancel_work_sync(&i915->fbc.underrun_work); - ret = mutex_lock_interruptible(&dev_priv->fbc.lock); + ret = mutex_lock_interruptible(&i915->fbc.lock); if (ret) return ret; - if (dev_priv->fbc.underrun_detected) { - drm_dbg_kms(&dev_priv->drm, + if (i915->fbc.underrun_detected) { + drm_dbg_kms(&i915->drm, "Re-allowing FBC after fifo underrun\n"); - dev_priv->fbc.no_fbc_reason = "FIFO underrun cleared"; + i915->fbc.no_fbc_reason = "FIFO underrun cleared"; } - dev_priv->fbc.underrun_detected = false; - mutex_unlock(&dev_priv->fbc.lock); + i915->fbc.underrun_detected = false; + mutex_unlock(&i915->fbc.lock); return 0; } /** * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun - * @dev_priv: i915 device instance + * @i915: i915 device instance * * Without FBC, most underruns are harmless and don't really cause too many * problems, except for an annoying message on dmesg. With FBC, underruns can @@ -1642,11 +1642,11 @@ int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv) * * This function is called from the IRQ handler. */ -void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv) +void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(i915)) return; /* There's no guarantee that underrun_detected won't be set to true @@ -1670,26 +1670,26 @@ void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv) * space to change the value during runtime without sanitizing it again. IGT * relies on being able to change i915.enable_fbc at runtime. */ -static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) +static int intel_sanitize_fbc_option(struct drm_i915_private *i915) { - if (dev_priv->params.enable_fbc >= 0) - return !!dev_priv->params.enable_fbc; + if (i915->params.enable_fbc >= 0) + return !!i915->params.enable_fbc; - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(i915)) return 0; - if (IS_BROADWELL(dev_priv) || DISPLAY_VER(dev_priv) >= 9) + if (IS_BROADWELL(i915) || DISPLAY_VER(i915) >= 9) return 1; return 0; } -static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv) +static bool need_fbc_vtd_wa(struct drm_i915_private *i915) { /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ if (intel_vtd_active() && - (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))) { - drm_info(&dev_priv->drm, + (IS_SKYLAKE(i915) || IS_BROXTON(i915))) { + drm_info(&i915->drm, "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n"); return true; } @@ -1699,42 +1699,42 @@ static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv) /** * intel_fbc_init - Initialize FBC - * @dev_priv: the i915 device + * @i915: the i915 device * * This function might be called during PM init process. */ -void intel_fbc_init(struct drm_i915_private *dev_priv) +void intel_fbc_init(struct drm_i915_private *i915) { - struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc *fbc = &i915->fbc; INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); mutex_init(&fbc->lock); fbc->active = false; - if (!drm_mm_initialized(&dev_priv->mm.stolen)) - mkwrite_device_info(dev_priv)->display.has_fbc = false; + if (!drm_mm_initialized(&i915->mm.stolen)) + mkwrite_device_info(i915)->display.has_fbc = false; - if (need_fbc_vtd_wa(dev_priv)) - mkwrite_device_info(dev_priv)->display.has_fbc = false; + if (need_fbc_vtd_wa(i915)) + mkwrite_device_info(i915)->display.has_fbc = false; - dev_priv->params.enable_fbc = intel_sanitize_fbc_option(dev_priv); - drm_dbg_kms(&dev_priv->drm, "Sanitized enable_fbc value: %d\n", - dev_priv->params.enable_fbc); + i915->params.enable_fbc = intel_sanitize_fbc_option(i915); + drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n", + i915->params.enable_fbc); - if (!HAS_FBC(dev_priv)) { + if (!HAS_FBC(i915)) { fbc->no_fbc_reason = "unsupported by this chipset"; return; } - if (DISPLAY_VER(dev_priv) >= 7) + if (DISPLAY_VER(i915) >= 7) fbc->funcs = &ivb_fbc_funcs; - else if (DISPLAY_VER(dev_priv) == 6) + else if (DISPLAY_VER(i915) == 6) fbc->funcs = &snb_fbc_funcs; - else if (DISPLAY_VER(dev_priv) == 5) + else if (DISPLAY_VER(i915) == 5) fbc->funcs = &ilk_fbc_funcs; - else if (IS_G4X(dev_priv)) + else if (IS_G4X(i915)) fbc->funcs = &g4x_fbc_funcs; - else if (DISPLAY_VER(dev_priv) == 4) + else if (DISPLAY_VER(i915) == 4) fbc->funcs = &i965_fbc_funcs; else fbc->funcs = &i8xx_fbc_funcs; @@ -1742,6 +1742,6 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) /* We still don't have any sort of hardware state readout for FBC, so * deactivate it in case the BIOS activated it to make sure software * matches the hardware state. */ - if (intel_fbc_hw_is_active(dev_priv)) - intel_fbc_hw_deactivate(dev_priv); + if (intel_fbc_hw_is_active(i915)) + intel_fbc_hw_deactivate(i915); } From e49a656b924ef125a2b00945a60df39cd09b8c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:19 +0200 Subject: [PATCH 135/176] drm/i915/fbc: Start passing around intel_fbc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for multiple FBC instances start passing around intel_fbc pointers rather than i915 pointers. And once there are multiple of these we can't rely on container_of() to get back to the i915, so we toss in a fbc->i915 pointer already. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-17-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../drm/i915/display/intel_display_debugfs.c | 8 +- drivers/gpu/drm/i915/display/intel_fbc.c | 379 +++++++++--------- drivers/gpu/drm/i915/display/intel_fbc.h | 14 +- .../drm/i915/display/intel_fifo_underrun.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 +- 7 files changed, 200 insertions(+), 208 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 40efd5ad029a4..d6ff4aea73198 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10815,7 +10815,7 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915) destroy_workqueue(i915->flip_wq); destroy_workqueue(i915->modeset_wq); - intel_fbc_cleanup_cfb(i915); + intel_fbc_cleanup(i915); } /* part #3: call after gem init */ diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 1a92107397273..3f5a5e1b1c41f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -52,10 +52,10 @@ static int i915_fbc_status(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); mutex_lock(&fbc->lock); - if (intel_fbc_is_active(dev_priv)) { + if (intel_fbc_is_active(fbc)) { seq_puts(m, "FBC enabled\n"); seq_printf(m, "Compressing: %s\n", - yesno(intel_fbc_is_compressing(dev_priv))); + yesno(intel_fbc_is_compressing(fbc))); } else { seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); } @@ -79,7 +79,7 @@ static int i915_fbc_false_color_set(void *data, u64 val) { struct drm_i915_private *dev_priv = data; - return intel_fbc_set_false_color(dev_priv, val); + return intel_fbc_set_false_color(&dev_priv->fbc, val); } DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_false_color_fops, @@ -2063,7 +2063,7 @@ i915_fifo_underrun_reset_write(struct file *filp, return ret; } - ret = intel_fbc_reset_underrun(dev_priv); + ret = intel_fbc_reset_underrun(&dev_priv->fbc); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index ea3968001c4b7..e8235d55e76af 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -49,13 +49,13 @@ #include "intel_frontbuffer.h" struct intel_fbc_funcs { - void (*activate)(struct drm_i915_private *i915); - void (*deactivate)(struct drm_i915_private *i915); - bool (*is_active)(struct drm_i915_private *i915); - bool (*is_compressing)(struct drm_i915_private *i915); - void (*nuke)(struct drm_i915_private *i915); - void (*program_cfb)(struct drm_i915_private *i915); - void (*set_false_color)(struct drm_i915_private *i915, bool enable); + void (*activate)(struct intel_fbc *fbc); + void (*deactivate)(struct intel_fbc *fbc); + bool (*is_active)(struct intel_fbc *fbc); + bool (*is_compressing)(struct intel_fbc *fbc); + void (*nuke)(struct intel_fbc *fbc); + void (*program_cfb)(struct intel_fbc *fbc); + void (*set_false_color)(struct intel_fbc *fbc, bool enable); }; /* @@ -94,9 +94,10 @@ static unsigned int _intel_fbc_cfb_stride(const struct intel_fbc_state_cache *ca } /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */ -static unsigned int skl_fbc_min_cfb_stride(struct drm_i915_private *i915, +static unsigned int skl_fbc_min_cfb_stride(struct intel_fbc *fbc, const struct intel_fbc_state_cache *cache) { + struct drm_i915_private *i915 = fbc->i915; unsigned int limit = 4; /* 1:4 compression limit is the worst case */ unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ unsigned int height = 4; /* FBC segment is 4 lines */ @@ -123,9 +124,10 @@ static unsigned int skl_fbc_min_cfb_stride(struct drm_i915_private *i915, } /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */ -static unsigned int intel_fbc_cfb_stride(struct drm_i915_private *i915, +static unsigned int intel_fbc_cfb_stride(struct intel_fbc *fbc, const struct intel_fbc_state_cache *cache) { + struct drm_i915_private *i915 = fbc->i915; unsigned int stride = _intel_fbc_cfb_stride(cache); /* @@ -134,14 +136,15 @@ static unsigned int intel_fbc_cfb_stride(struct drm_i915_private *i915, * that regardless of the compression limit we choose later. */ if (DISPLAY_VER(i915) >= 9) - return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(i915, cache)); + return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(fbc, cache)); else return stride; } -static unsigned int intel_fbc_cfb_size(struct drm_i915_private *i915, +static unsigned int intel_fbc_cfb_size(struct intel_fbc *fbc, const struct intel_fbc_state_cache *cache) { + struct drm_i915_private *i915 = fbc->i915; int lines = cache->plane.src_h; if (DISPLAY_VER(i915) == 7) @@ -149,13 +152,13 @@ static unsigned int intel_fbc_cfb_size(struct drm_i915_private *i915, else if (DISPLAY_VER(i915) >= 8) lines = min(lines, 2560); - return lines * intel_fbc_cfb_stride(i915, cache); + return lines * intel_fbc_cfb_stride(fbc, cache); } -static u32 i8xx_fbc_ctl(struct drm_i915_private *i915) +static u32 i8xx_fbc_ctl(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; unsigned int cfb_stride; u32 fbc_ctl; @@ -180,9 +183,9 @@ static u32 i8xx_fbc_ctl(struct drm_i915_private *i915) return fbc_ctl; } -static u32 i965_fbc_ctl2(struct drm_i915_private *i915) +static u32 i965_fbc_ctl2(struct intel_fbc *fbc) { - const struct intel_fbc_reg_params *params = &i915->fbc.params; + const struct intel_fbc_reg_params *params = &fbc->params; u32 fbc_ctl2; fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | @@ -194,8 +197,9 @@ static u32 i965_fbc_ctl2(struct drm_i915_private *i915) return fbc_ctl2; } -static void i8xx_fbc_deactivate(struct drm_i915_private *i915) +static void i8xx_fbc_deactivate(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; u32 fbc_ctl; /* Disable compression */ @@ -214,10 +218,10 @@ static void i8xx_fbc_deactivate(struct drm_i915_private *i915) } } -static void i8xx_fbc_activate(struct drm_i915_private *i915) +static void i8xx_fbc_activate(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; int i; /* Clear old tags */ @@ -226,30 +230,31 @@ static void i8xx_fbc_activate(struct drm_i915_private *i915) if (DISPLAY_VER(i915) == 4) { intel_de_write(i915, FBC_CONTROL2, - i965_fbc_ctl2(i915)); + i965_fbc_ctl2(fbc)); intel_de_write(i915, FBC_FENCE_OFF, params->fence_y_offset); } intel_de_write(i915, FBC_CONTROL, - FBC_CTL_EN | i8xx_fbc_ctl(i915)); + FBC_CTL_EN | i8xx_fbc_ctl(fbc)); } -static bool i8xx_fbc_is_active(struct drm_i915_private *i915) +static bool i8xx_fbc_is_active(struct intel_fbc *fbc) { - return intel_de_read(i915, FBC_CONTROL) & FBC_CTL_EN; + return intel_de_read(fbc->i915, FBC_CONTROL) & FBC_CTL_EN; } -static bool i8xx_fbc_is_compressing(struct drm_i915_private *i915) +static bool i8xx_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(i915, FBC_STATUS) & + return intel_de_read(fbc->i915, FBC_STATUS) & (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); } -static void i8xx_fbc_nuke(struct drm_i915_private *dev_priv) +static void i8xx_fbc_nuke(struct intel_fbc *fbc) { - struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + struct intel_fbc_reg_params *params = &fbc->params; enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; + struct drm_i915_private *dev_priv = fbc->i915; spin_lock_irq(&dev_priv->uncore.lock); intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), @@ -257,9 +262,9 @@ static void i8xx_fbc_nuke(struct drm_i915_private *dev_priv) spin_unlock_irq(&dev_priv->uncore.lock); } -static void i8xx_fbc_program_cfb(struct drm_i915_private *i915) +static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, fbc->compressed_fb.start, U32_MAX)); @@ -281,10 +286,11 @@ static const struct intel_fbc_funcs i8xx_fbc_funcs = { .program_cfb = i8xx_fbc_program_cfb, }; -static void i965_fbc_nuke(struct drm_i915_private *dev_priv) +static void i965_fbc_nuke(struct intel_fbc *fbc) { - struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + struct intel_fbc_reg_params *params = &fbc->params; enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; + struct drm_i915_private *dev_priv = fbc->i915; spin_lock_irq(&dev_priv->uncore.lock); intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), @@ -301,11 +307,11 @@ static const struct intel_fbc_funcs i965_fbc_funcs = { .program_cfb = i8xx_fbc_program_cfb, }; -static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) +static u32 g4x_dpfc_ctl_limit(struct intel_fbc *fbc) { - switch (i915->fbc.limit) { + switch (fbc->limit) { default: - MISSING_CASE(i915->fbc.limit); + MISSING_CASE(fbc->limit); fallthrough; case 1: return DPFC_CTL_LIMIT_1X; @@ -316,12 +322,13 @@ static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915) } } -static u32 g4x_dpfc_ctl(struct drm_i915_private *i915) +static u32 g4x_dpfc_ctl(struct intel_fbc *fbc) { - const struct intel_fbc_reg_params *params = &i915->fbc.params; + const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; u32 dpfc_ctl; - dpfc_ctl = g4x_dpfc_ctl_limit(i915) | + dpfc_ctl = g4x_dpfc_ctl_limit(fbc) | DPFC_CTL_PLANE_G4X(params->crtc.i9xx_plane); if (IS_G4X(i915)) @@ -337,19 +344,21 @@ static u32 g4x_dpfc_ctl(struct drm_i915_private *i915) return dpfc_ctl; } -static void g4x_fbc_activate(struct drm_i915_private *i915) +static void g4x_fbc_activate(struct intel_fbc *fbc) { - const struct intel_fbc_reg_params *params = &i915->fbc.params; + const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; intel_de_write(i915, DPFC_FENCE_YOFF, params->fence_y_offset); intel_de_write(i915, DPFC_CONTROL, - DPFC_CTL_EN | g4x_dpfc_ctl(i915)); + DPFC_CTL_EN | g4x_dpfc_ctl(fbc)); } -static void g4x_fbc_deactivate(struct drm_i915_private *i915) +static void g4x_fbc_deactivate(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; u32 dpfc_ctl; /* Disable compression */ @@ -360,19 +369,19 @@ static void g4x_fbc_deactivate(struct drm_i915_private *i915) } } -static bool g4x_fbc_is_active(struct drm_i915_private *i915) +static bool g4x_fbc_is_active(struct intel_fbc *fbc) { - return intel_de_read(i915, DPFC_CONTROL) & DPFC_CTL_EN; + return intel_de_read(fbc->i915, DPFC_CONTROL) & DPFC_CTL_EN; } -static bool g4x_fbc_is_compressing(struct drm_i915_private *i915) +static bool g4x_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; + return intel_de_read(fbc->i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; } -static void g4x_fbc_program_cfb(struct drm_i915_private *i915) +static void g4x_fbc_program_cfb(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; intel_de_write(i915, DPFC_CB_BASE, fbc->compressed_fb.start); } @@ -386,19 +395,21 @@ static const struct intel_fbc_funcs g4x_fbc_funcs = { .program_cfb = g4x_fbc_program_cfb, }; -static void ilk_fbc_activate(struct drm_i915_private *i915) +static void ilk_fbc_activate(struct intel_fbc *fbc) { - struct intel_fbc_reg_params *params = &i915->fbc.params; + struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; intel_de_write(i915, ILK_DPFC_FENCE_YOFF, params->fence_y_offset); intel_de_write(i915, ILK_DPFC_CONTROL, - DPFC_CTL_EN | g4x_dpfc_ctl(i915)); + DPFC_CTL_EN | g4x_dpfc_ctl(fbc)); } -static void ilk_fbc_deactivate(struct drm_i915_private *i915) +static void ilk_fbc_deactivate(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; u32 dpfc_ctl; /* Disable compression */ @@ -409,19 +420,19 @@ static void ilk_fbc_deactivate(struct drm_i915_private *i915) } } -static bool ilk_fbc_is_active(struct drm_i915_private *i915) +static bool ilk_fbc_is_active(struct intel_fbc *fbc) { - return intel_de_read(i915, ILK_DPFC_CONTROL) & DPFC_CTL_EN; + return intel_de_read(fbc->i915, ILK_DPFC_CONTROL) & DPFC_CTL_EN; } -static bool ilk_fbc_is_compressing(struct drm_i915_private *i915) +static bool ilk_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(i915, ILK_DPFC_STATUS) & DPFC_COMP_SEG_MASK; + return intel_de_read(fbc->i915, ILK_DPFC_STATUS) & DPFC_COMP_SEG_MASK; } -static void ilk_fbc_program_cfb(struct drm_i915_private *i915) +static void ilk_fbc_program_cfb(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; intel_de_write(i915, ILK_DPFC_CB_BASE, fbc->compressed_fb.start); } @@ -435,9 +446,10 @@ static const struct intel_fbc_funcs ilk_fbc_funcs = { .program_cfb = ilk_fbc_program_cfb, }; -static void snb_fbc_program_fence(struct drm_i915_private *i915) +static void snb_fbc_program_fence(struct intel_fbc *fbc) { - const struct intel_fbc_reg_params *params = &i915->fbc.params; + const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; u32 ctl = 0; if (params->fence_id >= 0) @@ -447,15 +459,17 @@ static void snb_fbc_program_fence(struct drm_i915_private *i915) intel_de_write(i915, SNB_DPFC_CPU_FENCE_OFFSET, params->fence_y_offset); } -static void snb_fbc_activate(struct drm_i915_private *i915) +static void snb_fbc_activate(struct intel_fbc *fbc) { - snb_fbc_program_fence(i915); + snb_fbc_program_fence(fbc); - ilk_fbc_activate(i915); + ilk_fbc_activate(fbc); } -static void snb_fbc_nuke(struct drm_i915_private *i915) +static void snb_fbc_nuke(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; + intel_de_write(i915, MSG_FBC_REND_STATE, FBC_REND_NUKE); intel_de_posting_read(i915, MSG_FBC_REND_STATE); } @@ -469,10 +483,10 @@ static const struct intel_fbc_funcs snb_fbc_funcs = { .program_cfb = ilk_fbc_program_cfb, }; -static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) +static void glk_fbc_program_cfb_stride(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; u32 val = 0; if (params->override_cfb_stride) @@ -482,10 +496,10 @@ static void glk_fbc_program_cfb_stride(struct drm_i915_private *i915) intel_de_write(i915, GLK_FBC_STRIDE, val); } -static void skl_fbc_program_cfb_stride(struct drm_i915_private *i915) +static void skl_fbc_program_cfb_stride(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; u32 val = 0; /* Display WA #0529: skl, kbl, bxt. */ @@ -498,12 +512,13 @@ static void skl_fbc_program_cfb_stride(struct drm_i915_private *i915) CHICKEN_FBC_STRIDE_MASK, val); } -static u32 ivb_dpfc_ctl(struct drm_i915_private *i915) +static u32 ivb_dpfc_ctl(struct intel_fbc *fbc) { - const struct intel_fbc_reg_params *params = &i915->fbc.params; + const struct intel_fbc_reg_params *params = &fbc->params; + struct drm_i915_private *i915 = fbc->i915; u32 dpfc_ctl; - dpfc_ctl = g4x_dpfc_ctl_limit(i915); + dpfc_ctl = g4x_dpfc_ctl_limit(fbc); if (IS_IVYBRIDGE(i915)) dpfc_ctl |= DPFC_CTL_PLANE_IVB(params->crtc.i9xx_plane); @@ -511,35 +526,37 @@ static u32 ivb_dpfc_ctl(struct drm_i915_private *i915) if (params->fence_id >= 0) dpfc_ctl |= DPFC_CTL_FENCE_EN_IVB; - if (i915->fbc.false_color) + if (fbc->false_color) dpfc_ctl |= DPFC_CTL_FALSE_COLOR; return dpfc_ctl; } -static void ivb_fbc_activate(struct drm_i915_private *i915) +static void ivb_fbc_activate(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; + if (DISPLAY_VER(i915) >= 10) - glk_fbc_program_cfb_stride(i915); + glk_fbc_program_cfb_stride(fbc); else if (DISPLAY_VER(i915) == 9) - skl_fbc_program_cfb_stride(i915); + skl_fbc_program_cfb_stride(fbc); if (i915->ggtt.num_fences) - snb_fbc_program_fence(i915); + snb_fbc_program_fence(fbc); intel_de_write(i915, ILK_DPFC_CONTROL, - DPFC_CTL_EN | ivb_dpfc_ctl(i915)); + DPFC_CTL_EN | ivb_dpfc_ctl(fbc)); } -static bool ivb_fbc_is_compressing(struct drm_i915_private *i915) +static bool ivb_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(i915, ILK_DPFC_STATUS2) & DPFC_COMP_SEG_MASK_IVB; + return intel_de_read(fbc->i915, ILK_DPFC_STATUS2) & DPFC_COMP_SEG_MASK_IVB; } -static void ivb_fbc_set_false_color(struct drm_i915_private *i915, +static void ivb_fbc_set_false_color(struct intel_fbc *fbc, bool enable) { - intel_de_rmw(i915, ILK_DPFC_CONTROL, + intel_de_rmw(fbc->i915, ILK_DPFC_CONTROL, DPFC_CTL_FALSE_COLOR, enable ? DPFC_CTL_FALSE_COLOR : 0); } @@ -553,56 +570,44 @@ static const struct intel_fbc_funcs ivb_fbc_funcs = { .set_false_color = ivb_fbc_set_false_color, }; -static bool intel_fbc_hw_is_active(struct drm_i915_private *i915) +static bool intel_fbc_hw_is_active(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - - return fbc->funcs->is_active(i915); + return fbc->funcs->is_active(fbc); } -static void intel_fbc_hw_activate(struct drm_i915_private *i915) +static void intel_fbc_hw_activate(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - trace_intel_fbc_activate(fbc->crtc); fbc->active = true; fbc->activated = true; - fbc->funcs->activate(i915); + fbc->funcs->activate(fbc); } -static void intel_fbc_hw_deactivate(struct drm_i915_private *i915) +static void intel_fbc_hw_deactivate(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - trace_intel_fbc_deactivate(fbc->crtc); fbc->active = false; - fbc->funcs->deactivate(i915); + fbc->funcs->deactivate(fbc); } -bool intel_fbc_is_compressing(struct drm_i915_private *i915) +bool intel_fbc_is_compressing(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - - return fbc->funcs->is_compressing(i915); + return fbc->funcs->is_compressing(fbc); } -static void intel_fbc_nuke(struct drm_i915_private *i915) +static void intel_fbc_nuke(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - trace_intel_fbc_nuke(fbc->crtc); - fbc->funcs->nuke(i915); + fbc->funcs->nuke(fbc); } -int intel_fbc_set_false_color(struct drm_i915_private *i915, bool enable) +int intel_fbc_set_false_color(struct intel_fbc *fbc, bool enable) { - struct intel_fbc *fbc = &i915->fbc; - if (!fbc->funcs || !fbc->funcs->set_false_color) return -ENODEV; @@ -610,7 +615,7 @@ int intel_fbc_set_false_color(struct drm_i915_private *i915, bool enable) fbc->false_color = enable; - fbc->funcs->set_false_color(i915, enable); + fbc->funcs->set_false_color(fbc, enable); mutex_unlock(&fbc->lock); @@ -626,26 +631,25 @@ int intel_fbc_set_false_color(struct drm_i915_private *i915, bool enable) * FIXME: This should be tracked in the plane config eventually * instead of queried at runtime for most callers. */ -bool intel_fbc_is_active(struct drm_i915_private *i915) +bool intel_fbc_is_active(struct intel_fbc *fbc) { - return i915->fbc.active; + return fbc->active; } -static void intel_fbc_activate(struct drm_i915_private *i915) +static void intel_fbc_activate(struct intel_fbc *fbc) { - intel_fbc_hw_activate(i915); - intel_fbc_nuke(i915); + intel_fbc_hw_activate(fbc); + intel_fbc_nuke(fbc); } -static void intel_fbc_deactivate(struct drm_i915_private *i915, - const char *reason) +static void intel_fbc_deactivate(struct intel_fbc *fbc, const char *reason) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); if (fbc->active) - intel_fbc_hw_deactivate(i915); + intel_fbc_hw_deactivate(fbc); fbc->no_fbc_reason = reason; } @@ -693,10 +697,10 @@ static int intel_fbc_max_limit(struct drm_i915_private *i915) return 4; } -static int find_compression_limit(struct drm_i915_private *i915, +static int find_compression_limit(struct intel_fbc *fbc, unsigned int size, int min_limit) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; u64 end = intel_fbc_stolen_end(i915); int ret, limit = min_limit; @@ -718,10 +722,10 @@ static int find_compression_limit(struct drm_i915_private *i915, return 0; } -static int intel_fbc_alloc_cfb(struct drm_i915_private *i915, +static int intel_fbc_alloc_cfb(struct intel_fbc *fbc, unsigned int size, int min_limit) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; int ret; drm_WARN_ON(&i915->drm, @@ -736,7 +740,7 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *i915, goto err; } - ret = find_compression_limit(i915, size, min_limit); + ret = find_compression_limit(fbc, size, min_limit); if (!ret) goto err_llb; else if (ret > min_limit) @@ -760,18 +764,16 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *i915, return -ENOSPC; } -static void intel_fbc_program_cfb(struct drm_i915_private *i915) +static void intel_fbc_program_cfb(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - - fbc->funcs->program_cfb(i915); + fbc->funcs->program_cfb(fbc); } -static void __intel_fbc_cleanup_cfb(struct drm_i915_private *i915) +static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; - if (WARN_ON(intel_fbc_hw_is_active(i915))) + if (WARN_ON(intel_fbc_hw_is_active(fbc))) return; if (drm_mm_node_allocated(&fbc->compressed_llb)) @@ -780,7 +782,7 @@ static void __intel_fbc_cleanup_cfb(struct drm_i915_private *i915) i915_gem_stolen_remove_node(i915, &fbc->compressed_fb); } -void intel_fbc_cleanup_cfb(struct drm_i915_private *i915) +void intel_fbc_cleanup(struct drm_i915_private *i915) { struct intel_fbc *fbc = &i915->fbc; @@ -788,7 +790,7 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private *i915) return; mutex_lock(&fbc->lock); - __intel_fbc_cleanup_cfb(i915); + __intel_fbc_cleanup_cfb(fbc); mutex_unlock(&fbc->lock); } @@ -860,10 +862,10 @@ static bool rotation_is_valid(struct drm_i915_private *i915, * the X and Y offset registers. That's why we include the src x/y offsets * instead of just looking at the plane size. */ -static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) +static bool intel_fbc_hw_tracking_covers_screen(struct intel_fbc *fbc, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; unsigned int effective_w, effective_h, max_w, max_h; if (DISPLAY_VER(i915) >= 10) { @@ -954,19 +956,17 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->psr2_active = crtc_state->has_psr2; } -static bool intel_fbc_cfb_size_changed(struct drm_i915_private *i915) +static bool intel_fbc_cfb_size_changed(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - - return intel_fbc_cfb_size(i915, &fbc->state_cache) > + return intel_fbc_cfb_size(fbc, &fbc->state_cache) > fbc->compressed_fb.size * fbc->limit; } -static u16 intel_fbc_override_cfb_stride(struct drm_i915_private *i915, +static u16 intel_fbc_override_cfb_stride(struct intel_fbc *fbc, const struct intel_fbc_state_cache *cache) { unsigned int stride = _intel_fbc_cfb_stride(cache); - unsigned int stride_aligned = intel_fbc_cfb_stride(i915, cache); + unsigned int stride_aligned = intel_fbc_cfb_stride(fbc, cache); /* * Override stride in 64 byte units per 4 line segment. @@ -976,16 +976,16 @@ static u16 intel_fbc_override_cfb_stride(struct drm_i915_private *i915, * we always need to use the override there. */ if (stride != stride_aligned || - (DISPLAY_VER(i915) == 9 && + (DISPLAY_VER(fbc->i915) == 9 && cache->fb.modifier == DRM_FORMAT_MOD_LINEAR)) return stride_aligned * 4 / 64; return 0; } -static bool intel_fbc_can_enable(struct drm_i915_private *i915) +static bool intel_fbc_can_enable(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; if (intel_vgpu_active(i915)) { fbc->no_fbc_reason = "VGPU is active"; @@ -1011,7 +1011,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) struct intel_fbc *fbc = &i915->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; - if (!intel_fbc_can_enable(i915)) + if (!intel_fbc_can_enable(fbc)) return false; if (!cache->plane.visible) { @@ -1032,7 +1032,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return false; } - if (!intel_fbc_hw_tracking_covers_screen(crtc)) { + if (!intel_fbc_hw_tracking_covers_screen(fbc, crtc)) { fbc->no_fbc_reason = "mode too large for compression"; return false; } @@ -1104,7 +1104,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * we didn't get any invalidate/deactivate calls, but this would require * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ - if (intel_fbc_cfb_size_changed(i915)) { + if (intel_fbc_cfb_size_changed(fbc)) { fbc->no_fbc_reason = "CFB requirements changed"; return false; } @@ -1140,12 +1140,11 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return true; } -static void intel_fbc_get_reg_params(struct intel_crtc *crtc, - struct intel_fbc_reg_params *params) +static void intel_fbc_get_reg_params(struct intel_fbc *fbc, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &i915->fbc; - struct intel_fbc_state_cache *cache = &fbc->state_cache; + const struct intel_fbc_state_cache *cache = &fbc->state_cache; + struct intel_fbc_reg_params *params = &fbc->params; /* Since all our fields are integer types, use memset here so the * comparison function can rely on memcmp because the padding will be @@ -1164,9 +1163,9 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->fb.modifier = cache->fb.modifier; params->fb.stride = cache->fb.stride; - params->cfb_stride = intel_fbc_cfb_stride(i915, cache); - params->cfb_size = intel_fbc_cfb_size(i915, cache); - params->override_cfb_stride = intel_fbc_override_cfb_stride(i915, cache); + params->cfb_stride = intel_fbc_cfb_stride(fbc, cache); + params->cfb_size = intel_fbc_cfb_size(fbc, cache); + params->override_cfb_stride = intel_fbc_override_cfb_stride(fbc, cache); params->plane_visible = cache->plane.visible; } @@ -1175,7 +1174,7 @@ static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - const struct intel_fbc *fbc = &i915->fbc; + struct intel_fbc *fbc = &i915->fbc; const struct intel_fbc_state_cache *cache = &fbc->state_cache; const struct intel_fbc_reg_params *params = &fbc->params; @@ -1197,13 +1196,13 @@ static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) if (params->fb.stride != cache->fb.stride) return false; - if (params->cfb_stride != intel_fbc_cfb_stride(i915, cache)) + if (params->cfb_stride != intel_fbc_cfb_stride(fbc, cache)) return false; - if (params->cfb_size != intel_fbc_cfb_size(i915, cache)) + if (params->cfb_size != intel_fbc_cfb_size(fbc, cache)) return false; - if (params->override_cfb_stride != intel_fbc_override_cfb_stride(i915, cache)) + if (params->override_cfb_stride != intel_fbc_override_cfb_stride(fbc, cache)) return false; return true; @@ -1234,7 +1233,7 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, fbc->flip_pending = true; if (!intel_fbc_can_flip_nuke(crtc_state)) { - intel_fbc_deactivate(i915, reason); + intel_fbc_deactivate(fbc, reason); /* * Display WA #1198: glk+ @@ -1260,16 +1259,9 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, return need_vblank_wait; } -/** - * __intel_fbc_disable - disable FBC - * @i915: i915 device instance - * - * This is the low level function that actually disables FBC. Callers should - * grab the FBC lock. - */ -static void __intel_fbc_disable(struct drm_i915_private *i915) +static void __intel_fbc_disable(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; + struct drm_i915_private *i915 = fbc->i915; struct intel_crtc *crtc = fbc->crtc; drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); @@ -1279,7 +1271,7 @@ static void __intel_fbc_disable(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "Disabling FBC on pipe %c\n", pipe_name(crtc->pipe)); - __intel_fbc_cleanup_cfb(i915); + __intel_fbc_cleanup_cfb(fbc); fbc->crtc = NULL; } @@ -1297,21 +1289,21 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) fbc->flip_pending = false; if (!i915->params.enable_fbc) { - intel_fbc_deactivate(i915, "disabled at runtime per module param"); - __intel_fbc_disable(i915); + intel_fbc_deactivate(fbc, "disabled at runtime per module param"); + __intel_fbc_disable(fbc); return; } - intel_fbc_get_reg_params(crtc, &fbc->params); + intel_fbc_get_reg_params(fbc, crtc); if (!intel_fbc_can_activate(crtc)) return; if (!fbc->busy_bits) - intel_fbc_activate(i915); + intel_fbc_activate(fbc); else - intel_fbc_deactivate(i915, "frontbuffer write"); + intel_fbc_deactivate(fbc, "frontbuffer write"); } void intel_fbc_post_update(struct intel_atomic_state *state, @@ -1356,7 +1348,7 @@ void intel_fbc_invalidate(struct drm_i915_private *i915, fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; if (fbc->crtc && fbc->busy_bits) - intel_fbc_deactivate(i915, "frontbuffer write"); + intel_fbc_deactivate(fbc, "frontbuffer write"); mutex_unlock(&fbc->lock); } @@ -1379,7 +1371,7 @@ void intel_fbc_flush(struct drm_i915_private *i915, if (!fbc->busy_bits && fbc->crtc && (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) { if (fbc->active) - intel_fbc_nuke(i915); + intel_fbc_nuke(fbc); else if (!fbc->flip_pending) __intel_fbc_post_update(fbc->crtc); } @@ -1416,7 +1408,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *i915, !intel_atomic_get_new_crtc_state(state, fbc->crtc)) goto out; - if (!intel_fbc_can_enable(i915)) + if (!intel_fbc_can_enable(fbc)) goto out; /* Simply choose the first CRTC that is compatible and has a visible @@ -1483,10 +1475,10 @@ static void intel_fbc_enable(struct intel_atomic_state *state, goto out; if (fbc->limit >= min_limit && - !intel_fbc_cfb_size_changed(i915)) + !intel_fbc_cfb_size_changed(fbc)) goto out; - __intel_fbc_disable(i915); + __intel_fbc_disable(fbc); } drm_WARN_ON(&i915->drm, fbc->active); @@ -1497,8 +1489,7 @@ static void intel_fbc_enable(struct intel_atomic_state *state, if (!cache->plane.visible) goto out; - if (intel_fbc_alloc_cfb(i915, - intel_fbc_cfb_size(i915, cache), min_limit)) { + if (intel_fbc_alloc_cfb(fbc, intel_fbc_cfb_size(fbc, cache), min_limit)) { cache->plane.visible = false; fbc->no_fbc_reason = "not enough stolen memory"; goto out; @@ -1510,7 +1501,7 @@ static void intel_fbc_enable(struct intel_atomic_state *state, fbc->crtc = crtc; - intel_fbc_program_cfb(i915); + intel_fbc_program_cfb(fbc); out: mutex_unlock(&fbc->lock); } @@ -1532,7 +1523,7 @@ void intel_fbc_disable(struct intel_crtc *crtc) mutex_lock(&fbc->lock); if (fbc->crtc == crtc) - __intel_fbc_disable(i915); + __intel_fbc_disable(fbc); mutex_unlock(&fbc->lock); } @@ -1574,7 +1565,7 @@ void intel_fbc_global_disable(struct drm_i915_private *i915) mutex_lock(&fbc->lock); if (fbc->crtc) { drm_WARN_ON(&i915->drm, fbc->crtc->active); - __intel_fbc_disable(i915); + __intel_fbc_disable(fbc); } mutex_unlock(&fbc->lock); } @@ -1594,7 +1585,7 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) drm_dbg_kms(&i915->drm, "Disabling FBC due to FIFO underrun.\n"); fbc->underrun_detected = true; - intel_fbc_deactivate(i915, "FIFO underrun"); + intel_fbc_deactivate(fbc, "FIFO underrun"); out: mutex_unlock(&fbc->lock); } @@ -1606,24 +1597,25 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we * want to re-enable FBC after an underrun to increase test coverage. */ -int intel_fbc_reset_underrun(struct drm_i915_private *i915) +int intel_fbc_reset_underrun(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; int ret; - cancel_work_sync(&i915->fbc.underrun_work); + cancel_work_sync(&fbc->underrun_work); - ret = mutex_lock_interruptible(&i915->fbc.lock); + ret = mutex_lock_interruptible(&fbc->lock); if (ret) return ret; - if (i915->fbc.underrun_detected) { + if (fbc->underrun_detected) { drm_dbg_kms(&i915->drm, "Re-allowing FBC after fifo underrun\n"); - i915->fbc.no_fbc_reason = "FIFO underrun cleared"; + fbc->no_fbc_reason = "FIFO underrun cleared"; } - i915->fbc.underrun_detected = false; - mutex_unlock(&i915->fbc.lock); + fbc->underrun_detected = false; + mutex_unlock(&fbc->lock); return 0; } @@ -1642,11 +1634,9 @@ int intel_fbc_reset_underrun(struct drm_i915_private *i915) * * This function is called from the IRQ handler. */ -void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915) +void intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc) { - struct intel_fbc *fbc = &i915->fbc; - - if (!HAS_FBC(i915)) + if (!HAS_FBC(fbc->i915)) return; /* There's no guarantee that underrun_detected won't be set to true @@ -1707,6 +1697,7 @@ void intel_fbc_init(struct drm_i915_private *i915) { struct intel_fbc *fbc = &i915->fbc; + fbc->i915 = i915; INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); mutex_init(&fbc->lock); fbc->active = false; @@ -1742,6 +1733,6 @@ void intel_fbc_init(struct drm_i915_private *i915) /* We still don't have any sort of hardware state readout for FBC, so * deactivate it in case the BIOS activated it to make sure software * matches the hardware state. */ - if (intel_fbc_hw_is_active(i915)) - intel_fbc_hw_deactivate(i915); + if (intel_fbc_hw_is_active(fbc)) + intel_fbc_hw_deactivate(fbc); } diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index 4d1f2a76ccb49..ce48a22c5e9e6 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -14,17 +14,19 @@ struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; +struct intel_fbc; struct intel_plane_state; void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, struct intel_atomic_state *state); -bool intel_fbc_is_active(struct drm_i915_private *dev_priv); -bool intel_fbc_is_compressing(struct drm_i915_private *dev_priv); +bool intel_fbc_is_active(struct intel_fbc *fbc); +bool intel_fbc_is_compressing(struct intel_fbc *fbc); bool intel_fbc_pre_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); +void intel_fbc_cleanup(struct drm_i915_private *dev_priv); void intel_fbc_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_disable(struct intel_crtc *crtc); @@ -34,10 +36,8 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, enum fb_op_origin origin); void intel_fbc_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin); -void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); -void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); -int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv); -int intel_fbc_set_false_color(struct drm_i915_private *i915, - bool enable); +void intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc); +int intel_fbc_reset_underrun(struct intel_fbc *fbc); +int intel_fbc_set_false_color(struct intel_fbc *fbc, bool enable); #endif /* __INTEL_FBC_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c index eb841960840d3..28d9eeb7b4f38 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c @@ -434,7 +434,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe)); } - intel_fbc_handle_fifo_underrun_irq(dev_priv); + intel_fbc_handle_fifo_underrun_irq(&dev_priv->fbc); } /** diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6d091187ecd80..e6ba8e96a411b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -407,6 +407,7 @@ struct intel_fbc_funcs; #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ struct intel_fbc { + struct drm_i915_private *i915; const struct intel_fbc_funcs *funcs; /* This is always the inner lock when overlapping with struct_mutex and diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2796f32d72ad0..41d52789660d2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3375,7 +3375,7 @@ static void ilk_wm_merge(struct drm_i915_private *dev_priv, * enabled sometime later. */ if (DISPLAY_VER(dev_priv) == 5 && !merged->fbc_wm_enabled && - intel_fbc_is_active(dev_priv)) { + intel_fbc_is_active(&dev_priv->fbc)) { for (level = 2; level <= max_level; level++) { struct intel_wm_level *wm = &merged->wm[level]; From 02689a2055d8a78b7cd0b722a591d1acff8b1e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 4 Nov 2021 16:45:20 +0200 Subject: [PATCH 136/176] drm/1915/fbc: Replace plane->has_fbc with a pointer to the fbc instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With multiple fbc instances we need to find the right one for each plane. Rather than going looking for the right instance every time let's just replace the has_fbc boolean with a pointer that gets us there straight away. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211104144520.22605-18-ville.syrjala@linux.intel.com Acked-by: Jani Nikula Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/i9xx_plane.c | 10 ++++---- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../drm/i915/display/intel_display_types.h | 4 +++- drivers/gpu/drm/i915/display/intel_fbc.c | 24 +++++++++---------- .../drm/i915/display/skl_universal_plane.c | 10 ++++---- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index ba276e8ab4f09..2194f74101ae2 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -807,12 +807,10 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->id = PLANE_PRIMARY; plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); - plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane); - if (plane->has_fbc) { - struct intel_fbc *fbc = &dev_priv->fbc; - - fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; - } + if (i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane)) + plane->fbc = &dev_priv->fbc; + if (plane->fbc) + plane->fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { formats = vlv_primary_formats; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d6ff4aea73198..0ceee8ac66717 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -645,7 +645,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) struct drm_i915_private *dev_priv = to_i915(plane->base.dev); return DISPLAY_VER(dev_priv) < 4 || - (plane->has_fbc && + (plane->fbc && plane_state->view.gtt.type == I915_GGTT_VIEW_NORMAL); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 7771716a26ad6..ea1e8a6e10b0f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -51,6 +51,7 @@ struct drm_printer; struct __intel_global_objs_state; struct intel_ddi_buf_trans; +struct intel_fbc; /* * Display related stuff @@ -1339,7 +1340,6 @@ struct intel_plane { enum i9xx_plane_id i9xx_plane; enum plane_id id; enum pipe pipe; - bool has_fbc; bool need_async_flip_disable_wa; u32 frontbuffer_bit; @@ -1347,6 +1347,8 @@ struct intel_plane { u32 base, cntl, size; } cursor; + struct intel_fbc *fbc; + /* * NOTE: Do not place new plane state fields here (e.g., when adding * new plane properties). New runtime state should now be placed in diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index e8235d55e76af..a7e0f79ceb637 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1217,11 +1217,11 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &i915->fbc; + struct intel_fbc *fbc = plane->fbc; const char *reason = "update pending"; bool need_vblank_wait = false; - if (!plane->has_fbc || !plane_state) + if (!fbc || !plane_state) return need_vblank_wait; mutex_lock(&fbc->lock); @@ -1309,13 +1309,12 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) void intel_fbc_post_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); - struct intel_fbc *fbc = &i915->fbc; + struct intel_fbc *fbc = plane->fbc; - if (!plane->has_fbc || !plane_state) + if (!fbc || !plane_state) return; mutex_lock(&fbc->lock); @@ -1419,7 +1418,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *i915, struct intel_crtc_state *crtc_state; struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); - if (!plane->has_fbc) + if (plane->fbc != fbc) continue; if (!plane_state->uapi.visible) @@ -1458,13 +1457,15 @@ static void intel_fbc_enable(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); - struct intel_fbc *fbc = &i915->fbc; - struct intel_fbc_state_cache *cache = &fbc->state_cache; + struct intel_fbc *fbc = plane->fbc; + struct intel_fbc_state_cache *cache; int min_limit; - if (!plane->has_fbc || !plane_state) + if (!fbc || !plane_state) return; + cache = &fbc->state_cache; + min_limit = intel_fbc_min_limit(plane_state->hw.fb ? plane_state->hw.fb->format->cpp[0] : 0); @@ -1514,11 +1515,10 @@ static void intel_fbc_enable(struct intel_atomic_state *state, */ void intel_fbc_disable(struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); - struct intel_fbc *fbc = &i915->fbc; + struct intel_fbc *fbc = plane->fbc; - if (!plane->has_fbc) + if (!fbc) return; mutex_lock(&fbc->lock); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 9eda04322a0e6..28890876bdebf 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2101,12 +2101,10 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->id = plane_id; plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id); - plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id); - if (plane->has_fbc) { - struct intel_fbc *fbc = &dev_priv->fbc; - - fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; - } + if (skl_plane_has_fbc(dev_priv, pipe, plane_id)) + plane->fbc = &dev_priv->fbc; + if (plane->fbc) + plane->fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; if (DISPLAY_VER(dev_priv) >= 11) { plane->min_width = icl_plane_min_width; From c582ffadbe6cf64be4544d9d168bcc520bd0c984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Mon, 8 Nov 2021 13:38:07 -0800 Subject: [PATCH 137/176] drm/i915/psr: Fix PSR2 handling of multiplanar format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a plane with a multiplanar format is added to the state by drm_atomic_add_affected_planes(), only the UV plane is added, so a intel_atomic_get_new_plane_state() call to get the Y plane state can return a null pointer. To fix this, intel_atomic_get_plane_state() should be called and the return needs to be checked for errors, as it could return a EAGAIN as other atomic state could be holding the lock for the Y plane. Other issue with the patch being fixed is that the Y plane is not being committed to hardware because the corresponded plane bit is not set in update_planes when UV and Y planes are added to the state by drm_atomic_add_affected_planes(). Cc: Jouni Högander Cc: Mika Kahola Fixes: 3809991ff5f4 ("drm/i915/display: Add initial selective fetch support for biplanar formats") Signed-off-by: José Roberto de Souza Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20211108213807.39865-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 9d589d471e335..a1a663f362e7d 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1732,13 +1732,17 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, * same area for Y plane as well. */ if (linked) { - struct intel_plane_state *linked_new_plane_state = - intel_atomic_get_new_plane_state(state, linked); - struct drm_rect *linked_sel_fetch_area = - &linked_new_plane_state->psr2_sel_fetch_area; + struct intel_plane_state *linked_new_plane_state; + struct drm_rect *linked_sel_fetch_area; + linked_new_plane_state = intel_atomic_get_plane_state(state, linked); + if (IS_ERR(linked_new_plane_state)) + return PTR_ERR(linked_new_plane_state); + + linked_sel_fetch_area = &linked_new_plane_state->psr2_sel_fetch_area; linked_sel_fetch_area->y1 = sel_fetch_area->y1; linked_sel_fetch_area->y2 = sel_fetch_area->y2; + crtc_state->update_planes |= BIT(linked->id); } } From 2a2d23b68c4e4cd71c9999ea8b8608700c3f9ead Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 15 Sep 2021 12:27:02 +0100 Subject: [PATCH 138/176] drm/i915: make array states static const Don't populate the read-only array states on the stack but instead it static. Also makes the object code smaller. Signed-off-by: Colin Ian King Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20210915112702.12783-1-colin.king@canonical.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 344e3d6967020..a31974aa37cec 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -900,7 +900,7 @@ static u32 sanitize_target_dc_state(struct drm_i915_private *dev_priv, u32 target_dc_state) { - u32 states[] = { + static const u32 states[] = { DC_STATE_EN_UPTO_DC6, DC_STATE_EN_UPTO_DC5, DC_STATE_EN_DC3CO, From 6f07707fa09e1dc58c431d57c25ef2e68b9bec47 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 19 Oct 2021 20:44:32 +0530 Subject: [PATCH 139/176] drm/i915/dsi/xelpd: Fix the bit mask for wakeup GB v2: Fix the typo, move out the hardcoding from macro(Jani, Ville) Fixes: f87c46c43175 ("drm/i915/dsi/xelpd: Add WA to program LP to HS wakeup guardband") Signed-off-by: Vandita Kulkarni Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211019151435.20477-2-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 3 ++- drivers/gpu/drm/i915/i915_reg.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index c05fb861f10c6..edc38fbd2545d 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1269,7 +1269,8 @@ static void adlp_set_lp_hs_wakeup_gb(struct intel_encoder *encoder) if (DISPLAY_VER(i915) == 13) { for_each_dsi_port(port, intel_dsi->ports) intel_de_rmw(i915, TGL_DSI_CHKN_REG(port), - TGL_DSI_CHKN_LSHS_GB, 0x4); + TGL_DSI_CHKN_LSHS_GB_MASK, + TGL_DSI_CHKN_LSHS_GB(4)); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7d182d2ca7e69..a6dcf252a70fc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -11730,7 +11730,9 @@ enum skl_power_gate { #define TGL_DSI_CHKN_REG(port) _MMIO_PORT(port, \ _TGL_DSI_CHKN_REG_0, \ _TGL_DSI_CHKN_REG_1) -#define TGL_DSI_CHKN_LSHS_GB REG_GENMASK(15, 12) +#define TGL_DSI_CHKN_LSHS_GB_MASK REG_GENMASK(15, 12) +#define TGL_DSI_CHKN_LSHS_GB(byte_clocks) REG_FIELD_PREP(TGL_DSI_CHKN_LSHS_GB_MASK, \ + (byte_clocks)) /* Display Stream Splitter Control */ #define DSS_CTL1 _MMIO(0x67400) From 09eea212653304522e9ec74cdda59721af8d4969 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 19 Oct 2021 20:44:33 +0530 Subject: [PATCH 140/176] drm/i915/dsi/xelpd: Add DSI transcoder support Update ADL_P device info to support DSI0, DSI1 v2: Re-define cpu_transcoder_mask only (Jani) Signed-off-by: Vandita Kulkarni Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211019151435.20477-3-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 169837de395d3..44c3577be748d 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -932,8 +932,6 @@ static const struct intel_device_info adl_s_info = { #define XE_LPD_FEATURES \ .abox_mask = GENMASK(1, 0), \ .color = { .degamma_lut_size = 0, .gamma_lut_size = 0 }, \ - .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ - BIT(TRANSCODER_C) | BIT(TRANSCODER_D), \ .dbuf.size = 4096, \ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \ BIT(DBUF_S4), \ @@ -955,12 +953,16 @@ static const struct intel_device_info adl_s_info = { [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = PIPE_C_OFFSET, \ [TRANSCODER_D] = PIPE_D_OFFSET, \ + [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \ + [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \ }, \ .trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ [TRANSCODER_D] = TRANSCODER_D_OFFSET, \ + [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \ + [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \ }, \ XE_LPD_CURSOR_OFFSETS @@ -969,6 +971,9 @@ static const struct intel_device_info adl_p_info = { XE_LPD_FEATURES, PLATFORM(INTEL_ALDERLAKE_P), .require_force_probe = 1, + .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | + BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | + BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), .display.has_cdclk_crawl = 1, .display.has_modular_fia = 1, .display.has_psr_hw_tracking = 0, @@ -1038,6 +1043,8 @@ static const struct intel_device_info dg2_info = { BIT(VECS0) | BIT(VECS1) | BIT(VCS0) | BIT(VCS2), .require_force_probe = 1, + .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | + BIT(TRANSCODER_C) | BIT(TRANSCODER_D), }; #undef PLATFORM From 5a06f68dbe0fb9cc08db9cfae310c7933aebd6d2 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 19 Oct 2021 20:44:34 +0530 Subject: [PATCH 141/176] drm/i915/dsi/xelpd: Disable DC states in Video mode MIPI DSI transcoder cannot be in video mode to support any of the display C states. Bspec: 49195 (For DC*co DSI transcoders cannot be in video mode) Bspec: 49193 (Hardware does not support DC5 or DC6 with MIPI DSI enabled) Bspec: 49188 (desc of DSI_DCSTATE_CTL talks about cmd mode PM control v2: Align to the power domain ordering (Jani) Add bspec references (Imre) Signed-off-by: Vandita Kulkarni Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211019151435.20477-4-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index a31974aa37cec..d30639a59ea5e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3111,6 +3111,7 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915, BIT_ULL(POWER_DOMAIN_MODESET) | \ BIT_ULL(POWER_DOMAIN_AUX_A) | \ BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_PORT_DSI) | \ BIT_ULL(POWER_DOMAIN_INIT)) #define XELPD_AUX_IO_D_XELPD_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_D_XELPD) From dd54575a83d85c031d9c1c4a78607ec3c95696ac Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 15 Nov 2021 13:53:11 +0200 Subject: [PATCH 142/176] drm/i915: include intel-gtt.h only where needed Only intel_gt.c and intel_ggtt.c need the interface. Cc: Andy Shevchenko Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Acked-by: Andy Shevchenko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/034f57db24d6936ac2e4e6830261d791240cdd79.1636977089.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/gt/intel_ggtt.c | 1 + drivers/gpu/drm/i915/gt/intel_gt.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 1 - 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 1fb4a03d7ac35..0c956e5e7fc78 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -9,6 +9,7 @@ #include #include +#include #include "gem/i915_gem_lmem.h" diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 1cb1948ac9594..f2422d48be32d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "intel_gt_debugfs.h" #include "gem/i915_gem_lmem.h" diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e6ba8e96a411b..4d05cb0c0b77f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -50,7 +50,6 @@ #include #include -#include #include #include #include From ce6838afc9244171cd07620bbb82e18695c491e9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Nov 2021 13:53:12 +0200 Subject: [PATCH 143/176] agp/intel-gtt: Replace kernel.h with the necessary inclusions When kernel.h is used in the headers it adds a lot into dependency hell, especially when there are circular dependencies are involved. Replace kernel.h inclusion with the list of what is really being used. Signed-off-by: Andy Shevchenko Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/4d6a976459547407979f4b4c05a52785523e6bd8.1636977089.git.jani.nikula@intel.com --- include/drm/intel-gtt.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index abfefaaf897a0..4e5f8e7e25d09 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -6,7 +6,10 @@ #include #include -#include +#include + +struct pci_dev; +struct sg_table; void intel_gtt_get(u64 *gtt_total, phys_addr_t *mappable_base, From 7e78153aef7f9efcb935487402151de31e0836ad Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 15 Nov 2021 13:53:13 +0200 Subject: [PATCH 144/176] agp/intel-gtt: reduce intel-gtt dependencies more Don't include stuff on behalf of users if they're not strictly necessary for the header. Cc: Andy Shevchenko Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Acked-by: Andy Shevchenko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/7bcaa1684587b9b008d3c41468fb40e63c54fbc7.1636977089.git.jani.nikula@intel.com --- drivers/char/agp/intel-gtt.c | 1 + drivers/gpu/drm/i915/gt/intel_ggtt.c | 1 + include/drm/intel-gtt.h | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 5bfdf222d5f90..c53cc9868cd80 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include "agp.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 0c956e5e7fc78..555111c3bee50 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -3,6 +3,7 @@ * Copyright © 2020 Intel Corporation */ +#include #include #include diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 4e5f8e7e25d09..67530bfef129c 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -4,10 +4,9 @@ #ifndef _DRM_INTEL_GTT_H #define _DRM_INTEL_GTT_H -#include -#include #include +struct agp_bridge_data; struct pci_dev; struct sg_table; From d5e781a2e50fefbcde81f10e0e9e2669fadc9b01 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 15 Nov 2021 16:05:49 +0200 Subject: [PATCH 145/176] drm/i915/fbc: fix the FBC kernel-doc warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the recently introduced 'make htmldocs' warnings: $ make htmldocs 2>&1 > /dev/null | grep i915 ./drivers/gpu/drm/i915/display/intel_fbc.c:635: warning: Excess function parameter 'i915' description in 'intel_fbc_is_active' ./drivers/gpu/drm/i915/display/intel_fbc.c:1638: warning: Excess function parameter 'i915' description in 'intel_fbc_handle_fifo_underrun_irq' ./drivers/gpu/drm/i915/display/intel_fbc.c:635: warning: Function parameter or member 'fbc' not described in 'intel_fbc_is_active' ./drivers/gpu/drm/i915/display/intel_fbc.c:635: warning: Excess function parameter 'i915' description in 'intel_fbc_is_active' ./drivers/gpu/drm/i915/display/intel_fbc.c:1638: warning: Function parameter or member 'fbc' not described in 'intel_fbc_handle_fifo_underrun_irq' ./drivers/gpu/drm/i915/display/intel_fbc.c:1638: warning: Excess function parameter 'i915' description in 'intel_fbc_handle_fifo_underrun_irq' Fixes: e49a656b924e ("drm/i915/fbc: Start passing around intel_fbc") Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211115140549.27629-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_fbc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index a7e0f79ceb637..d0c34bc3af6c2 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -624,7 +624,7 @@ int intel_fbc_set_false_color(struct intel_fbc *fbc, bool enable) /** * intel_fbc_is_active - Is FBC active? - * @i915: i915 device instance + * @fbc: The FBC instance * * This function is used to verify the current state of FBC. * @@ -1592,7 +1592,7 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) /* * intel_fbc_reset_underrun - reset FBC fifo underrun status. - * @i915: i915 device instance + * @fbc: The FBC instance * * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we * want to re-enable FBC after an underrun to increase test coverage. @@ -1622,7 +1622,7 @@ int intel_fbc_reset_underrun(struct intel_fbc *fbc) /** * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun - * @i915: i915 device instance + * @fbc: The FBC instance * * Without FBC, most underruns are harmless and don't really cause too many * problems, except for an annoying message on dmesg. With FBC, underruns can From 1a085e23411de188ad0615f40a9399d80d1f7368 Mon Sep 17 00:00:00 2001 From: Tilak Tangudu Date: Mon, 15 Nov 2021 21:10:54 +0530 Subject: [PATCH 146/176] drm/i915: Disable D3Cold in s2idle and runtime pm s2idle and runtime pm puts the pci gfx device in D3Hot, ACPI runtime monitors the pci tree,if it sees complete tree as D3Hot,it transitions the device to D3Cold.But i915 do not have D3Cold support in S2idle or in runtime pm. so disabling D3cold in above flows and its FIXME. Added pci D3Cold enable/disable in s2idle and runtime suspend/resume flows. Signed-off-by: Tilak Tangudu Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20211115154054.3220476-1-tilak.tangudu@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d9630d79106fc..8229d006f7a65 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1187,6 +1187,14 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) goto out; } + /* + * FIXME: Temporary hammer to avoid freezing the machine on our DGFX + * This should be totally removed when we handle the pci states properly + * on runtime PM and on s2idle cases. + */ + if (suspend_to_idle(dev_priv)) + pci_d3cold_disable(pdev); + pci_disable_device(pdev); /* * During hibernation on some platforms the BIOS may try to access @@ -1350,6 +1358,8 @@ static int i915_drm_resume_early(struct drm_device *dev) pci_set_master(pdev); + pci_d3cold_enable(pdev); + disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); ret = vlv_resume_prepare(dev_priv, false); @@ -1526,6 +1536,7 @@ static int intel_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); int ret; if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv))) @@ -1571,6 +1582,12 @@ static int intel_runtime_suspend(struct device *kdev) drm_err(&dev_priv->drm, "Unclaimed access detected prior to suspending\n"); + /* + * FIXME: Temporary hammer to avoid freezing the machine on our DGFX + * This should be totally removed when we handle the pci states properly + * on runtime PM and on s2idle cases. + */ + pci_d3cold_disable(pdev); rpm->suspended = true; /* @@ -1609,6 +1626,7 @@ static int intel_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); int ret; if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv))) @@ -1621,6 +1639,7 @@ static int intel_runtime_resume(struct device *kdev) intel_opregion_notify_adapter(dev_priv, PCI_D0); rpm->suspended = false; + pci_d3cold_enable(pdev); if (intel_uncore_unclaimed_mmio(&dev_priv->uncore)) drm_dbg(&dev_priv->drm, "Unclaimed access during suspend, bios?\n"); From 58471f6384fd8f807d3ff2e771c34f71c473f6b0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 11 Nov 2021 12:13:02 +0200 Subject: [PATCH 147/176] drm/i915/driver: rename i915_drv.c to i915_driver.c This is more about trimming i915_drv.h than the renamed i915_driver.[ch]. Split out i915_driver.[ch] out of i915_drv.h as a feasible thing to do. Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211111101304.13094-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/Makefile | 2 +- .../drm/i915/{i915_drv.c => i915_driver.c} | 5 ++-- drivers/gpu/drm/i915/i915_driver.h | 24 +++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 11 +-------- drivers/gpu/drm/i915/i915_pci.c | 1 + drivers/gpu/drm/i915/i915_switcheroo.c | 1 + 6 files changed, 31 insertions(+), 13 deletions(-) rename drivers/gpu/drm/i915/{i915_drv.c => i915_driver.c} (99%) create mode 100644 drivers/gpu/drm/i915/i915_driver.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 467872cca027f..568d711a3537b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -30,7 +30,7 @@ subdir-ccflags-y += -I$(srctree)/$(src) # Please keep these build lists sorted! # core driver code -i915-y += i915_drv.o \ +i915-y += i915_driver.o \ i915_config.o \ i915_irq.o \ i915_getparam.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_driver.c similarity index 99% rename from drivers/gpu/drm/i915/i915_drv.c rename to drivers/gpu/drm/i915/i915_driver.c index 8229d006f7a65..119bb2b1f03d8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -29,8 +29,8 @@ #include #include -#include #include +#include #include #include #include @@ -48,8 +48,8 @@ #include "display/intel_acpi.h" #include "display/intel_bw.h" #include "display/intel_cdclk.h" -#include "display/intel_dmc.h" #include "display/intel_display_types.h" +#include "display/intel_dmc.h" #include "display/intel_dp.h" #include "display/intel_dpt.h" #include "display/intel_fbdev.h" @@ -72,6 +72,7 @@ #include "pxp/intel_pxp_pm.h" #include "i915_debugfs.h" +#include "i915_driver.h" #include "i915_drv.h" #include "i915_ioc32.h" #include "i915_irq.h" diff --git a/drivers/gpu/drm/i915/i915_driver.h b/drivers/gpu/drm/i915/i915_driver.h new file mode 100644 index 0000000000000..e99c00fb6312b --- /dev/null +++ b/drivers/gpu/drm/i915/i915_driver.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __I915_DRIVER_H__ +#define __I915_DRIVER_H__ + +#include + +struct pci_dev; +struct pci_device_id; +struct drm_i915_private; + +extern const struct dev_pm_ops i915_pm_ops; + +int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +void i915_driver_remove(struct drm_i915_private *i915); +void i915_driver_shutdown(struct drm_i915_private *i915); + +int i915_resume_switcheroo(struct drm_i915_private *i915); +int i915_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); + +#endif /* __I915_DRIVER_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4d05cb0c0b77f..1a43757bf2614 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1785,16 +1785,7 @@ intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915) return IS_CHERRYVIEW(i915) || intel_ggtt_update_needs_vtd_wa(i915); } -/* i915_drv.c */ -extern const struct dev_pm_ops i915_pm_ops; - -int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -void i915_driver_remove(struct drm_i915_private *i915); -void i915_driver_shutdown(struct drm_i915_private *i915); - -int i915_resume_switcheroo(struct drm_i915_private *i915); -int i915_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); - +/* i915_getparam.c */ int i915_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 44c3577be748d..c408941aba4cf 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -27,6 +27,7 @@ #include #include +#include "i915_driver.h" #include "i915_drv.h" #include "i915_pci.h" diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c index de0e224b56ce3..7f06f5ad07498 100644 --- a/drivers/gpu/drm/i915/i915_switcheroo.c +++ b/drivers/gpu/drm/i915/i915_switcheroo.c @@ -5,6 +5,7 @@ #include +#include "i915_driver.h" #include "i915_drv.h" #include "i915_switcheroo.h" From 4588d7eb3b530b471104d78a19f82df701ec8c25 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 11 Nov 2021 12:13:03 +0200 Subject: [PATCH 148/176] drm/i915/driver: rename driver to i915_drm_driver As a name, "driver" is too generic and short to be easily located in a file this size. Rename it to i915_drm_driver. Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211111101304.13094-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 119bb2b1f03d8..1ef1a4f2815d9 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -92,7 +92,7 @@ #include "intel_region_ttm.h" #include "vlv_suspend.h" -static const struct drm_driver driver; +static const struct drm_driver i915_drm_driver; static int i915_get_bridge_dev(struct drm_i915_private *dev_priv) { @@ -769,7 +769,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) struct intel_device_info *device_info; struct drm_i915_private *i915; - i915 = devm_drm_dev_alloc(&pdev->dev, &driver, + i915 = devm_drm_dev_alloc(&pdev->dev, &i915_drm_driver, struct drm_i915_private, drm); if (IS_ERR(i915)) return i915; @@ -1803,7 +1803,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW), }; -static const struct drm_driver driver = { +static const struct drm_driver i915_drm_driver = { /* Don't use MTRRs here; the Xserver or userspace app should * deal with them for Intel hardware. */ From b8d65b8a5aea3309c14cb899149ad5ce93589f58 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 11 Nov 2021 12:13:04 +0200 Subject: [PATCH 149/176] drm/i915/driver: add i915_driver_ prefix to functions Add the i915_driver_ prefix to the switcheroo functions in i915_driver.[ch]. Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211111101304.13094-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_driver.c | 5 +++-- drivers/gpu/drm/i915/i915_driver.h | 4 ++-- drivers/gpu/drm/i915/i915_switcheroo.c | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 1ef1a4f2815d9..b394b8702f1cc 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1220,7 +1220,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) return ret; } -int i915_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state) +int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, + pm_message_t state) { int error; @@ -1381,7 +1382,7 @@ static int i915_drm_resume_early(struct drm_device *dev) return ret; } -int i915_resume_switcheroo(struct drm_i915_private *i915) +int i915_driver_resume_switcheroo(struct drm_i915_private *i915) { int ret; diff --git a/drivers/gpu/drm/i915/i915_driver.h b/drivers/gpu/drm/i915/i915_driver.h index e99c00fb6312b..9ef8db4aa0a6f 100644 --- a/drivers/gpu/drm/i915/i915_driver.h +++ b/drivers/gpu/drm/i915/i915_driver.h @@ -18,7 +18,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent); void i915_driver_remove(struct drm_i915_private *i915); void i915_driver_shutdown(struct drm_i915_private *i915); -int i915_resume_switcheroo(struct drm_i915_private *i915); -int i915_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); +int i915_driver_resume_switcheroo(struct drm_i915_private *i915); +int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); #endif /* __I915_DRIVER_H__ */ diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c index 7f06f5ad07498..23777d500cdf9 100644 --- a/drivers/gpu/drm/i915/i915_switcheroo.c +++ b/drivers/gpu/drm/i915/i915_switcheroo.c @@ -25,12 +25,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, i915->drm.switch_power_state = DRM_SWITCH_POWER_CHANGING; /* i915 resume handler doesn't set to D0 */ pci_set_power_state(pdev, PCI_D0); - i915_resume_switcheroo(i915); + i915_driver_resume_switcheroo(i915); i915->drm.switch_power_state = DRM_SWITCH_POWER_ON; } else { drm_info(&i915->drm, "switched off\n"); i915->drm.switch_power_state = DRM_SWITCH_POWER_CHANGING; - i915_suspend_switcheroo(i915, pmm); + i915_driver_suspend_switcheroo(i915, pmm); i915->drm.switch_power_state = DRM_SWITCH_POWER_OFF; } } From fe69a2dd88b2c741bd55336d74dd484d7b848679 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 16 Nov 2021 14:49:16 +0300 Subject: [PATCH 150/176] drm/i915/guc: fix NULL vs IS_ERR() checking The intel_engine_create_virtual() function does not return NULL. It returns error pointers. Fixes: e5e32171a2cf ("drm/i915/guc: Connect UAPI to GuC multi-lrc interface") Signed-off-by: Dan Carpenter Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20211116114916.GB11936@kili --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index d7710debcd478..3d6df8aaefb83 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3079,8 +3079,8 @@ guc_create_parallel(struct intel_engine_cs **engines, ce = intel_engine_create_virtual(siblings, num_siblings, FORCE_VIRTUAL); - if (!ce) { - err = ERR_PTR(-ENOMEM); + if (IS_ERR(ce)) { + err = ERR_CAST(ce); goto unwind; } From a59308a5fb231aca72b9b070a6577fa49ec2d72a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 15 Nov 2021 20:11:21 +0200 Subject: [PATCH 151/176] drm/i915: Fix fastsets on TypeC ports following a non-blocking modeset After a non-blocking modeset on a TypeC port's CRTC - possibly blocked later in drm_atomic_helper_wait_for_dependencies() - a fastset on the same CRTC may copy the state of CRTC before this gets updated to reflect the up-to-date DP-alt vs. TBT-alt TypeC mode DPLL used for the CRTC. In this case after the first (non-blocking) commit completes enabling the DPLL required for the up-to-date TypeC mode the following fastset will update the CRTC state pointing to the wrong DPLL. A subsequent disabling modeset will try to disable the wrong PLL, triggering a state checker WARN (and leaving the DPLL which is actually used active for good). Fix the above race by copying the DPLL state for fastset CRTCs from the old CRTC state at the point where it's guaranteed to be up-to-date already. This could be handled in the encoder's update_prepare() hook as well, but that's a bigger change, which is better done as a follow-up. v2: Copy dpll_hw_state as well. (Ville) Testcase: igt/kms_busy/extended-modeset-hang-newfb-with-reset Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4308 Cc: Ville Syrjala Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20211115181121.156197-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 31 ++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0ceee8ac66717..f3c9208a30b16 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1572,10 +1572,30 @@ intel_connector_primary_encoder(struct intel_connector *connector) static void intel_encoders_update_prepare(struct intel_atomic_state *state) { + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *new_crtc_state, *old_crtc_state; + struct intel_crtc *crtc; struct drm_connector_state *new_conn_state; struct drm_connector *connector; int i; + /* + * Make sure the DPLL state is up-to-date for fastset TypeC ports after non-blocking commits. + * TODO: Update the DPLL state for all cases in the encoder->update_prepare() hook. + */ + if (i915->dpll.mgr) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (intel_crtc_needs_modeset(new_crtc_state)) + continue; + + new_crtc_state->shared_dpll = old_crtc_state->shared_dpll; + new_crtc_state->dpll_hw_state = old_crtc_state->dpll_hw_state; + } + } + + if (!state->modeset) + return; + for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) { struct intel_connector *intel_connector; @@ -1602,6 +1622,9 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state) struct drm_connector *connector; int i; + if (!state->modeset) + return; + for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) { struct intel_connector *intel_connector; @@ -8670,8 +8693,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) } } - if (state->modeset) - intel_encoders_update_prepare(state); + intel_encoders_update_prepare(state); intel_dbuf_pre_plane_update(state); @@ -8683,11 +8705,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) /* Now enable the clocks, plane, pipe, and connectors that we set up. */ dev_priv->display->commit_modeset_enables(state); - if (state->modeset) { - intel_encoders_update_complete(state); + intel_encoders_update_complete(state); + if (state->modeset) intel_set_cdclk_post_plane_update(state); - } intel_wait_for_vblank_workers(state); From 4121113410fe16649d0a66c81715c8fab7740b14 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 24 Oct 2021 17:50:20 +0200 Subject: [PATCH 152/176] drm/i915/vlv_dsi: Double pixelclock on read-back for dual-link panels In intel_dsi_get_config() double the pclk returned by foo_dsi_get_pclk() for dual-link panels. This fixes the following WARN triggering: i915 0000:00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in pixel_rate (expected 235710, found 118056) i915 0000:00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in hw.pipe_mode.crtc_clock (expected 235710, found 118056) i915 0000:00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in hw.adjusted_mode.crtc_clock (expected 235710, found 118056) i915 0000:00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in port_clock (expected 235710, found 118056) ------------[ cut here ]------------ pipe state doesn't match! WARNING: CPU: 3 PID: 136 at drivers/gpu/drm/i915/display/intel_display.c:9125 intel_display_finish_reset+0x1bd3/0x2050 [i915] ... This has been tested on a Xiaomi Mi Pad 2 (with CHT x5-Z8500 SoC) tablet, with a 1536x2048 dual-link DSI panel. Note this fix was taken from icl_dsi.c which does the same in its get_config(). Cc: Tsuchiya Yuto Signed-off-by: Hans de Goede Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211024155020.126328-1-hdegoede@redhat.com --- drivers/gpu/drm/i915/display/vlv_dsi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 07584695514b7..59ebfbd46e6fa 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1258,7 +1258,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); u32 pclk; + drm_dbg_kms(&dev_priv->drm, "\n"); pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI); @@ -1270,6 +1272,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, pclk = vlv_dsi_get_pclk(encoder, pipe_config); } + if (intel_dsi->dual_link) + pclk *= 2; + if (pclk) { pipe_config->hw.adjusted_mode.crtc_clock = pclk; pipe_config->port_clock = pclk; From 4765d061d50559ce3addc9a86433c35f48d76085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Nov 2021 20:31:01 +0200 Subject: [PATCH 153/176] drm/i915: Move vrr push after the frame counter sampling again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving the vrr push to happen before sampling the frame counter was wrong. If we are already in vblank when the push is sent the vblank exit will start immediately which causes the sampled frame counter to correspond to the next frame instead of the current frame. So put things back into the original order (except we should keep the vrr push within the irq disable section to avoid pointless irq related delays here). We'll just have to accept the tiny race that exists between sampling the frame counter vs. vrr push. And let's at least document said race properly in a comment. I suppose we could try to minimize the race by sampling the frame counter just before sending the push, but that would require changing drm_crtc_arm_vblank_event() to accept a caller provided vblank counter value, so leave it be for now. Another thing we could do is change the vblank evasion to account for the case where a push was already sent. That would anyway be required for mailbox style updates. Currently mailbox updates are only used by the legacy cursor, but we don't do a vrr push for those. Cc: Manasi Navare Fixes: 6f9976bd1310 ("drm/i915: Do vrr push before sampling the frame counter") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211117183103.27418-1-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_crtc.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index f09df2cf052b8..cf403be7736c2 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -610,9 +610,6 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end); - /* Send VRR Push to terminate Vblank */ - intel_vrr_send_push(new_crtc_state); - /* * Incase of mipi dsi command mode, we need to set frame update * request for every commit. @@ -641,6 +638,22 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) new_crtc_state->uapi.event = NULL; } + /* + * Send VRR Push to terminate Vblank. If we are already in vblank + * this has to be done _after_ sampling the frame counter, as + * otherwise the push would immediately terminate the vblank and + * the sampled frame counter would correspond to the next frame + * instead of the current frame. + * + * There is a tiny race here (iff vblank evasion failed us) where + * we might sample the frame counter just before vmax vblank start + * but the push would be sent just after it. That would cause the + * push to affect the next frame instead of the current frame, + * which would cause the next frame to terminate already at vmin + * vblank start instead of vmax vblank start. + */ + intel_vrr_send_push(new_crtc_state); + local_irq_enable(); if (intel_vgpu_active(dev_priv)) From 0088d39b6ad9f7d814c10e7188aba0ddbc737883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Nov 2021 20:31:02 +0200 Subject: [PATCH 154/176] drm/i915: Do vblank evasion correctly if vrr push has already been sent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's adjust the vblank evasion to account for the case where a push has already been sent. In that case the vblank exit will start at vmin vblank start (as opposed to vmax vblank start when no push has been sent). This should minimize the effects of the tiny race between sampling the frame counter vs. intel_vrr_send_push() during the previous frame. This will also be required if we want to do mailbox style updates with vrr since then we'd definitely do multiple commits per frame. Currently mailbox updates are only used by the legacy cursor, but we don't do vrr push for those. Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211117183103.27418-2-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_crtc.c | 10 +++++++--- drivers/gpu/drm/i915/display/intel_vrr.c | 12 ++++++++++++ drivers/gpu/drm/i915/display/intel_vrr.h | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index cf403be7736c2..eb5444f90e77c 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -470,10 +470,14 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state) if (intel_crtc_needs_vblank_work(new_crtc_state)) intel_crtc_vblank_work_init(new_crtc_state); - if (new_crtc_state->vrr.enable) - vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state); - else + if (new_crtc_state->vrr.enable) { + if (intel_vrr_is_push_sent(new_crtc_state)) + vblank_start = intel_vrr_vmin_vblank_start(new_crtc_state); + else + vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state); + } else { vblank_start = intel_mode_vblank_start(adjusted_mode); + } /* FIXME needs to be calibrated sensibly */ min = vblank_start - intel_usecs_to_scanlines(adjusted_mode, diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index c335b1dbafcf8..db1c3902fc2d1 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -193,6 +193,18 @@ void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) TRANS_PUSH_EN | TRANS_PUSH_SEND); } +bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + if (!crtc_state->vrr.enable) + return false; + + return intel_de_read(dev_priv, TRANS_PUSH(cpu_transcoder)) & TRANS_PUSH_SEND; +} + void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h index 96f9c9c27ab9f..1c2da572693d2 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.h +++ b/drivers/gpu/drm/i915/display/intel_vrr.h @@ -23,6 +23,7 @@ void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, void intel_vrr_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_vrr_send_push(const struct intel_crtc_state *crtc_state); +bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state); void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state); void intel_vrr_get_config(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); From 9cca74b51ea543f4f64464b0347ff5d43a4e57ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Nov 2021 20:31:03 +0200 Subject: [PATCH 155/176] drm/i915: Fix framestart_delay commens in VRR code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since I originally wrote these comments we decided to change our definition of framestart_delay from 0-3 to 1-4. Adjust the comments to match that new convention. The actual code was adjusted already. Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211117183103.27418-3-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_vrr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index db1c3902fc2d1..139e8936edc58 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -60,7 +60,7 @@ intel_vrr_check_modeset(struct intel_atomic_state *state) * Between those two points the vblank exit starts (and hence registers get * latched) ASAP after a push is sent. * - * framestart_delay is programmable 0-3. + * framestart_delay is programmable 1-4. */ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_state) { @@ -138,13 +138,13 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, i915->window2_delay; else /* - * FIXME: s/4/framestart_delay+1/ to get consistent + * FIXME: s/4/framestart_delay/ to get consistent * earliest/latest points for register latching regardless * of the framestart_delay used? * * FIXME: this really needs the extra scanline to provide consistent * behaviour for all framestart_delay values. Otherwise with - * framestart_delay==3 we will end up extending the min vblank by + * framestart_delay==4 we will end up extending the min vblank by * one extra line. */ crtc_state->vrr.pipeline_full = From a37795cbdff243c198d9cf9615bd5d016bbfd546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 14 Oct 2021 21:18:55 +0300 Subject: [PATCH 156/176] drm/i915: Declare .(de)gamma_lut_tests for icl+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All interpolated gamma modes including the icl+ multi segment mode require non-decreasing entries for the interpolation to work correctly. For some reason we're forgetting to declare that for icl+. Let us do so. References: https://gitlab.freedesktop.org/drm/intel/-/issues/3916 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211014181856.17581-1-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/i915_pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index c408941aba4cf..b8586a5552441 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -146,6 +146,12 @@ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ DRM_COLOR_LUT_EQUAL_CHANNELS, \ } +#define ICL_COLORS \ + .color = { .degamma_lut_size = 33, .gamma_lut_size = 262145, \ + .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ + DRM_COLOR_LUT_EQUAL_CHANNELS, \ + .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ + } /* Keep in gen based order, and chronological order within a gen */ @@ -812,7 +818,7 @@ static const struct intel_device_info cml_gt2_info = { [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \ }, \ GEN(11), \ - .color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }, \ + ICL_COLORS, \ .dbuf.size = 2048, \ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \ .display.has_dsc = 1, \ From 99510e1afb4863a225207146bd988064c5fd0629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 14 Oct 2021 21:18:56 +0300 Subject: [PATCH 157/176] drm/i915: Disable DSB usage for now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out the DSB has trouble correctly loading the gamma LUT. From a cursory look maybe like some entries do not load properly, or they get loaded with some gibberish. Unfortunately our current kms_color/etc. tests do not seem to catch this. I had a brief look at the generated DSB batch and it looked correct. Tried a few quick tricks like writing the index register twice/etc. but didn't see any improvement. Also tried switching to the 10bit gamma mode in case there is yet another issue with the multi-segment mode, but even the 10bit mode was showing issues. Switching to mmio fixes all of it. I suppose one theory is that maybe the DSB bangs on the LUT too quickly and it can't keep up and instead some data either gets dropped or corrupted. To confirm that someone should try to slow down the DSB's progress a bit. Another thought was that maybe the LUT has crappy dual porting and you get contention if you try to load it during active scanout. But why then would the mmio path work, unless it's just sufficiently slow? Whatever the case, this is currently busted so let's disable it until we get to the root of the problem. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3916 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211014181856.17581-2-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/i915_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index b8586a5552441..52749b8f4f6b8 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -873,7 +873,7 @@ static const struct intel_device_info jsl_info = { TGL_CURSOR_OFFSETS, \ .has_global_mocs = 1, \ .has_pxp = 1, \ - .display.has_dsb = 1 + .display.has_dsb = 0 /* FIXME: LUT load is broken with DSB */ static const struct intel_device_info tgl_info = { GEN12_FEATURES, From b2e7d636d9ad5dc7e84a95b004345cdd2fc82b2d Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Tue, 16 Nov 2021 15:12:09 -0800 Subject: [PATCH 158/176] drm/i915/: Extend VRR platform support to Gen 11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VRR is supported on Gen 11 HW , hence extend the support in the driver to enable this for Gen 11. Cc: Ville Syrjälä Signed-off-by: Manasi Navare Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211116231209.28621-1-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1a43757bf2614..4f58e14565057 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1741,7 +1741,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_DISPLAY(dev_priv) (INTEL_INFO(dev_priv)->pipe_mask != 0) -#define HAS_VRR(i915) (GRAPHICS_VER(i915) >= 12) +#define HAS_VRR(i915) (GRAPHICS_VER(i915) >= 11) #define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5) From 6bb0a0e0fd358d4f9f6ce4c2d36c1f80d7496f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 12 Nov 2021 21:38:13 +0200 Subject: [PATCH 159/176] drm/i915: Clean up FPGA_DBG/CLAIM_ER bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for FPGA_DBG/CLAIM_ER bits. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211112193813.8224-10-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a6dcf252a70fc..d9d47ab8d6281 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2798,12 +2798,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define GEN12_AUX_ERR_DBG _MMIO(0x43f4) #define FPGA_DBG _MMIO(0x42300) -#define FPGA_DBG_RM_NOCLAIM (1 << 31) +#define FPGA_DBG_RM_NOCLAIM REG_BIT(31) #define CLAIM_ER _MMIO(VLV_DISPLAY_BASE + 0x2028) -#define CLAIM_ER_CLR (1 << 31) -#define CLAIM_ER_OVERFLOW (1 << 16) -#define CLAIM_ER_CTR_MASK 0xffff +#define CLAIM_ER_CLR REG_BIT(31) +#define CLAIM_ER_OVERFLOW REG_BIT(16) +#define CLAIM_ER_CTR_MASK REG_GENMASK(15, 0) #define DERRMR _MMIO(0x44050) /* Note that HBLANK events are reserved on bdw+ */ From 7d938bc0119507d11dc02cc6ee47f386cd5d2f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 12 Nov 2021 21:38:12 +0200 Subject: [PATCH 160/176] drm/i915: Clean up DPINVGTT/VLV_DPFLIPSTAT bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for DPINVTT/VLV_DPFLIPSTAT bits. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211112193813.8224-9-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 94 ++++++++++++++++----------------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 77680bca46eec..a4b0a0c45b132 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3016,7 +3016,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) if (IS_CHERRYVIEW(dev_priv)) intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); else - intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK); + intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); intel_uncore_write(uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d9d47ab8d6281..c3a4c9a2222d2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6276,55 +6276,55 @@ enum { #define PIPE_STATUS_PORT_UNDERRUN_XELPD REG_BIT(26) #define VLV_DPFLIPSTAT _MMIO(VLV_DISPLAY_BASE + 0x70028) -#define PIPEB_LINE_COMPARE_INT_EN (1 << 29) -#define PIPEB_HLINE_INT_EN (1 << 28) -#define PIPEB_VBLANK_INT_EN (1 << 27) -#define SPRITED_FLIP_DONE_INT_EN (1 << 26) -#define SPRITEC_FLIP_DONE_INT_EN (1 << 25) -#define PLANEB_FLIP_DONE_INT_EN (1 << 24) -#define PIPE_PSR_INT_EN (1 << 22) -#define PIPEA_LINE_COMPARE_INT_EN (1 << 21) -#define PIPEA_HLINE_INT_EN (1 << 20) -#define PIPEA_VBLANK_INT_EN (1 << 19) -#define SPRITEB_FLIP_DONE_INT_EN (1 << 18) -#define SPRITEA_FLIP_DONE_INT_EN (1 << 17) -#define PLANEA_FLIPDONE_INT_EN (1 << 16) -#define PIPEC_LINE_COMPARE_INT_EN (1 << 13) -#define PIPEC_HLINE_INT_EN (1 << 12) -#define PIPEC_VBLANK_INT_EN (1 << 11) -#define SPRITEF_FLIPDONE_INT_EN (1 << 10) -#define SPRITEE_FLIPDONE_INT_EN (1 << 9) -#define PLANEC_FLIPDONE_INT_EN (1 << 8) +#define PIPEB_LINE_COMPARE_INT_EN REG_BIT(29) +#define PIPEB_HLINE_INT_EN REG_BIT(28) +#define PIPEB_VBLANK_INT_EN REG_BIT(27) +#define SPRITED_FLIP_DONE_INT_EN REG_BIT(26) +#define SPRITEC_FLIP_DONE_INT_EN REG_BIT(25) +#define PLANEB_FLIP_DONE_INT_EN REG_BIT(24) +#define PIPE_PSR_INT_EN REG_BIT(22) +#define PIPEA_LINE_COMPARE_INT_EN REG_BIT(21) +#define PIPEA_HLINE_INT_EN REG_BIT(20) +#define PIPEA_VBLANK_INT_EN REG_BIT(19) +#define SPRITEB_FLIP_DONE_INT_EN REG_BIT(18) +#define SPRITEA_FLIP_DONE_INT_EN REG_BIT(17) +#define PLANEA_FLIPDONE_INT_EN REG_BIT(16) +#define PIPEC_LINE_COMPARE_INT_EN REG_BIT(13) +#define PIPEC_HLINE_INT_EN REG_BIT(12) +#define PIPEC_VBLANK_INT_EN REG_BIT(11) +#define SPRITEF_FLIPDONE_INT_EN REG_BIT(10) +#define SPRITEE_FLIPDONE_INT_EN REG_BIT(9) +#define PLANEC_FLIPDONE_INT_EN REG_BIT(8) #define DPINVGTT _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */ -#define SPRITEF_INVALID_GTT_INT_EN (1 << 27) -#define SPRITEE_INVALID_GTT_INT_EN (1 << 26) -#define PLANEC_INVALID_GTT_INT_EN (1 << 25) -#define CURSORC_INVALID_GTT_INT_EN (1 << 24) -#define CURSORB_INVALID_GTT_INT_EN (1 << 23) -#define CURSORA_INVALID_GTT_INT_EN (1 << 22) -#define SPRITED_INVALID_GTT_INT_EN (1 << 21) -#define SPRITEC_INVALID_GTT_INT_EN (1 << 20) -#define PLANEB_INVALID_GTT_INT_EN (1 << 19) -#define SPRITEB_INVALID_GTT_INT_EN (1 << 18) -#define SPRITEA_INVALID_GTT_INT_EN (1 << 17) -#define PLANEA_INVALID_GTT_INT_EN (1 << 16) -#define DPINVGTT_EN_MASK 0xff0000 -#define DPINVGTT_EN_MASK_CHV 0xfff0000 -#define SPRITEF_INVALID_GTT_STATUS (1 << 11) -#define SPRITEE_INVALID_GTT_STATUS (1 << 10) -#define PLANEC_INVALID_GTT_STATUS (1 << 9) -#define CURSORC_INVALID_GTT_STATUS (1 << 8) -#define CURSORB_INVALID_GTT_STATUS (1 << 7) -#define CURSORA_INVALID_GTT_STATUS (1 << 6) -#define SPRITED_INVALID_GTT_STATUS (1 << 5) -#define SPRITEC_INVALID_GTT_STATUS (1 << 4) -#define PLANEB_INVALID_GTT_STATUS (1 << 3) -#define SPRITEB_INVALID_GTT_STATUS (1 << 2) -#define SPRITEA_INVALID_GTT_STATUS (1 << 1) -#define PLANEA_INVALID_GTT_STATUS (1 << 0) -#define DPINVGTT_STATUS_MASK 0xff -#define DPINVGTT_STATUS_MASK_CHV 0xfff +#define DPINVGTT_EN_MASK_CHV REG_GENMASK(27, 16) +#define DPINVGTT_EN_MASK_VLV REG_GENMASK(23, 16) +#define SPRITEF_INVALID_GTT_INT_EN REG_BIT(27) +#define SPRITEE_INVALID_GTT_INT_EN REG_BIT(26) +#define PLANEC_INVALID_GTT_INT_EN REG_BIT(25) +#define CURSORC_INVALID_GTT_INT_EN REG_BIT(24) +#define CURSORB_INVALID_GTT_INT_EN REG_BIT(23) +#define CURSORA_INVALID_GTT_INT_EN REG_BIT(22) +#define SPRITED_INVALID_GTT_INT_EN REG_BIT(21) +#define SPRITEC_INVALID_GTT_INT_EN REG_BIT(20) +#define PLANEB_INVALID_GTT_INT_EN REG_BIT(19) +#define SPRITEB_INVALID_GTT_INT_EN REG_BIT(18) +#define SPRITEA_INVALID_GTT_INT_EN REG_BIT(17) +#define PLANEA_INVALID_GTT_INT_EN REG_BIT(16) +#define DPINVGTT_STATUS_MASK_CHV REG_GENMASK(11, 0) +#define DPINVGTT_STATUS_MASK_VLV REG_GENMASK(7, 0) +#define SPRITEF_INVALID_GTT_STATUS REG_BIT(11) +#define SPRITEE_INVALID_GTT_STATUS REG_BIT(10) +#define PLANEC_INVALID_GTT_STATUS REG_BIT(9) +#define CURSORC_INVALID_GTT_STATUS REG_BIT(8) +#define CURSORB_INVALID_GTT_STATUS REG_BIT(7) +#define CURSORA_INVALID_GTT_STATUS REG_BIT(6) +#define SPRITED_INVALID_GTT_STATUS REG_BIT(5) +#define SPRITEC_INVALID_GTT_STATUS REG_BIT(4) +#define PLANEB_INVALID_GTT_STATUS REG_BIT(3) +#define SPRITEB_INVALID_GTT_STATUS REG_BIT(2) +#define SPRITEA_INVALID_GTT_STATUS REG_BIT(1) +#define PLANEA_INVALID_GTT_STATUS REG_BIT(0) #define DSPARB _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70030) #define DSPARB_CSTART_MASK (0x7f << 7) From 51707f22744439f0ba009f0665faf7964b4e1b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 12 Nov 2021 21:38:11 +0200 Subject: [PATCH 161/176] drm/i915: Clean up CRC register defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for the CRC registers. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211112193813.8224-8-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_reg.h | 77 ++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c3a4c9a2222d2..47fcd104868fe 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4319,47 +4319,52 @@ enum { /* Pipe A CRC regs */ #define _PIPE_CRC_CTL_A 0x60050 -#define PIPE_CRC_ENABLE (1 << 31) +#define PIPE_CRC_ENABLE REG_BIT(31) /* skl+ source selection */ -#define PIPE_CRC_SOURCE_PLANE_1_SKL (0 << 28) -#define PIPE_CRC_SOURCE_PLANE_2_SKL (2 << 28) -#define PIPE_CRC_SOURCE_DMUX_SKL (4 << 28) -#define PIPE_CRC_SOURCE_PLANE_3_SKL (6 << 28) -#define PIPE_CRC_SOURCE_PLANE_4_SKL (7 << 28) -#define PIPE_CRC_SOURCE_PLANE_5_SKL (5 << 28) -#define PIPE_CRC_SOURCE_PLANE_6_SKL (3 << 28) -#define PIPE_CRC_SOURCE_PLANE_7_SKL (1 << 28) +#define PIPE_CRC_SOURCE_MASK_SKL REG_GENMASK(30, 28) +#define PIPE_CRC_SOURCE_PLANE_1_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 0) +#define PIPE_CRC_SOURCE_PLANE_2_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 2) +#define PIPE_CRC_SOURCE_DMUX_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 4) +#define PIPE_CRC_SOURCE_PLANE_3_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 6) +#define PIPE_CRC_SOURCE_PLANE_4_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 7) +#define PIPE_CRC_SOURCE_PLANE_5_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 5) +#define PIPE_CRC_SOURCE_PLANE_6_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 3) +#define PIPE_CRC_SOURCE_PLANE_7_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 1) /* ivb+ source selection */ -#define PIPE_CRC_SOURCE_PRIMARY_IVB (0 << 29) -#define PIPE_CRC_SOURCE_SPRITE_IVB (1 << 29) -#define PIPE_CRC_SOURCE_PF_IVB (2 << 29) +#define PIPE_CRC_SOURCE_MASK_IVB REG_GENMASK(30, 29) +#define PIPE_CRC_SOURCE_PRIMARY_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 0) +#define PIPE_CRC_SOURCE_SPRITE_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 1) +#define PIPE_CRC_SOURCE_PF_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 2) /* ilk+ source selection */ -#define PIPE_CRC_SOURCE_PRIMARY_ILK (0 << 28) -#define PIPE_CRC_SOURCE_SPRITE_ILK (1 << 28) -#define PIPE_CRC_SOURCE_PIPE_ILK (2 << 28) -/* embedded DP port on the north display block, reserved on ivb */ -#define PIPE_CRC_SOURCE_PORT_A_ILK (4 << 28) -#define PIPE_CRC_SOURCE_FDI_ILK (5 << 28) /* reserved on ivb */ +#define PIPE_CRC_SOURCE_MASK_ILK REG_GENMASK(30, 28) +#define PIPE_CRC_SOURCE_PRIMARY_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 0) +#define PIPE_CRC_SOURCE_SPRITE_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 1) +#define PIPE_CRC_SOURCE_PIPE_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 2) +/* embedded DP port on the north display block */ +#define PIPE_CRC_SOURCE_PORT_A_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 4) +#define PIPE_CRC_SOURCE_FDI_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 5) /* vlv source selection */ -#define PIPE_CRC_SOURCE_PIPE_VLV (0 << 27) -#define PIPE_CRC_SOURCE_HDMIB_VLV (1 << 27) -#define PIPE_CRC_SOURCE_HDMIC_VLV (2 << 27) +#define PIPE_CRC_SOURCE_MASK_VLV REG_GENMASK(30, 27) +#define PIPE_CRC_SOURCE_PIPE_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 0) +#define PIPE_CRC_SOURCE_HDMIB_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 1) +#define PIPE_CRC_SOURCE_HDMIC_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 2) /* with DP port the pipe source is invalid */ -#define PIPE_CRC_SOURCE_DP_D_VLV (3 << 27) -#define PIPE_CRC_SOURCE_DP_B_VLV (6 << 27) -#define PIPE_CRC_SOURCE_DP_C_VLV (7 << 27) +#define PIPE_CRC_SOURCE_DP_D_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 3) +#define PIPE_CRC_SOURCE_DP_B_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 6) +#define PIPE_CRC_SOURCE_DP_C_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 7) /* gen3+ source selection */ -#define PIPE_CRC_SOURCE_PIPE_I9XX (0 << 28) -#define PIPE_CRC_SOURCE_SDVOB_I9XX (1 << 28) -#define PIPE_CRC_SOURCE_SDVOC_I9XX (2 << 28) +#define PIPE_CRC_SOURCE_MASK_I9XX REG_GENMASK(30, 28) +#define PIPE_CRC_SOURCE_PIPE_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 0) +#define PIPE_CRC_SOURCE_SDVOB_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 1) +#define PIPE_CRC_SOURCE_SDVOC_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 2) /* with DP/TV port the pipe source is invalid */ -#define PIPE_CRC_SOURCE_DP_D_G4X (3 << 28) -#define PIPE_CRC_SOURCE_TV_PRE (4 << 28) -#define PIPE_CRC_SOURCE_TV_POST (5 << 28) -#define PIPE_CRC_SOURCE_DP_B_G4X (6 << 28) -#define PIPE_CRC_SOURCE_DP_C_G4X (7 << 28) +#define PIPE_CRC_SOURCE_DP_D_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 3) +#define PIPE_CRC_SOURCE_TV_PRE REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 4) +#define PIPE_CRC_SOURCE_TV_POST REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 5) +#define PIPE_CRC_SOURCE_DP_B_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 6) +#define PIPE_CRC_SOURCE_DP_C_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 7) /* gen2 doesn't have source selection bits */ -#define PIPE_CRC_INCLUDE_BORDER_I8XX (1 << 30) +#define PIPE_CRC_INCLUDE_BORDER_I8XX REG_BIT(30) #define _PIPE_CRC_RES_1_A_IVB 0x60064 #define _PIPE_CRC_RES_2_A_IVB 0x60068 @@ -5009,9 +5014,9 @@ enum { #define PORT_DFT2_G4X _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61154) #define DC_BALANCE_RESET_VLV (1 << 31) #define PIPE_SCRAMBLE_RESET_MASK ((1 << 14) | (0x3 << 0)) -#define PIPE_C_SCRAMBLE_RESET (1 << 14) /* chv */ -#define PIPE_B_SCRAMBLE_RESET (1 << 1) -#define PIPE_A_SCRAMBLE_RESET (1 << 0) +#define PIPE_C_SCRAMBLE_RESET REG_BIT(14) /* chv */ +#define PIPE_B_SCRAMBLE_RESET REG_BIT(1) +#define PIPE_A_SCRAMBLE_RESET REG_BIT(0) /* Gen 3 SDVO bits: */ #define SDVO_ENABLE (1 << 31) From 6f51260f0eda41a19dff4023d14d543907f0f967 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 16 Nov 2021 19:14:30 +0200 Subject: [PATCH 162/176] drm/i915: drop intel_display.h include from intel_ddi.h Use forward declarations instead. Signed-off-by: Jani Nikula Reviewed-by: Daniel Vetter Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211116171434.20516-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 6f4551c9d5b7d..c2fea65629179 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -6,11 +6,11 @@ #ifndef __INTEL_DDI_H__ #define __INTEL_DDI_H__ -#include "intel_display.h" #include "i915_reg.h" struct drm_connector_state; struct drm_i915_private; +struct intel_atomic_state; struct intel_connector; struct intel_crtc; struct intel_crtc_state; @@ -18,6 +18,8 @@ struct intel_dp; struct intel_dpll_hw_state; struct intel_encoder; struct intel_shared_dpll; +enum pipe; +enum port; enum transcoder; i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder, From 497520ca1915a91188560a26c2dceb9b9c43db4e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 16 Nov 2021 19:14:31 +0200 Subject: [PATCH 163/176] drm/i915: drop intel_display.h include from intel_dpll_mgr.h Use forward declarations instead. Signed-off-by: Jani Nikula Reviewed-by: Daniel Vetter Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211116171434.20516-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 2f59d863be4c0..ef28897538070 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -27,7 +27,6 @@ #include -#include "intel_display.h" #include "intel_wakeref.h" /*FIXME: Move this to a more appropriate place. */ @@ -37,6 +36,7 @@ (void) (&__a == &__b); \ __a > __b ? (__a - __b) : (__b - __a); }) +enum tc_port; struct drm_device; struct drm_i915_private; struct intel_atomic_state; From 6abf2fc0072b020cdbb9124ea935603b02502e6c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 16 Nov 2021 19:14:32 +0200 Subject: [PATCH 164/176] drm/i915/debugfs: move debug printing to intel_display_power.c The debugfs should have no special privileges to look into the implementation guts. Move the actual debug printing of power domains to intel_display_power.c. Cc: Imre Deak Signed-off-by: Jani Nikula Reviewed-by: Daniel Vetter Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211116171434.20516-3-jani.nikula@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 23 ++--------------- .../drm/i915/display/intel_display_power.c | 25 +++++++++++++++++++ .../drm/i915/display/intel_display_power.h | 2 ++ 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 3f5a5e1b1c41f..acf70ae66a292 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -471,28 +471,9 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops, static int i915_power_domain_info(struct seq_file *m, void *unused) { - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct i915_power_domains *power_domains = &dev_priv->power_domains; - int i; - - mutex_lock(&power_domains->lock); - - seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count"); - for (i = 0; i < power_domains->power_well_count; i++) { - struct i915_power_well *power_well; - enum intel_display_power_domain power_domain; - - power_well = &power_domains->power_wells[i]; - seq_printf(m, "%-25s %d\n", power_well->desc->name, - power_well->count); - - for_each_power_domain(power_domain, power_well->desc->domains) - seq_printf(m, " %-23s %d\n", - intel_display_power_domain_str(power_domain), - power_domains->domain_use_count[power_domain]); - } + struct drm_i915_private *i915 = node_to_i915(m->private); - mutex_unlock(&power_domains->lock); + intel_display_power_debug(i915, m); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index d30639a59ea5e..5ebc758498c80 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -6397,3 +6397,28 @@ void intel_display_power_resume(struct drm_i915_private *i915) hsw_disable_pc8(i915); } } + +void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m) +{ + struct i915_power_domains *power_domains = &i915->power_domains; + int i; + + mutex_lock(&power_domains->lock); + + seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count"); + for (i = 0; i < power_domains->power_well_count; i++) { + struct i915_power_well *power_well; + enum intel_display_power_domain power_domain; + + power_well = &power_domains->power_wells[i]; + seq_printf(m, "%-25s %d\n", power_well->desc->name, + power_well->count); + + for_each_power_domain(power_domain, power_well->desc->domains) + seq_printf(m, " %-23s %d\n", + intel_display_power_domain_str(power_domain), + power_domains->domain_use_count[power_domain]); + } + + mutex_unlock(&power_domains->lock); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index d54b7574ed373..b28cc1f94576b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -391,6 +391,8 @@ intel_display_power_put_all_in_set(struct drm_i915_private *i915, intel_display_power_put_mask_in_set(i915, power_domain_set, power_domain_set->mask); } +void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m); + /* * FIXME: We should probably switch this to a 0-based scheme to be consistent * with how we now name/number DBUF_CTL instances. From de511df7254ab22ee777ef6049547c69c1b2c78b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 16 Nov 2021 19:14:33 +0200 Subject: [PATCH 165/176] drm/i915: move structs from intel_display_power.h to .c Anything internal to the implementation should be hidden away. Move the intel_display_power structs to the .c file. Cc: Imre Deak Signed-off-by: Jani Nikula Reviewed-by: Daniel Vetter Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211116171434.20516-4-jani.nikula@intel.com --- .../drm/i915/display/intel_display_power.c | 92 ++++++++++++++++++ .../drm/i915/display/intel_display_power.h | 95 +------------------ 2 files changed, 93 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 5ebc758498c80..229b4c127c6ce 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -24,6 +24,98 @@ #include "intel_vga.h" #include "vlv_sideband.h" +struct i915_power_well_ops { + /* + * Synchronize the well's hw state to match the current sw state, for + * example enable/disable it based on the current refcount. Called + * during driver init and resume time, possibly after first calling + * the enable/disable handlers. + */ + void (*sync_hw)(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well); + /* + * Enable the well and resources that depend on it (for example + * interrupts located on the well). Called after the 0->1 refcount + * transition. + */ + void (*enable)(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well); + /* + * Disable the well and resources that depend on it. Called after + * the 1->0 refcount transition. + */ + void (*disable)(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well); + /* Returns the hw enabled state. */ + bool (*is_enabled)(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well); +}; + +struct i915_power_well_regs { + i915_reg_t bios; + i915_reg_t driver; + i915_reg_t kvmr; + i915_reg_t debug; +}; + +/* Power well structure for haswell */ +struct i915_power_well_desc { + const char *name; + bool always_on; + u64 domains; + /* unique identifier for this power well */ + enum i915_power_well_id id; + /* + * Arbitraty data associated with this power well. Platform and power + * well specific. + */ + union { + struct { + /* + * request/status flag index in the PUNIT power well + * control/status registers. + */ + u8 idx; + } vlv; + struct { + enum dpio_phy phy; + } bxt; + struct { + const struct i915_power_well_regs *regs; + /* + * request/status flag index in the power well + * constrol/status registers. + */ + u8 idx; + /* Mask of pipes whose IRQ logic is backed by the pw */ + u8 irq_pipe_mask; + /* + * Instead of waiting for the status bit to ack enables, + * just wait a specific amount of time and then consider + * the well enabled. + */ + u16 fixed_enable_delay; + /* The pw is backing the VGA functionality */ + bool has_vga:1; + bool has_fuses:1; + /* + * The pw is for an ICL+ TypeC PHY port in + * Thunderbolt mode. + */ + bool is_tc_tbt:1; + } hsw; + }; + const struct i915_power_well_ops *ops; +}; + +struct i915_power_well { + const struct i915_power_well_desc *desc; + /* power well enable/disable usage count */ + int count; + /* cached hw enabled state */ + bool hw_enabled; +}; + bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, enum i915_power_well_id power_well_id); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index b28cc1f94576b..2777af09c7116 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -11,6 +11,7 @@ #include "i915_reg.h" struct drm_i915_private; +struct i915_power_well; struct intel_encoder; enum intel_display_power_domain { @@ -155,100 +156,6 @@ enum i915_power_well_id { ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \ (tran) + POWER_DOMAIN_TRANSCODER_A) -struct i915_power_well; - -struct i915_power_well_ops { - /* - * Synchronize the well's hw state to match the current sw state, for - * example enable/disable it based on the current refcount. Called - * during driver init and resume time, possibly after first calling - * the enable/disable handlers. - */ - void (*sync_hw)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); - /* - * Enable the well and resources that depend on it (for example - * interrupts located on the well). Called after the 0->1 refcount - * transition. - */ - void (*enable)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); - /* - * Disable the well and resources that depend on it. Called after - * the 1->0 refcount transition. - */ - void (*disable)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); - /* Returns the hw enabled state. */ - bool (*is_enabled)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); -}; - -struct i915_power_well_regs { - i915_reg_t bios; - i915_reg_t driver; - i915_reg_t kvmr; - i915_reg_t debug; -}; - -/* Power well structure for haswell */ -struct i915_power_well_desc { - const char *name; - bool always_on; - u64 domains; - /* unique identifier for this power well */ - enum i915_power_well_id id; - /* - * Arbitraty data associated with this power well. Platform and power - * well specific. - */ - union { - struct { - /* - * request/status flag index in the PUNIT power well - * control/status registers. - */ - u8 idx; - } vlv; - struct { - enum dpio_phy phy; - } bxt; - struct { - const struct i915_power_well_regs *regs; - /* - * request/status flag index in the power well - * constrol/status registers. - */ - u8 idx; - /* Mask of pipes whose IRQ logic is backed by the pw */ - u8 irq_pipe_mask; - /* - * Instead of waiting for the status bit to ack enables, - * just wait a specific amount of time and then consider - * the well enabled. - */ - u16 fixed_enable_delay; - /* The pw is backing the VGA functionality */ - bool has_vga:1; - bool has_fuses:1; - /* - * The pw is for an ICL+ TypeC PHY port in - * Thunderbolt mode. - */ - bool is_tc_tbt:1; - } hsw; - }; - const struct i915_power_well_ops *ops; -}; - -struct i915_power_well { - const struct i915_power_well_desc *desc; - /* power well enable/disable usage count */ - int count; - /* cached hw enabled state */ - bool hw_enabled; -}; - struct i915_power_domains { /* * Power wells needed for initialization at driver init and suspend From 5ed597daa4202e92472953fbfd82105f10aa35e1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 16 Nov 2021 19:14:34 +0200 Subject: [PATCH 166/176] drm/i915: drop intel_display.h include from intel_display_power.h Use forward declarations instead. Cc: Imre Deak Signed-off-by: Jani Nikula Reviewed-by: Daniel Vetter Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211116171434.20516-5-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 2777af09c7116..686d18eaa24c8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -6,10 +6,11 @@ #ifndef __INTEL_DISPLAY_POWER_H__ #define __INTEL_DISPLAY_POWER_H__ -#include "intel_display.h" #include "intel_runtime_pm.h" #include "i915_reg.h" +enum dpio_channel; +enum dpio_phy; struct drm_i915_private; struct i915_power_well; struct intel_encoder; From 2052287a74c95234eabe7a858f157a88d6880029 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 16 Nov 2021 15:58:13 +0200 Subject: [PATCH 167/176] drm/i915/pxp: fix includes for headers in include/drm Use <> not "" for including headers from include/drm. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20211116135813.19806-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/pxp/intel_pxp_session.c | 3 ++- drivers/gpu/drm/i915/pxp/intel_pxp_tee.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c index d02732f04757e..598840b73dfa0 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c @@ -3,7 +3,8 @@ * Copyright(c) 2020, Intel Corporation. All rights reserved. */ -#include "drm/i915_drm.h" +#include + #include "i915_drv.h" #include "intel_pxp.h" diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index 49508f31dcb73..5d169624ad60b 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -4,8 +4,10 @@ */ #include -#include "drm/i915_pxp_tee_interface.h" -#include "drm/i915_component.h" + +#include +#include + #include "i915_drv.h" #include "intel_pxp.h" #include "intel_pxp_session.h" From eeb04fa64af18cbe03d1067a435c6423da47b6fc Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Thu, 18 Nov 2021 11:39:07 +0200 Subject: [PATCH 168/176] drm/i915/dg2: Implement WM0 cursor WA for DG2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug in the register unit which results in WM1 register used when only WM0 is enabled on cursor. Software workaround is when only WM0 enabled on cursor, copy contents of CUR_WM_0[30:0] (exclude the enable bit) into CUR_WM_1[30:0]. v2: - s/dev_priv/i915/ (Ville Syrjälä) - Removed unneeded brackets (Ville Syrjälä) HSDES: 14012656716 Reviewed-by: Ville Syrjälä Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20211118093907.18510-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 41d52789660d2..e9f2e307b98e4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5095,6 +5095,18 @@ skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm, } } +static bool icl_need_wm1_wa(struct drm_i915_private *i915, + enum plane_id plane_id) +{ + /* + * Wa_1408961008:icl, ehl + * Wa_14012656716:tgl, adl + * Underruns with WM1+ disabled + */ + return DISPLAY_VER(i915) == 11 || + (IS_DISPLAY_VER(i915, 12, 13) && plane_id == PLANE_CURSOR); +} + static int skl_allocate_plane_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc) @@ -5265,11 +5277,7 @@ skl_allocate_plane_ddb(struct intel_atomic_state *state, skl_check_nv12_wm_level(&wm->wm[level], &wm->uv_wm[level], total[plane_id], uv_total[plane_id]); - /* - * Wa_1408961008:icl, ehl - * Underruns with WM1+ disabled - */ - if (DISPLAY_VER(dev_priv) == 11 && + if (icl_need_wm1_wa(dev_priv, plane_id) && level == 1 && wm->wm[0].enable) { wm->wm[level].blocks = wm->wm[0].blocks; wm->wm[level].lines = wm->wm[0].lines; From 527bab0473f28236e4587c7870586275c1ef5516 Mon Sep 17 00:00:00 2001 From: Tilak Tangudu Date: Tue, 16 Nov 2021 21:22:38 +0530 Subject: [PATCH 169/176] drm/i915/rpm: Enable runtime pm autosuspend by default Let's enable runtime pm autosuspend by default everywhere. So, we can allow D3hot and bigger power savings on idle scenarios. But at this time let's not touch the autosuspend_delay time, what caused some regression on our previous attempt. Also, the latest identified issue on GuC PM has been fixed by commit 1a52faed3131 ("drm/i915/guc: Take GT PM ref when deregistering context") v1: Enable runtime pm autosuspend by default for Gen12 and later versions. v2: Enable runtime pm autosuspend by default for all platforms(Syrjala Ville) v3: Change commit message(Nikula Jani) Signed-off-by: Tilak Tangudu Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20211116155238.3226516-1-tilak.tangudu@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index eaf7688f517d0..f26ed1427fdc5 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -600,6 +600,9 @@ void intel_runtime_pm_enable(struct intel_runtime_pm *rpm) pm_runtime_use_autosuspend(kdev); } + /* Enable by default */ + pm_runtime_allow(kdev); + /* * The core calls the driver load handler with an RPM reference held. * We drop that here and will reacquire it during unloading in From 3c542cfa8266e3364938d055b3d548b7bed7f08e Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Mon, 22 Nov 2021 23:14:20 +0200 Subject: [PATCH 170/176] drm/i915/dg2: Tile 4 plane format support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TileF(Tile4 in bspec) format is 4K tile organized into 64B subtiles with same basic shape as for legacy TileY which will be supported by Display13. v2: - Fixed wrong case condition(Jani Nikula) - Increased I915_FORMAT_MOD_F_TILED up to 12(Imre Deak) v3: - s/I915_TILING_F/TILING_4/g - s/I915_FORMAT_MOD_F_TILED/I915_FORMAT_MOD_4_TILED/g - Removed unneeded fencing code v4: - Rebased, fixed merge conflict with new table-oriented format modifier checking(Stan) - Replaced the rest of "Tile F" mentions to "Tile 4"(Stan) v5: - Still had to remove some Tile F mentionings - Moved has_4tile from adlp to DG2(Ramalingam C) - Check specifically for DG2, but not the Display13(Imre) v6: - Moved Tile4 associating struct for modifier/display to the beginning(Imre Deak) - Removed unneeded case I915_FORMAT_MOD_4_TILED modifier checks(Imre Deak) - Fixed I915_FORMAT_MOD_4_TILED to be 9 instead of 12 (Imre Deak) v7: - Fixed display_ver to { 13, 13 }(Imre Deak) - Removed redundant newline(Imre Deak) Reviewed-by: Imre Deak Cc: Imre Deak Cc: Matt Roper Cc: Maarten Lankhorst Signed-off-by: Stanislav Lisovskiy Signed-off-by: Matt Roper Signed-off-by: Juha-Pekka Heikkilä Link: https://patchwork.freedesktop.org/patch/msgid/20211122211420.31584-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_fb.c | 9 +++++++++ drivers/gpu/drm/i915/display/intel_fbc.c | 1 + .../drm/i915/display/intel_plane_initial.c | 1 + .../drm/i915/display/skl_universal_plane.c | 20 +++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_pci.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_device_info.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 1 + include/uapi/drm/drm_fourcc.h | 8 ++++++++ 11 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f3c9208a30b16..7429965d36828 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7766,6 +7766,7 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: + case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index c4a743d0913fc..b7f1ef62072ce 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -139,6 +139,9 @@ struct intel_modifier_desc { static const struct intel_modifier_desc intel_modifiers[] = { { + .modifier = I915_FORMAT_MOD_4_TILED, + .display_ver = { 13, 13 }, + }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, .display_ver = { 12, 13 }, .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC, @@ -544,6 +547,12 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) return 128; else return 512; + case I915_FORMAT_MOD_4_TILED: + /* + * Each 4K tile consists of 64B(8*8) subtiles, with + * same shape as Y Tile(i.e 4*16B OWords) + */ + return 128; case I915_FORMAT_MOD_Y_TILED_CCS: if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return 128; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index d0c34bc3af6c2..0ceabe40d8c9d 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -898,6 +898,7 @@ static bool tiling_is_valid(struct drm_i915_private *i915, case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: return DISPLAY_VER(i915) >= 9; + case I915_FORMAT_MOD_4_TILED: case I915_FORMAT_MOD_X_TILED: return true; default: diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index dcd698a02da21..d80855ee9b961 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -125,6 +125,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg(&dev_priv->drm, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 28890876bdebf..e5cda5bcbde41 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -751,6 +751,8 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier) 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_Y_TILED_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; @@ -1971,9 +1973,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_Y216: case DRM_FORMAT_XVYU12_16161616: case DRM_FORMAT_XVYU16161616: - if (modifier == DRM_FORMAT_MOD_LINEAR || - modifier == I915_FORMAT_MOD_X_TILED || - modifier == I915_FORMAT_MOD_Y_TILED) + if (!intel_fb_is_ccs_modifier(modifier)) return true; fallthrough; default: @@ -2299,11 +2299,15 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, else fb->modifier = I915_FORMAT_MOD_Y_TILED; break; - case PLANE_CTL_TILED_YF: - if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) - fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; - else - fb->modifier = I915_FORMAT_MOD_Yf_TILED; + case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */ + if (HAS_4TILE(dev_priv)) { + fb->modifier = I915_FORMAT_MOD_4_TILED; + } else { + if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) + fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; + else + fb->modifier = I915_FORMAT_MOD_Yf_TILED; + } break; default: MISSING_CASE(tiling); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4f58e14565057..250ac161f55c5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1624,6 +1624,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define CMDPARSER_USES_GGTT(dev_priv) (GRAPHICS_VER(dev_priv) == 7) #define HAS_LLC(dev_priv) (INTEL_INFO(dev_priv)->has_llc) +#define HAS_4TILE(dev_priv) (INTEL_INFO(dev_priv)->has_4tile) #define HAS_SNOOP(dev_priv) (INTEL_INFO(dev_priv)->has_snoop) #define HAS_EDRAM(dev_priv) ((dev_priv)->edram_size_mb) #define HAS_SECURE_BATCHES(dev_priv) (GRAPHICS_VER(dev_priv) < 6) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 52749b8f4f6b8..69b8029da6b61 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1044,6 +1044,7 @@ static const struct intel_device_info dg2_info = { DGFX_FEATURES, .graphics_rel = 55, .media_rel = 55, + .has_4tile = 1, PLATFORM(INTEL_DG2), .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 47fcd104868fe..38b4e3b5d8b2c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7210,6 +7210,7 @@ enum { #define PLANE_CTL_TILED_X (1 << 10) #define PLANE_CTL_TILED_Y (4 << 10) #define PLANE_CTL_TILED_YF (5 << 10) +#define PLANE_CTL_TILED_4 (5 << 10) #define PLANE_CTL_ASYNC_FLIP (1 << 9) #define PLANE_CTL_FLIP_HORIZONTAL (1 << 8) #define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE (1 << 4) /* TGL+ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 8e6f48d1eb7bc..6c543a1522508 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -125,6 +125,7 @@ enum intel_ppgtt_type { func(has_64bit_reloc); \ func(gpu_reset_clobbers_display); \ func(has_reset_engine); \ + func(has_4tile); \ func(has_global_mocs); \ func(has_gt_uc); \ func(has_l3_dpf); \ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e9f2e307b98e4..2ad577dfe5040 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5386,6 +5386,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, } wp->y_tiled = modifier == I915_FORMAT_MOD_Y_TILED || + modifier == I915_FORMAT_MOD_4_TILED || modifier == I915_FORMAT_MOD_Yf_TILED || modifier == I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS; diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 7f652c96845ba..41184a94935d5 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -564,6 +564,14 @@ extern "C" { * pitch is required to be a multiple of 4 tile widths. */ #define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8) +/* + * Intel F-tiling(aka Tile4) layout + * + * This is a tiled layout using 4Kb tiles in row-major layout. + * Within the tile pixels are laid out in 64 byte units / sub-tiles in OWORD + * (16 bytes) chunks column-major.. + */ +#define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9) /* * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks From aebdd7428c65a8e2e96c1fd2fd89b4ab90bad913 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 22 Nov 2021 13:15:01 +0200 Subject: [PATCH 171/176] drm/i915/dsi: split out intel_dsi_vbt.h Follow the convention of corresponding .h for .c. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20211122111504.223248-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 1 + drivers/gpu/drm/i915/display/intel_dsi.h | 9 -------- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 1 + drivers/gpu/drm/i915/display/intel_dsi_vbt.h | 22 ++++++++++++++++++++ drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + 5 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dsi_vbt.h diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index edc38fbd2545d..2f15b322d78f9 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -36,6 +36,7 @@ #include "intel_ddi.h" #include "intel_de.h" #include "intel_dsi.h" +#include "intel_dsi_vbt.h" #include "intel_panel.h" #include "intel_vdsc.h" #include "skl_scaler.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index fbc40ffdc02ec..e3571ca7db5c2 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -210,13 +210,4 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port); void assert_dsi_pll_enabled(struct drm_i915_private *i915); void assert_dsi_pll_disabled(struct drm_i915_private *i915); -/* intel_dsi_vbt.c */ -bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id); -void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on); -void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi); -void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi, - enum mipi_seq seq_id); -void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec); -void intel_dsi_log_params(struct intel_dsi *intel_dsi); - #endif /* _INTEL_DSI_H */ diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index f241bedb8597f..c29a136192244 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -41,6 +41,7 @@ #include "i915_drv.h" #include "intel_display_types.h" #include "intel_dsi.h" +#include "intel_dsi_vbt.h" #include "vlv_sideband.h" #define MIPI_TRANSFER_MODE_SHIFT 0 diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.h b/drivers/gpu/drm/i915/display/intel_dsi_vbt.h new file mode 100644 index 0000000000000..dc642c1fe7efd --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __INTEL_DSI_VBT_H__ +#define __INTEL_DSI_VBT_H__ + +#include + +enum mipi_seq; +struct intel_dsi; + +bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id); +void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on); +void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi); +void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi, + enum mipi_seq seq_id); +void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec); +void intel_dsi_log_params(struct intel_dsi *intel_dsi); + +#endif /* __INTEL_DSI_VBT_H__ */ diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 59ebfbd46e6fa..be070a1afcd07 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -38,6 +38,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsi.h" +#include "intel_dsi_vbt.h" #include "intel_fifo_underrun.h" #include "intel_panel.h" #include "skl_scaler.h" From 01e526285a6a591900e7ed7266c1723fed366754 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 22 Nov 2021 13:15:02 +0200 Subject: [PATCH 172/176] drm/i915/dsi: split out vlv_dsi_pll.h Follow the convention of corresponding .h for .c. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20211122111504.223248-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_dsi.h | 23 ------------ drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 1 + drivers/gpu/drm/i915/display/vlv_dsi_pll.h | 38 ++++++++++++++++++++ 6 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/vlv_dsi_pll.h diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index c870a0e50cb11..840f13b754929 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -26,7 +26,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dpll.h" -#include "intel_dsi.h" +#include "vlv_dsi_pll.h" #define CTM_COEFF_SIGN (1ULL << 63) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7429965d36828..7b330420aabec 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -109,6 +109,7 @@ #include "i9xx_plane.h" #include "skl_scaler.h" #include "skl_universal_plane.h" +#include "vlv_dsi_pll.h" #include "vlv_sideband.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index e3571ca7db5c2..39a0eae45a0d2 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -187,27 +187,4 @@ struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, enum port port); void vlv_dsi_init(struct drm_i915_private *dev_priv); -/* vlv_dsi_pll.c */ -int vlv_dsi_pll_compute(struct intel_encoder *encoder, - struct intel_crtc_state *config); -void vlv_dsi_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *config); -void vlv_dsi_pll_disable(struct intel_encoder *encoder); -u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, - struct intel_crtc_state *config); -void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port); - -bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv); -int bxt_dsi_pll_compute(struct intel_encoder *encoder, - struct intel_crtc_state *config); -void bxt_dsi_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *config); -void bxt_dsi_pll_disable(struct intel_encoder *encoder); -u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, - struct intel_crtc_state *config); -void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port); - -void assert_dsi_pll_enabled(struct drm_i915_private *i915); -void assert_dsi_pll_disabled(struct drm_i915_private *i915); - #endif /* _INTEL_DSI_H */ diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index be070a1afcd07..ed2a0d764f37d 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -42,6 +42,7 @@ #include "intel_fifo_underrun.h" #include "intel_panel.h" #include "skl_scaler.h" +#include "vlv_dsi_pll.h" #include "vlv_sideband.h" /* return pixels in terms of txbyteclkhs */ diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 5413b52ab6ba0..1b81797dd02ec 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -31,6 +31,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsi.h" +#include "vlv_dsi_pll.h" #include "vlv_sideband.h" static const u16 lfsr_converts[] = { diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.h b/drivers/gpu/drm/i915/display/vlv_dsi_pll.h new file mode 100644 index 0000000000000..ab9291ad1e794 --- /dev/null +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __VLV_DSI_PLL_H__ +#define __VLV_DSI_PLL_H__ + +#include + +enum port; +struct drm_i915_private; +struct intel_crtc_state; +struct intel_encoder; + +int vlv_dsi_pll_compute(struct intel_encoder *encoder, + struct intel_crtc_state *config); +void vlv_dsi_pll_enable(struct intel_encoder *encoder, + const struct intel_crtc_state *config); +void vlv_dsi_pll_disable(struct intel_encoder *encoder); +u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, + struct intel_crtc_state *config); +void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port); + +bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv); +int bxt_dsi_pll_compute(struct intel_encoder *encoder, + struct intel_crtc_state *config); +void bxt_dsi_pll_enable(struct intel_encoder *encoder, + const struct intel_crtc_state *config); +void bxt_dsi_pll_disable(struct intel_encoder *encoder); +u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, + struct intel_crtc_state *config); +void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port); + +void assert_dsi_pll_enabled(struct drm_i915_private *i915); +void assert_dsi_pll_disabled(struct drm_i915_private *i915); + +#endif /* __VLV_DSI_PLL_H__ */ From 7570d06db73f9e5a97cb55bcdfcc3b15f6f46b9b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 22 Nov 2021 13:15:03 +0200 Subject: [PATCH 173/176] drm/i915/dsi: split out vlv_dsi.h Follow the convention of corresponding .h for .c. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20211122111504.223248-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_dsi.h | 5 ----- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 1 + drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + drivers/gpu/drm/i915/display/vlv_dsi.h | 19 +++++++++++++++++++ 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/vlv_dsi.h diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7b330420aabec..30fff9f7bf82b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -111,6 +111,7 @@ #include "skl_universal_plane.h" #include "vlv_dsi_pll.h" #include "vlv_sideband.h" +#include "vlv_dsi.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index 39a0eae45a0d2..dd913ad352327 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -175,16 +175,11 @@ int intel_dsi_bitrate(const struct intel_dsi *intel_dsi); int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi); enum drm_panel_orientation intel_dsi_get_panel_orientation(struct intel_connector *connector); - -/* vlv_dsi.c */ -void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port); -enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt); int intel_dsi_get_modes(struct drm_connector *connector); enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode); struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, const struct mipi_dsi_host_ops *funcs, enum port port); -void vlv_dsi_init(struct drm_i915_private *dev_priv); #endif /* _INTEL_DSI_H */ diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index c29a136192244..0da91849efde4 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -42,6 +42,7 @@ #include "intel_display_types.h" #include "intel_dsi.h" #include "intel_dsi_vbt.h" +#include "vlv_dsi.h" #include "vlv_sideband.h" #define MIPI_TRANSFER_MODE_SHIFT 0 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index ed2a0d764f37d..20141f33ed644 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -42,6 +42,7 @@ #include "intel_fifo_underrun.h" #include "intel_panel.h" #include "skl_scaler.h" +#include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_sideband.h" diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.h b/drivers/gpu/drm/i915/display/vlv_dsi.h new file mode 100644 index 0000000000000..0c2b279df9d48 --- /dev/null +++ b/drivers/gpu/drm/i915/display/vlv_dsi.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __VLV_DSI_H__ +#define __VLV_DSI_H__ + +#include + +enum port; +struct drm_i915_private; +struct intel_dsi; + +void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port); +enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt); +void vlv_dsi_init(struct drm_i915_private *dev_priv); + +#endif /* __VLV_DSI_H__ */ From 617ed6c2f0365a62f21936449ca1701937027339 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 22 Nov 2021 13:15:04 +0200 Subject: [PATCH 174/176] drm/i915/dsi: split out icl_dsi.h Follow the convention of corresponding .h for .c. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20211122111504.223248-4-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 1 + drivers/gpu/drm/i915/display/icl_dsi.h | 15 +++++++++++++++ drivers/gpu/drm/i915/display/intel_crtc.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_dsi.h | 5 ----- 5 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/icl_dsi.h diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 2f15b322d78f9..5781e9fac8b45 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -28,6 +28,7 @@ #include #include +#include "icl_dsi.h" #include "intel_atomic.h" #include "intel_backlight.h" #include "intel_combo_phy.h" diff --git a/drivers/gpu/drm/i915/display/icl_dsi.h b/drivers/gpu/drm/i915/display/icl_dsi.h new file mode 100644 index 0000000000000..b4861b56b5b2a --- /dev/null +++ b/drivers/gpu/drm/i915/display/icl_dsi.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __ICL_DSI_H__ +#define __ICL_DSI_H__ + +struct drm_i915_private; +struct intel_crtc_state; + +void icl_dsi_init(struct drm_i915_private *i915); +void icl_dsi_frame_update(struct intel_crtc_state *crtc_state); + +#endif /* __ICL_DSI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index eb5444f90e77c..243d5cc29734c 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -14,7 +14,7 @@ #include "i915_trace.h" #include "i915_vgpu.h" - +#include "icl_dsi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_color.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 30fff9f7bf82b..760e1bb928760 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -73,6 +73,7 @@ #include "g4x_dp.h" #include "g4x_hdmi.h" #include "i915_drv.h" +#include "icl_dsi.h" #include "intel_acpi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index dd913ad352327..a3a906cb097eb 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -166,11 +166,6 @@ static inline u16 intel_dsi_encoder_ports(struct intel_encoder *encoder) return enc_to_intel_dsi(encoder)->ports; } -/* icl_dsi.c */ -void icl_dsi_init(struct drm_i915_private *dev_priv); -void icl_dsi_frame_update(struct intel_crtc_state *crtc_state); - -/* intel_dsi.c */ int intel_dsi_bitrate(const struct intel_dsi *intel_dsi); int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi); enum drm_panel_orientation From 86c82c8aeebf6db5df8ab73cec8333853c405070 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Wed, 24 Nov 2021 11:23:55 +0200 Subject: [PATCH 175/176] Revert "drm/i915/dg2: Tile 4 plane format support" Tile4 patch still needs an ack from userspace, IGT tests and some essential fixes, related to new .plane_caps attribute being added. This reverts commit 3c542cfa8266e3364938d055b3d548b7bed7f08e. Signed-off-by: Stanislav Lisovskiy Acked-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20211124092355.16668-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/display/intel_fb.c | 9 --------- drivers/gpu/drm/i915/display/intel_fbc.c | 1 - .../drm/i915/display/intel_plane_initial.c | 1 - .../drm/i915/display/skl_universal_plane.c | 20 ++++++++----------- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_pci.c | 1 - drivers/gpu/drm/i915/i915_reg.h | 1 - drivers/gpu/drm/i915/intel_device_info.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 1 - include/uapi/drm/drm_fourcc.h | 8 -------- 11 files changed, 8 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 760e1bb928760..b2d51cd79d6cc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7769,7 +7769,6 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: - case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index b7f1ef62072ce..c4a743d0913fc 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -139,9 +139,6 @@ struct intel_modifier_desc { static const struct intel_modifier_desc intel_modifiers[] = { { - .modifier = I915_FORMAT_MOD_4_TILED, - .display_ver = { 13, 13 }, - }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, .display_ver = { 12, 13 }, .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC, @@ -547,12 +544,6 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) return 128; else return 512; - case I915_FORMAT_MOD_4_TILED: - /* - * Each 4K tile consists of 64B(8*8) subtiles, with - * same shape as Y Tile(i.e 4*16B OWords) - */ - return 128; case I915_FORMAT_MOD_Y_TILED_CCS: if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return 128; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 0ceabe40d8c9d..d0c34bc3af6c2 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -898,7 +898,6 @@ static bool tiling_is_valid(struct drm_i915_private *i915, case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: return DISPLAY_VER(i915) >= 9; - case I915_FORMAT_MOD_4_TILED: case I915_FORMAT_MOD_X_TILED: return true; default: diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index d80855ee9b961..dcd698a02da21 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -125,7 +125,6 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg(&dev_priv->drm, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index e5cda5bcbde41..28890876bdebf 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -751,8 +751,6 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier) 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_Y_TILED_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; @@ -1973,7 +1971,9 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_Y216: case DRM_FORMAT_XVYU12_16161616: case DRM_FORMAT_XVYU16161616: - if (!intel_fb_is_ccs_modifier(modifier)) + if (modifier == DRM_FORMAT_MOD_LINEAR || + modifier == I915_FORMAT_MOD_X_TILED || + modifier == I915_FORMAT_MOD_Y_TILED) return true; fallthrough; default: @@ -2299,15 +2299,11 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, else fb->modifier = I915_FORMAT_MOD_Y_TILED; break; - case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */ - if (HAS_4TILE(dev_priv)) { - fb->modifier = I915_FORMAT_MOD_4_TILED; - } else { - if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) - fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; - else - fb->modifier = I915_FORMAT_MOD_Yf_TILED; - } + case PLANE_CTL_TILED_YF: + if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) + fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; + else + fb->modifier = I915_FORMAT_MOD_Yf_TILED; break; default: MISSING_CASE(tiling); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 250ac161f55c5..4f58e14565057 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1624,7 +1624,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define CMDPARSER_USES_GGTT(dev_priv) (GRAPHICS_VER(dev_priv) == 7) #define HAS_LLC(dev_priv) (INTEL_INFO(dev_priv)->has_llc) -#define HAS_4TILE(dev_priv) (INTEL_INFO(dev_priv)->has_4tile) #define HAS_SNOOP(dev_priv) (INTEL_INFO(dev_priv)->has_snoop) #define HAS_EDRAM(dev_priv) ((dev_priv)->edram_size_mb) #define HAS_SECURE_BATCHES(dev_priv) (GRAPHICS_VER(dev_priv) < 6) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 69b8029da6b61..52749b8f4f6b8 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1044,7 +1044,6 @@ static const struct intel_device_info dg2_info = { DGFX_FEATURES, .graphics_rel = 55, .media_rel = 55, - .has_4tile = 1, PLATFORM(INTEL_DG2), .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 38b4e3b5d8b2c..47fcd104868fe 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7210,7 +7210,6 @@ enum { #define PLANE_CTL_TILED_X (1 << 10) #define PLANE_CTL_TILED_Y (4 << 10) #define PLANE_CTL_TILED_YF (5 << 10) -#define PLANE_CTL_TILED_4 (5 << 10) #define PLANE_CTL_ASYNC_FLIP (1 << 9) #define PLANE_CTL_FLIP_HORIZONTAL (1 << 8) #define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE (1 << 4) /* TGL+ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 6c543a1522508..8e6f48d1eb7bc 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -125,7 +125,6 @@ enum intel_ppgtt_type { func(has_64bit_reloc); \ func(gpu_reset_clobbers_display); \ func(has_reset_engine); \ - func(has_4tile); \ func(has_global_mocs); \ func(has_gt_uc); \ func(has_l3_dpf); \ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2ad577dfe5040..e9f2e307b98e4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5386,7 +5386,6 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, } wp->y_tiled = modifier == I915_FORMAT_MOD_Y_TILED || - modifier == I915_FORMAT_MOD_4_TILED || modifier == I915_FORMAT_MOD_Yf_TILED || modifier == I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS; diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 41184a94935d5..7f652c96845ba 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -564,14 +564,6 @@ extern "C" { * pitch is required to be a multiple of 4 tile widths. */ #define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8) -/* - * Intel F-tiling(aka Tile4) layout - * - * This is a tiled layout using 4Kb tiles in row-major layout. - * Within the tile pixels are laid out in 64 byte units / sub-tiles in OWORD - * (16 bytes) chunks column-major.. - */ -#define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9) /* * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks From 74ba89c08e309bfeb2b2f401bf588ab54a1542fe Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 25 Nov 2021 19:16:03 +0200 Subject: [PATCH 176/176] drm/i915: Fix DPT suspend/resume on !HAS_DISPLAY platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The drm.mode_config state is not initialized in case of !HAS_DISPLAY so taking the fb_lock and iterating the fb list won't work on those platforms. Skip the suspend/resume with an explicit check for this. Fixes: 9755f055f512 ("drm/i915: Restore memory mapping for DPT FBs across system suspend/resume") Cc: Chris Wilson Cc: Ville Syrjala Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211125171603.1775179-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 56755788547d2..963ca7155b064 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -183,6 +183,9 @@ void intel_dpt_resume(struct drm_i915_private *i915) { struct drm_framebuffer *drm_fb; + if (!HAS_DISPLAY(i915)) + return; + mutex_lock(&i915->drm.mode_config.fb_lock); drm_for_each_fb(drm_fb, &i915->drm) { struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb); @@ -207,6 +210,9 @@ void intel_dpt_suspend(struct drm_i915_private *i915) { struct drm_framebuffer *drm_fb; + if (!HAS_DISPLAY(i915)) + return; + mutex_lock(&i915->drm.mode_config.fb_lock); drm_for_each_fb(drm_fb, &i915->drm) {