diff options
Diffstat (limited to 'drivers/gpu')
27 files changed, 759 insertions, 690 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9d588d936e3d..1a771ee5b1d0 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -212,6 +212,7 @@ i915-y += \ display/intel_cursor.o \ display/intel_display.o \ display/intel_display_power.o \ + display/intel_display_power_well.o \ display/intel_dmc.o \ display/intel_dpio_phy.o \ display/intel_dpll.o \ diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index a87b65cd41fd..af190bacdd97 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -418,9 +418,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane, { 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); @@ -441,8 +438,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane, intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1)); } - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void i9xx_plane_update_arm(struct intel_plane *plane, @@ -465,8 +460,6 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, else dspaddr_offset = linear_offset; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - 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; @@ -496,13 +489,15 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, * the control register just before the surface register. */ intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + + /* lock to protect against rmw in fbc nuke */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (DISPLAY_VER(dev_priv) >= 4) intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); else intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -540,14 +535,14 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane, */ dspcntr = i9xx_plane_ctl_crtc(crtc_state); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + + /* lock to protect against rmw in fbc nuke */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (DISPLAY_VER(dev_priv) >= 4) intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); else intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -566,8 +561,10 @@ g4x_primary_async_flip(struct intel_plane *plane, if (async_flip) dspcntr |= DISP_ASYNC_FLIP; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + + /* lock to protect against rmw in fbc nuke */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); @@ -582,12 +579,9 @@ vlv_primary_async_flip(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); u32 dspaddr_offset = plane_state->view.color_plane[0].offset; 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, DSPADDR_VLV(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 2ade8fdd9bdd..57ef9403f4e9 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -152,6 +152,9 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, /* Use the unclipped src/dst rectangles, which we program to hw */ plane_state->uapi.src = src; plane_state->uapi.dst = dst; + if (intel_crtc_is_bigjoiner_slave(crtc_state)) + drm_rect_translate(&plane_state->uapi.dst, + -crtc_state->pipe_src_w, 0); ret = intel_cursor_check_surface(plane_state); if (ret) @@ -255,7 +258,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); u32 cntl = 0, base = 0, pos = 0, size = 0; - unsigned long irqflags; if (plane_state && plane_state->uapi.visible) { unsigned int width = drm_rect_width(&plane_state->uapi.dst); @@ -270,8 +272,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane, pos = intel_cursor_position(plane_state); } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* On these chipsets we can only modify the base/size/stride * whilst the cursor is disabled. */ @@ -290,8 +290,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane, } else { intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos); } - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void i845_cursor_disable_arm(struct intel_plane *plane, @@ -492,7 +490,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0; - unsigned long irqflags; if (plane_state && plane_state->uapi.visible) { int width = drm_rect_width(&plane_state->uapi.dst); @@ -508,8 +505,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, pos = intel_cursor_position(plane_state); } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* * On some platforms writing CURCNTR first will also * cause CURPOS to be armed by the CURBASE write. @@ -555,8 +550,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, CURPOS(pipe), pos); intel_de_write_fw(dev_priv, CURBASE(pipe), base); } - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void i9xx_cursor_disable_arm(struct intel_plane *plane, @@ -715,6 +708,14 @@ intel_legacy_cursor_update(struct drm_plane *_plane, */ crtc_state->active_planes = new_crtc_state->active_planes; + /* + * Technically we should do a vblank evasion here to make + * sure all the cursor registers update on the same frame. + * For now just make sure the register writes happen as + * quickly as possible to minimize the race window. + */ + local_irq_disable(); + 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); @@ -722,6 +723,8 @@ intel_legacy_cursor_update(struct drm_plane *_plane, intel_plane_disable_arm(plane, crtc_state); } + local_irq_enable(); + intel_plane_unpin_fb(old_plane_state); out_free: diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e4260806c2a4..1cd394b0585e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4308,6 +4308,14 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) return; } + if (intel_phy_is_snps(dev_priv, phy) && + dev_priv->snps_phy_failed_calibration & BIT(phy)) { + drm_dbg_kms(&dev_priv->drm, + "SNPS PHY %c failed to calibrate; output will not be used.\n", + phy_name(phy)); + return; + } + dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); if (!dig_port) return; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 80b19c304c43..b8d511360f9f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -346,7 +346,10 @@ static enum pipe bigjoiner_master_pipe(const struct intel_crtc_state *crtc_state u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state) { - return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state)); + if (crtc_state->bigjoiner_pipes) + return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state)); + else + return 0; } bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state) @@ -2725,58 +2728,78 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) ilk_pipe_pixel_rate(crtc_state); } +static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state, + struct drm_display_mode *mode) +{ + if (!crtc_state->bigjoiner) + return; + + mode->crtc_clock /= 2; + mode->crtc_hdisplay /= 2; + mode->crtc_hblank_start /= 2; + mode->crtc_hblank_end /= 2; + mode->crtc_hsync_start /= 2; + mode->crtc_hsync_end /= 2; + mode->crtc_htotal /= 2; +} + +static void intel_splitter_adjust_timings(const struct intel_crtc_state *crtc_state, + struct drm_display_mode *mode) +{ + int overlap = crtc_state->splitter.pixel_overlap; + int n = crtc_state->splitter.link_count; + + if (!crtc_state->splitter.enable) + return; + + /* + * eDP MSO uses segment timings from EDID for transcoder + * timings, but full mode for everything else. + * + * h_full = (h_segment - pixel_overlap) * link_count + */ + mode->crtc_hdisplay = (mode->crtc_hdisplay - overlap) * n; + mode->crtc_hblank_start = (mode->crtc_hblank_start - overlap) * n; + mode->crtc_hblank_end = (mode->crtc_hblank_end - overlap) * n; + mode->crtc_hsync_start = (mode->crtc_hsync_start - overlap) * n; + mode->crtc_hsync_end = (mode->crtc_hsync_end - overlap) * n; + mode->crtc_htotal = (mode->crtc_htotal - overlap) * n; + mode->crtc_clock *= n; +} + static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state) { struct drm_display_mode *mode = &crtc_state->hw.mode; struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + /* + * Start with the adjusted_mode crtc timings, which + * have been filled with the transcoder timings. + */ drm_mode_copy(pipe_mode, adjusted_mode); - if (crtc_state->bigjoiner) { - /* - * transcoder is programmed to the full mode, - * but pipe timings are half of the transcoder mode - */ - pipe_mode->crtc_hdisplay /= 2; - pipe_mode->crtc_hblank_start /= 2; - pipe_mode->crtc_hblank_end /= 2; - pipe_mode->crtc_hsync_start /= 2; - pipe_mode->crtc_hsync_end /= 2; - pipe_mode->crtc_htotal /= 2; - pipe_mode->crtc_clock /= 2; - } - - if (crtc_state->splitter.enable) { - int n = crtc_state->splitter.link_count; - int overlap = crtc_state->splitter.pixel_overlap; - - /* - * eDP MSO uses segment timings from EDID for transcoder - * timings, but full mode for everything else. - * - * h_full = (h_segment - pixel_overlap) * link_count - */ - pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; - pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; - pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n; - pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n; - pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n; - pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n; - pipe_mode->crtc_clock *= n; - - intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - intel_mode_from_crtc_timings(adjusted_mode, pipe_mode); - } else { - intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); - } + /* Expand MSO per-segment transcoder timings to full */ + intel_splitter_adjust_timings(crtc_state, pipe_mode); - intel_crtc_compute_pixel_rate(crtc_state); + /* + * We want the full numbers in adjusted_mode normal timings, + * adjusted_mode crtc timings are left with the raw transcoder + * timings. + */ + intel_mode_from_crtc_timings(adjusted_mode, pipe_mode); - drm_mode_copy(mode, adjusted_mode); + /* Populate the "user" mode with full numbers */ + drm_mode_copy(mode, pipe_mode); + intel_mode_from_crtc_timings(mode, mode); mode->hdisplay = crtc_state->pipe_src_w << crtc_state->bigjoiner; mode->vdisplay = crtc_state->pipe_src_h; + + /* Derive per-pipe timings in case bigjoiner is used */ + intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); + + intel_crtc_compute_pixel_rate(crtc_state); } static void intel_encoder_get_config(struct intel_encoder *encoder, @@ -2787,44 +2810,63 @@ static void intel_encoder_get_config(struct intel_encoder *encoder, intel_crtc_readout_derived_state(crtc_state); } -static int intel_crtc_compute_config(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_display_mode *pipe_mode = &pipe_config->hw.pipe_mode; - int clock_limit = dev_priv->max_dotclk_freq; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); - drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode); + if (crtc_state->bigjoiner) + crtc_state->pipe_src_w /= 2; + + /* + * Pipe horizontal size must be even in: + * - DVO ganged mode + * - LVDS dual channel mode + * - Double wide pipe + */ + if (crtc_state->pipe_src_w & 1) { + if (crtc_state->double_wide) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] Odd pipe source width not supported with double wide pipe\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } - /* Adjust pipe_mode for bigjoiner, with half the horizontal mode */ - if (pipe_config->bigjoiner) { - pipe_mode->crtc_clock /= 2; - pipe_mode->crtc_hdisplay /= 2; - pipe_mode->crtc_hblank_start /= 2; - pipe_mode->crtc_hblank_end /= 2; - pipe_mode->crtc_hsync_start /= 2; - pipe_mode->crtc_hsync_end /= 2; - pipe_mode->crtc_htotal /= 2; - pipe_config->pipe_src_w /= 2; + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && + intel_is_dual_link_lvds(i915)) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] Odd pipe source width not supported with dual link LVDS\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } } - if (pipe_config->splitter.enable) { - int n = pipe_config->splitter.link_count; - int overlap = pipe_config->splitter.pixel_overlap; + return 0; +} - pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; - pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; - pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n; - pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n; - pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n; - pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n; - pipe_mode->crtc_clock *= n; - } +static int intel_crtc_compute_pipe_mode(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); + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; + int clock_limit = i915->max_dotclk_freq; + /* + * Start with the adjusted_mode crtc timings, which + * have been filled with the transcoder timings. + */ + drm_mode_copy(pipe_mode, adjusted_mode); + + /* Expand MSO per-segment transcoder timings to full */ + intel_splitter_adjust_timings(crtc_state, pipe_mode); + + /* Derive per-pipe timings in case bigjoiner is used */ + intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - if (DISPLAY_VER(dev_priv) < 4) { - clock_limit = dev_priv->max_cdclk_freq * 9 / 10; + if (DISPLAY_VER(i915) < 4) { + clock_limit = i915->max_cdclk_freq * 9 / 10; /* * Enable double wide mode when the dot clock @@ -2832,44 +2874,40 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, */ if (intel_crtc_supports_double_wide(crtc) && pipe_mode->crtc_clock > clock_limit) { - clock_limit = dev_priv->max_dotclk_freq; - pipe_config->double_wide = true; + clock_limit = i915->max_dotclk_freq; + crtc_state->double_wide = true; } } if (pipe_mode->crtc_clock > clock_limit) { - drm_dbg_kms(&dev_priv->drm, - "requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", + crtc->base.base.id, crtc->base.name, pipe_mode->crtc_clock, clock_limit, - yesno(pipe_config->double_wide)); + yesno(crtc_state->double_wide)); return -EINVAL; } - /* - * Pipe horizontal size must be even in: - * - DVO ganged mode - * - LVDS dual channel mode - * - Double wide pipe - */ - if (pipe_config->pipe_src_w & 1) { - if (pipe_config->double_wide) { - drm_dbg_kms(&dev_priv->drm, - "Odd pipe source width not supported with double wide pipe\n"); - return -EINVAL; - } + return 0; +} - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) && - intel_is_dual_link_lvds(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "Odd pipe source width not supported with dual link LVDS\n"); - return -EINVAL; - } - } +static int intel_crtc_compute_config(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + int ret; + + ret = intel_crtc_compute_pipe_src(crtc_state); + if (ret) + return ret; + + ret = intel_crtc_compute_pipe_mode(crtc_state); + if (ret) + return ret; - intel_crtc_compute_pixel_rate(pipe_config); + intel_crtc_compute_pixel_rate(crtc_state); - if (pipe_config->has_pch_encoder) - return ilk_fdi_compute_config(crtc, pipe_config); + if (crtc_state->has_pch_encoder) + return ilk_fdi_compute_config(crtc, crtc_state); return 0; } @@ -5590,12 +5628,9 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc); - /* Some fixups */ slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed; slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed; slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed; - slave_crtc_state->cpu_transcoder = master_crtc_state->cpu_transcoder; - slave_crtc_state->has_audio = master_crtc_state->has_audio; return 0; } @@ -7458,6 +7493,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_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index ffe6822d7414..78752ce46639 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -10,6 +10,7 @@ #include "intel_de.h" #include "intel_display_debugfs.h" #include "intel_display_power.h" +#include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dp.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 9ebae7ac3235..e8e8ce13aa96 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -11,6 +11,7 @@ #include "intel_crt.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dpio_phy.h" @@ -26,101 +27,6 @@ #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); - const char * intel_display_power_domain_str(enum intel_display_power_domain domain) { @@ -153,12 +59,12 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) return "TRANSCODER_D"; case POWER_DOMAIN_TRANSCODER_EDP: return "TRANSCODER_EDP"; - case POWER_DOMAIN_TRANSCODER_VDSC_PW2: - return "TRANSCODER_VDSC_PW2"; case POWER_DOMAIN_TRANSCODER_DSI_A: return "TRANSCODER_DSI_A"; case POWER_DOMAIN_TRANSCODER_DSI_C: return "TRANSCODER_DSI_C"; + case POWER_DOMAIN_TRANSCODER_VDSC_PW2: + return "TRANSCODER_VDSC_PW2"; case POWER_DOMAIN_PORT_DDI_A_LANES: return "PORT_DDI_A_LANES"; case POWER_DOMAIN_PORT_DDI_B_LANES: @@ -259,40 +165,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) } } -static void intel_power_well_enable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - drm_dbg_kms(&dev_priv->drm, "enabling %s\n", power_well->desc->name); - power_well->desc->ops->enable(dev_priv, power_well); - power_well->hw_enabled = true; -} - -static void intel_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - drm_dbg_kms(&dev_priv->drm, "disabling %s\n", power_well->desc->name); - power_well->hw_enabled = false; - power_well->desc->ops->disable(dev_priv, power_well); -} - -static void intel_power_well_get(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - if (!power_well->count++) - intel_power_well_enable(dev_priv, power_well); -} - -static void intel_power_well_put(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - drm_WARN(&dev_priv->drm, !power_well->count, - "Use count on power well %s is already zero", - power_well->desc->name); - - if (!--power_well->count) - intel_power_well_disable(dev_priv, power_well); -} - /** * __intel_display_power_is_enabled - unlocked check for a power domain * @dev_priv: i915 device instance @@ -317,10 +189,10 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, is_enabled = true; for_each_power_domain_well_reverse(dev_priv, power_well, BIT_ULL(domain)) { - if (power_well->desc->always_on) + if (intel_power_well_is_always_on(power_well)) continue; - if (!power_well->hw_enabled) { + if (!intel_power_well_is_enabled_cached(power_well)) { is_enabled = false; break; } @@ -438,7 +310,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool timeout_expected) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; int enable_delay = power_well->desc->hsw.fixed_enable_delay; @@ -456,7 +328,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, if (intel_de_wait_for_set(dev_priv, regs->driver, HSW_PWR_WELL_CTL_STATE(pw_idx), 1)) { drm_dbg_kms(&dev_priv->drm, "%s power well enable timeout\n", - power_well->desc->name); + intel_power_well_name(power_well)); drm_WARN_ON(&dev_priv->drm, !timeout_expected); @@ -482,7 +354,7 @@ static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv, static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; bool disabled; u32 reqs; @@ -504,7 +376,7 @@ static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, drm_dbg_kms(&dev_priv->drm, "%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n", - power_well->desc->name, + intel_power_well_name(power_well), !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8)); } @@ -520,7 +392,7 @@ static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, static void hsw_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; u32 val; @@ -567,7 +439,7 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv, static void hsw_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; u32 val; @@ -584,7 +456,7 @@ static void icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); u32 val; @@ -616,7 +488,7 @@ static void icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); u32 val; @@ -636,28 +508,10 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) -static u64 async_put_domains_mask(struct i915_power_domains *power_domains); - -static int power_well_async_ref_count(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - int refs = hweight64(power_well->desc->domains & - async_put_domains_mask(&dev_priv->power_domains)); - - drm_WARN_ON(&dev_priv->drm, refs > power_well->count); - - return refs; -} - static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, struct intel_digital_port *dig_port) { - /* Bypass the check if all references are released asynchronously */ - if (power_well_async_ref_count(dev_priv, power_well) == - power_well->count) - return; - if (drm_WARN_ON(&dev_priv->drm, !dig_port)) return; @@ -706,7 +560,7 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, { enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well); struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch); - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; bool is_tbt = power_well->desc->hsw.is_tc_tbt; bool timeout_expected; u32 val; @@ -749,18 +603,6 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, } static void -icl_tc_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well); - struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch); - - icl_tc_port_assert_ref_held(dev_priv, power_well, dig_port); - - hsw_power_well_disable(dev_priv, power_well); -} - -static void icl_aux_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -782,7 +624,7 @@ icl_aux_power_well_disable(struct drm_i915_private *dev_priv, enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); if (intel_phy_is_tc(dev_priv, phy)) - return icl_tc_phy_aux_power_well_disable(dev_priv, power_well); + return hsw_power_well_disable(dev_priv, power_well); else if (IS_ICELAKE(dev_priv)) return icl_combo_phy_aux_power_well_disable(dev_priv, power_well); @@ -798,7 +640,7 @@ icl_aux_power_well_disable(struct drm_i915_private *dev_priv, static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; enum i915_power_well_id id = power_well->desc->id; int pw_idx = power_well->desc->hsw.idx; u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) | @@ -1073,29 +915,6 @@ static void assert_dmc_loaded(struct drm_i915_private *dev_priv) "DMC HTP Not fine\n"); } -static struct i915_power_well * -lookup_power_well(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id) -{ - struct i915_power_well *power_well; - - for_each_power_well(dev_priv, power_well) - if (power_well->desc->id == power_well_id) - return power_well; - - /* - * It's not feasible to add error checking code to the callers since - * this condition really shouldn't happen and it doesn't even make sense - * to abort things like display initialization sequences. Just return - * the first power well and hope the WARN gets reported so we can fix - * our driver. - */ - drm_WARN(&dev_priv->drm, 1, - "Power well %d not defined for this platform\n", - power_well_id); - return &dev_priv->power_domains.power_wells[0]; -} - /** * intel_display_power_set_target_dc_state - Set target dc state. * @dev_priv: i915 device @@ -1123,19 +942,18 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv, if (state == dev_priv->dmc.target_dc_state) goto unlock; - dc_off_enabled = power_well->desc->ops->is_enabled(dev_priv, - power_well); + dc_off_enabled = intel_power_well_is_enabled(dev_priv, power_well); /* * If DC off power well is disabled, need to enable and disable the * DC off power well to effect target DC state. */ if (!dc_off_enabled) - power_well->desc->ops->enable(dev_priv, power_well); + intel_power_well_enable(dev_priv, power_well); dev_priv->dmc.target_dc_state = state; if (!dc_off_enabled) - power_well->desc->ops->disable(dev_priv, power_well); + intel_power_well_disable(dev_priv, power_well); unlock: mutex_unlock(&power_domains->lock); @@ -1208,7 +1026,7 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv) static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx); u32 bios_req = intel_de_read(dev_priv, regs->bios); @@ -1246,17 +1064,17 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) struct i915_power_well *power_well; power_well = lookup_power_well(dev_priv, BXT_DISP_PW_DPIO_CMN_A); - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy); power_well = lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC); - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy); if (IS_GEMINILAKE(dev_priv)) { power_well = lookup_power_well(dev_priv, GLK_DISP_PW_DPIO_CMN_C); - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy); } @@ -1382,7 +1200,7 @@ static bool i830_pipes_power_well_enabled(struct drm_i915_private *dev_priv, static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) i830_pipes_power_well_enable(dev_priv, power_well); else i830_pipes_power_well_disable(dev_priv, power_well); @@ -1655,7 +1473,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) | PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1)); - if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) { + if (intel_power_well_is_enabled(dev_priv, cmn_bc)) { phy_status |= PHY_POWERGOOD(DPIO_PHY0); /* this assumes override is only used to enable lanes */ @@ -1696,7 +1514,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1); } - if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) { + if (intel_power_well_is_enabled(dev_priv, cmn_d)) { phy_status |= PHY_POWERGOOD(DPIO_PHY1); /* this assumes override is only used to enable lanes */ @@ -3280,7 +3098,15 @@ static const struct i915_power_well_desc i830_power_wells[] = { }, }; +static const struct i915_power_well_regs hsw_power_well_regs = { + .bios = HSW_PWR_WELL_CTL1, + .driver = HSW_PWR_WELL_CTL2, + .kvmr = HSW_PWR_WELL_CTL3, + .debug = HSW_PWR_WELL_CTL4, +}; + static const struct i915_power_well_ops hsw_power_well_ops = { + .regs = &hsw_power_well_regs, .sync_hw = hsw_power_well_sync_hw, .enable = hsw_power_well_enable, .disable = hsw_power_well_disable, @@ -3301,13 +3127,6 @@ static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = { .is_enabled = bxt_dpio_cmn_power_well_enabled, }; -static const struct i915_power_well_regs hsw_power_well_regs = { - .bios = HSW_PWR_WELL_CTL1, - .driver = HSW_PWR_WELL_CTL2, - .kvmr = HSW_PWR_WELL_CTL3, - .debug = HSW_PWR_WELL_CTL4, -}; - static const struct i915_power_well_desc hsw_power_wells[] = { { .name = "always-on", @@ -3322,7 +3141,6 @@ static const struct i915_power_well_desc hsw_power_wells[] = { .ops = &hsw_power_well_ops, .id = HSW_DISP_PW_GLOBAL, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, .hsw.has_vga = true, }, @@ -3343,7 +3161,6 @@ static const struct i915_power_well_desc bdw_power_wells[] = { .ops = &hsw_power_well_ops, .id = HSW_DISP_PW_GLOBAL, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3487,18 +3304,6 @@ static const struct i915_power_well_desc chv_power_wells[] = { }, }; -bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id) -{ - struct i915_power_well *power_well; - bool ret; - - power_well = lookup_power_well(dev_priv, power_well_id); - ret = power_well->desc->ops->is_enabled(dev_priv, power_well); - - return ret; -} - static const struct i915_power_well_desc skl_power_wells[] = { { .name = "always-on", @@ -3515,7 +3320,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3528,7 +3332,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_MISC_IO, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_MISC_IO, }, }, @@ -3544,7 +3347,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3557,7 +3359,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E, }, }, @@ -3567,7 +3368,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_B, }, }, @@ -3577,7 +3377,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_C, }, }, @@ -3587,7 +3386,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_D, }, }, @@ -3609,7 +3407,6 @@ static const struct i915_power_well_desc bxt_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3626,7 +3423,6 @@ static const struct i915_power_well_desc bxt_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3669,7 +3465,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3686,7 +3481,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3726,7 +3520,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_AUX_A, }, }, @@ -3736,7 +3529,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_AUX_B, }, }, @@ -3746,7 +3538,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_AUX_C, }, }, @@ -3756,7 +3547,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_DDI_A, }, }, @@ -3766,7 +3556,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_B, }, }, @@ -3776,31 +3565,39 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_C, }, }, }; +static const struct i915_power_well_regs icl_aux_power_well_regs = { + .bios = ICL_PWR_WELL_CTL_AUX1, + .driver = ICL_PWR_WELL_CTL_AUX2, + .debug = ICL_PWR_WELL_CTL_AUX4, +}; + static const struct i915_power_well_ops icl_aux_power_well_ops = { + .regs = &icl_aux_power_well_regs, .sync_hw = hsw_power_well_sync_hw, .enable = icl_aux_power_well_enable, .disable = icl_aux_power_well_disable, .is_enabled = hsw_power_well_enabled, }; -static const struct i915_power_well_regs icl_aux_power_well_regs = { - .bios = ICL_PWR_WELL_CTL_AUX1, - .driver = ICL_PWR_WELL_CTL_AUX2, - .debug = ICL_PWR_WELL_CTL_AUX4, -}; - static const struct i915_power_well_regs icl_ddi_power_well_regs = { .bios = ICL_PWR_WELL_CTL_DDI1, .driver = ICL_PWR_WELL_CTL_DDI2, .debug = ICL_PWR_WELL_CTL_DDI4, }; +static const struct i915_power_well_ops icl_ddi_power_well_ops = { + .regs = &icl_ddi_power_well_regs, + .sync_hw = hsw_power_well_sync_hw, + .enable = hsw_power_well_enable, + .disable = hsw_power_well_disable, + .is_enabled = hsw_power_well_enabled, +}; + static const struct i915_power_well_desc icl_power_wells[] = { { .name = "always-on", @@ -3817,7 +3614,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3834,7 +3630,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, @@ -3845,7 +3640,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -3855,60 +3649,54 @@ static const struct i915_power_well_desc icl_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, }, }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, }, }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_C, }, }, { .name = "DDI D IO", .domains = ICL_DDI_IO_D_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_D, }, }, { .name = "DDI E IO", .domains = ICL_DDI_IO_E_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_E, }, }, { .name = "DDI F IO", .domains = ICL_DDI_IO_F_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_F, }, }, @@ -3918,7 +3706,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -3928,7 +3715,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -3938,7 +3724,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_C, .hsw.is_tc_tbt = false, }, @@ -3949,7 +3734,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_D, .hsw.is_tc_tbt = false, }, @@ -3960,7 +3744,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_E, .hsw.is_tc_tbt = false, }, @@ -3971,7 +3754,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_F, .hsw.is_tc_tbt = false, }, @@ -3982,7 +3764,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1, .hsw.is_tc_tbt = true, }, @@ -3993,7 +3774,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2, .hsw.is_tc_tbt = true, }, @@ -4004,7 +3784,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3, .hsw.is_tc_tbt = true, }, @@ -4015,7 +3794,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4, .hsw.is_tc_tbt = true, }, @@ -4026,7 +3804,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4094,7 +3871,7 @@ static void tgl_tc_cold_off_power_well_sync_hw(struct drm_i915_private *i915, struct i915_power_well *power_well) { - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) tgl_tc_cold_off_power_well_enable(i915, power_well); else tgl_tc_cold_off_power_well_disable(i915, power_well); @@ -4108,7 +3885,7 @@ tgl_tc_cold_off_power_well_is_enabled(struct drm_i915_private *dev_priv, * Not the correctly implementation but there is no way to just read it * from PCODE, so returning count to avoid state mismatch errors */ - return power_well->count; + return intel_power_well_refcount(power_well); } static const struct i915_power_well_ops tgl_tc_cold_off_ops = { @@ -4134,7 +3911,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4151,7 +3927,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, @@ -4162,7 +3937,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -4172,90 +3946,81 @@ static const struct i915_power_well_desc tgl_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_C, } }, { .name = "DDI IO TC1", .domains = TGL_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, }, }, { .name = "DDI IO TC2", .domains = TGL_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, }, }, { .name = "DDI IO TC3", .domains = TGL_DDI_IO_TC3_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3, }, }, { .name = "DDI IO TC4", .domains = TGL_DDI_IO_TC4_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4, }, }, { .name = "DDI IO TC5", .domains = TGL_DDI_IO_TC5_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC5, }, }, { .name = "DDI IO TC6", .domains = TGL_DDI_IO_TC6_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC6, }, }, @@ -4271,7 +4036,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -4281,7 +4045,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -4291,7 +4054,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_C, }, }, @@ -4301,7 +4063,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, .hsw.is_tc_tbt = false, }, @@ -4312,7 +4073,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, .hsw.is_tc_tbt = false, }, @@ -4323,7 +4083,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3, .hsw.is_tc_tbt = false, }, @@ -4334,7 +4093,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4, .hsw.is_tc_tbt = false, }, @@ -4345,7 +4103,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC5, .hsw.is_tc_tbt = false, }, @@ -4356,7 +4113,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC6, .hsw.is_tc_tbt = false, }, @@ -4367,7 +4123,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1, .hsw.is_tc_tbt = true, }, @@ -4378,7 +4133,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2, .hsw.is_tc_tbt = true, }, @@ -4389,7 +4143,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3, .hsw.is_tc_tbt = true, }, @@ -4400,7 +4153,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4, .hsw.is_tc_tbt = true, }, @@ -4411,7 +4163,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT5, .hsw.is_tc_tbt = true, }, @@ -4422,7 +4173,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT6, .hsw.is_tc_tbt = true, }, @@ -4433,7 +4183,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4445,7 +4194,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_PW_5, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_D), @@ -4469,7 +4217,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4486,7 +4233,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -4499,7 +4245,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4508,40 +4253,36 @@ static const struct i915_power_well_desc rkl_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI IO TC1", .domains = TGL_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, }, }, { .name = "DDI IO TC2", .domains = TGL_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, }, }, @@ -4551,7 +4292,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -4561,7 +4301,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -4571,7 +4310,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, }, }, @@ -4581,7 +4319,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, }, }, @@ -4603,7 +4340,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4620,7 +4356,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, @@ -4631,7 +4366,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -4641,40 +4375,36 @@ static const struct i915_power_well_desc dg1_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI IO TC1", .domains = TGL_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, }, }, { .name = "DDI IO TC2", .domains = TGL_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, }, }, @@ -4684,7 +4414,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -4694,7 +4423,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -4704,7 +4432,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, .hsw.is_tc_tbt = false, }, @@ -4715,7 +4442,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, .hsw.is_tc_tbt = false, }, @@ -4726,7 +4452,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4738,7 +4463,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_PW_5, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_D), @@ -4762,7 +4486,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4779,7 +4502,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_vga = true, .hsw.has_fuses = true, @@ -4791,7 +4513,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_A, .hsw.irq_pipe_mask = BIT(PIPE_A), .hsw.has_fuses = true, @@ -4803,7 +4524,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_B, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_fuses = true, @@ -4815,7 +4535,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_C, .hsw.irq_pipe_mask = BIT(PIPE_C), .hsw.has_fuses = true, @@ -4827,7 +4546,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_D, .hsw.irq_pipe_mask = BIT(PIPE_D), .hsw.has_fuses = true, @@ -4836,90 +4554,81 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_C, } }, { .name = "DDI IO D_XELPD", .domains = XELPD_DDI_IO_D_XELPD_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_DDI_D, } }, { .name = "DDI IO E_XELPD", .domains = XELPD_DDI_IO_E_XELPD_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_DDI_E, } }, { .name = "DDI IO TC1", .domains = XELPD_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, } }, { .name = "DDI IO TC2", .domains = XELPD_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, } }, { .name = "DDI IO TC3", .domains = XELPD_DDI_IO_TC3_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3, } }, { .name = "DDI IO TC4", .domains = XELPD_DDI_IO_TC4_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4, } }, @@ -4929,7 +4638,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, .hsw.fixed_enable_delay = 600, }, @@ -4940,7 +4648,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, .hsw.fixed_enable_delay = 600, }, @@ -4951,7 +4658,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_C, .hsw.fixed_enable_delay = 600, }, @@ -4962,7 +4668,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_AUX_D, .hsw.fixed_enable_delay = 600, }, @@ -4973,7 +4678,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_AUX_E, }, }, @@ -4983,7 +4687,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, .hsw.fixed_enable_delay = 600, }, @@ -4994,7 +4697,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, }, }, @@ -5004,7 +4706,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3, }, }, @@ -5014,7 +4715,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4, }, }, @@ -5024,7 +4724,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1, .hsw.is_tc_tbt = true, }, @@ -5035,7 +4734,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2, .hsw.is_tc_tbt = true, }, @@ -5046,7 +4744,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3, .hsw.is_tc_tbt = true, }, @@ -5057,7 +4754,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4, .hsw.is_tc_tbt = true, }, @@ -5281,11 +4977,8 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv) struct i915_power_well *power_well; mutex_lock(&power_domains->lock); - for_each_power_well(dev_priv, power_well) { - power_well->desc->ops->sync_hw(dev_priv, power_well); - power_well->hw_enabled = - power_well->desc->ops->is_enabled(dev_priv, power_well); - } + for_each_power_well(dev_priv, power_well) + intel_power_well_sync_hw(dev_priv, power_well); mutex_unlock(&power_domains->lock); } @@ -5998,7 +5691,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) * override and set the lane powerdown bits accding to the * current lane status. */ - if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) { + if (intel_power_well_is_enabled(dev_priv, cmn_bc)) { u32 status = intel_de_read(dev_priv, DPLL(PIPE_A)); unsigned int mask; @@ -6029,7 +5722,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) dev_priv->chv_phy_assert[DPIO_PHY0] = true; } - if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) { + if (intel_power_well_is_enabled(dev_priv, cmn_d)) { u32 status = intel_de_read(dev_priv, DPIO_PHY_STATUS); unsigned int mask; @@ -6065,15 +5758,15 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) lookup_power_well(dev_priv, VLV_DISP_PW_DISP2D); /* If the display might be already active skip this */ - if (cmn->desc->ops->is_enabled(dev_priv, cmn) && - disp2d->desc->ops->is_enabled(dev_priv, disp2d) && + if (intel_power_well_is_enabled(dev_priv, cmn) && + intel_power_well_is_enabled(dev_priv, disp2d) && intel_de_read(dev_priv, DPIO_CTL) & DPIO_CMNRST) return; drm_dbg_kms(&dev_priv->drm, "toggling display PHY side reset\n"); /* cmnlane needs DPLL registers */ - disp2d->desc->ops->enable(dev_priv, disp2d); + intel_power_well_enable(dev_priv, disp2d); /* * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx: @@ -6082,7 +5775,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) * Simply ungating isn't enough to reset the PHY enough to get * ports and lanes running. */ - cmn->desc->ops->disable(dev_priv, cmn); + intel_power_well_disable(dev_priv, cmn); } static bool vlv_punit_is_power_gated(struct drm_i915_private *dev_priv, u32 reg0) @@ -6233,12 +5926,12 @@ void intel_power_domains_sanitize_state(struct drm_i915_private *i915) for_each_power_well_reverse(i915, power_well) { if (power_well->desc->always_on || power_well->count || - !power_well->desc->ops->is_enabled(i915, power_well)) + !intel_power_well_is_enabled(i915, power_well)) continue; drm_dbg_kms(&i915->drm, "BIOS left unused %s power well enabled, disabling it\n", - power_well->desc->name); + intel_power_well_name(power_well)); intel_power_well_disable(i915, power_well); } @@ -6377,9 +6070,9 @@ static void intel_power_domains_dump_info(struct drm_i915_private *i915) enum intel_display_power_domain domain; drm_dbg(&i915->drm, "%-25s %d\n", - power_well->desc->name, power_well->count); + intel_power_well_name(power_well), intel_power_well_refcount(power_well)); - for_each_power_domain(domain, power_well->desc->domains) + for_each_power_domain(domain, intel_power_well_domains(power_well)) drm_dbg(&i915->drm, " %-23s %d\n", intel_display_power_domain_str(domain), power_domains->domain_use_count[domain]); @@ -6412,23 +6105,25 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915) int domains_count; bool enabled; - enabled = power_well->desc->ops->is_enabled(i915, power_well); - if ((power_well->count || power_well->desc->always_on) != + enabled = intel_power_well_is_enabled(i915, power_well); + if ((intel_power_well_refcount(power_well) || + intel_power_well_is_always_on(power_well)) != enabled) drm_err(&i915->drm, "power well %s state mismatch (refcount %d/enabled %d)", - power_well->desc->name, - power_well->count, enabled); + intel_power_well_name(power_well), + intel_power_well_refcount(power_well), enabled); domains_count = 0; - for_each_power_domain(domain, power_well->desc->domains) + for_each_power_domain(domain, intel_power_well_domains(power_well)) domains_count += power_domains->domain_use_count[domain]; - if (power_well->count != domains_count) { + if (intel_power_well_refcount(power_well) != domains_count) { drm_err(&i915->drm, "power well %s refcount/domain refcount mismatch " "(refcount %d/domains refcount %d)\n", - power_well->desc->name, power_well->count, + intel_power_well_name(power_well), + intel_power_well_refcount(power_well), domains_count); dump_domain_info = true; } @@ -6533,10 +6228,10 @@ void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m 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); + seq_printf(m, "%-25s %d\n", intel_power_well_name(power_well), + intel_power_well_refcount(power_well)); - for_each_power_domain(power_domain, power_well->desc->domains) + for_each_power_domain(power_domain, intel_power_well_domains(power_well)) seq_printf(m, " %-23s %d\n", intel_display_power_domain_str(power_domain), power_domains->domain_use_count[power_domain]); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index f6d0e6e73c6d..ced384b0a165 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -14,6 +14,11 @@ struct drm_i915_private; struct i915_power_well; struct intel_encoder; +/* + * Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances + * consecutive, so that the pipe,transcoder,port -> power domain macros + * work correctly. + */ enum intel_display_power_domain { POWER_DOMAIN_DISPLAY_CORE, POWER_DOMAIN_PIPE_A, @@ -29,10 +34,12 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_D, POWER_DOMAIN_TRANSCODER_EDP, - /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */ - POWER_DOMAIN_TRANSCODER_VDSC_PW2, POWER_DOMAIN_TRANSCODER_DSI_A, POWER_DOMAIN_TRANSCODER_DSI_C, + + /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */ + POWER_DOMAIN_TRANSCODER_VDSC_PW2, + POWER_DOMAIN_PORT_DDI_A_LANES, POWER_DOMAIN_PORT_DDI_B_LANES, POWER_DOMAIN_PORT_DDI_C_LANES, @@ -125,30 +132,6 @@ enum intel_display_power_domain { POWER_DOMAIN_NUM, }; -/* - * i915_power_well_id: - * - * IDs used to look up power wells. Power wells accessed directly bypassing - * the power domains framework must be assigned a unique ID. The rest of power - * wells must be assigned DISP_PW_ID_NONE. - */ -enum i915_power_well_id { - DISP_PW_ID_NONE, - - VLV_DISP_PW_DISP2D, - BXT_DISP_PW_DPIO_CMN_A, - VLV_DISP_PW_DPIO_CMN_BC, - GLK_DISP_PW_DPIO_CMN_C, - CHV_DISP_PW_DPIO_CMN_D, - HSW_DISP_PW_GLOBAL, - SKL_DISP_PW_MISC_IO, - SKL_DISP_PW_1, - SKL_DISP_PW_2, - ICL_DISP_PW_3, - SKL_DISP_DC_OFF, - TGL_DISP_PW_TC_COLD_OFF, -}; - #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER) @@ -232,8 +215,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain); bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); -bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id); bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c new file mode 100644 index 000000000000..2a0fb9d9c60f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include "i915_drv.h" +#include "intel_display_power_well.h" + +struct i915_power_well * +lookup_power_well(struct drm_i915_private *i915, + enum i915_power_well_id power_well_id) +{ + struct i915_power_well *power_well; + + for_each_power_well(i915, power_well) + if (power_well->desc->id == power_well_id) + return power_well; + + /* + * It's not feasible to add error checking code to the callers since + * this condition really shouldn't happen and it doesn't even make sense + * to abort things like display initialization sequences. Just return + * the first power well and hope the WARN gets reported so we can fix + * our driver. + */ + drm_WARN(&i915->drm, 1, + "Power well %d not defined for this platform\n", + power_well_id); + return &i915->power_domains.power_wells[0]; +} + +void intel_power_well_enable(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + drm_dbg_kms(&i915->drm, "enabling %s\n", power_well->desc->name); + power_well->desc->ops->enable(i915, power_well); + power_well->hw_enabled = true; +} + +void intel_power_well_disable(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + drm_dbg_kms(&i915->drm, "disabling %s\n", power_well->desc->name); + power_well->hw_enabled = false; + power_well->desc->ops->disable(i915, power_well); +} + +void intel_power_well_sync_hw(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + power_well->desc->ops->sync_hw(i915, power_well); + power_well->hw_enabled = + power_well->desc->ops->is_enabled(i915, power_well); +} + +void intel_power_well_get(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + if (!power_well->count++) + intel_power_well_enable(i915, power_well); +} + +void intel_power_well_put(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + drm_WARN(&i915->drm, !power_well->count, + "Use count on power well %s is already zero", + power_well->desc->name); + + if (!--power_well->count) + intel_power_well_disable(i915, power_well); +} + +bool intel_power_well_is_enabled(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + return power_well->desc->ops->is_enabled(i915, power_well); +} + +bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well) +{ + return power_well->hw_enabled; +} + +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, + enum i915_power_well_id power_well_id) +{ + struct i915_power_well *power_well; + + power_well = lookup_power_well(dev_priv, power_well_id); + + return intel_power_well_is_enabled(dev_priv, power_well); +} + +bool intel_power_well_is_always_on(struct i915_power_well *power_well) +{ + return power_well->desc->always_on; +} + +const char *intel_power_well_name(struct i915_power_well *power_well) +{ + return power_well->desc->name; +} + +u64 intel_power_well_domains(struct i915_power_well *power_well) +{ + return power_well->desc->domains; +} + +int intel_power_well_refcount(struct i915_power_well *power_well) +{ + return power_well->count; +} diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h new file mode 100644 index 000000000000..9a3756fdcf7f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ +#ifndef __INTEL_DISPLAY_POWER_WELL_H__ +#define __INTEL_DISPLAY_POWER_WELL_H__ + +#include <linux/types.h> + +#include "intel_display.h" + +struct drm_i915_private; +struct i915_power_well; + +/* + * i915_power_well_id: + * + * IDs used to look up power wells. Power wells accessed directly bypassing + * the power domains framework must be assigned a unique ID. The rest of power + * wells must be assigned DISP_PW_ID_NONE. + */ +enum i915_power_well_id { + DISP_PW_ID_NONE, + + VLV_DISP_PW_DISP2D, + BXT_DISP_PW_DPIO_CMN_A, + VLV_DISP_PW_DPIO_CMN_BC, + GLK_DISP_PW_DPIO_CMN_C, + CHV_DISP_PW_DPIO_CMN_D, + HSW_DISP_PW_GLOBAL, + SKL_DISP_PW_MISC_IO, + SKL_DISP_PW_1, + SKL_DISP_PW_2, + ICL_DISP_PW_3, + SKL_DISP_DC_OFF, + TGL_DISP_PW_TC_COLD_OFF, +}; + +struct i915_power_well_regs { + i915_reg_t bios; + i915_reg_t driver; + i915_reg_t kvmr; + i915_reg_t debug; +}; + +struct i915_power_well_ops { + const struct i915_power_well_regs *regs; + /* + * 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 *i915, + 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 *i915, + 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 *i915, + struct i915_power_well *power_well); + /* Returns the hw enabled state. */ + bool (*is_enabled)(struct drm_i915_private *i915, + struct i915_power_well *power_well); +}; + +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 { + /* + * 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_well *lookup_power_well(struct drm_i915_private *i915, + enum i915_power_well_id id); + +void intel_power_well_enable(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_disable(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_sync_hw(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_get(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_put(struct drm_i915_private *i915, + struct i915_power_well *power_well); +bool intel_power_well_is_enabled(struct drm_i915_private *i915, + struct i915_power_well *power_well); +bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well); +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, + enum i915_power_well_id power_well_id); +bool intel_power_well_is_always_on(struct i915_power_well *power_well); +const char *intel_power_well_name(struct i915_power_well *power_well); +u64 intel_power_well_domains(struct i915_power_well *power_well); +int intel_power_well_refcount(struct i915_power_well *power_well); + +#endif diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 7616a3906b9e..133476be6d28 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -697,7 +697,7 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) dmc->fw_path = RKL_DMC_PATH; dmc->required_version = RKL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; - } else if (DISPLAY_VER(dev_priv) >= 12) { + } else if (IS_TIGERLAKE(dev_priv)) { dmc->fw_path = TGL_DMC_PATH; dmc->required_version = TGL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 23cfe2e5ce2a..94c57facbb46 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -135,11 +135,16 @@ struct intel_modifier_desc { 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) + INTEL_PLANE_CAP_TILING_Yf | \ + INTEL_PLANE_CAP_TILING_4) #define INTEL_PLANE_CAP_TILING_NONE 0 static const struct intel_modifier_desc intel_modifiers[] = { { + .modifier = I915_FORMAT_MOD_4_TILED, + .display_ver = { 13, 13 }, + .plane_caps = INTEL_PLANE_CAP_TILING_4, + }, { .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, @@ -545,6 +550,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; @@ -650,6 +661,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) return I915_TILING_Y; case INTEL_PLANE_CAP_TILING_X: return I915_TILING_X; + case INTEL_PLANE_CAP_TILING_4: case INTEL_PLANE_CAP_TILING_Yf: case INTEL_PLANE_CAP_TILING_NONE: return I915_TILING_NONE; @@ -737,6 +749,7 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_4_TILED: case I915_FORMAT_MOD_Yf_TILED: return 1 * 1024 * 1024; default: diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index ba9df8986c1e..12386f13a4e0 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -27,6 +27,7 @@ struct intel_plane_state; #define INTEL_PLANE_CAP_TILING_X BIT(3) #define INTEL_PLANE_CAP_TILING_Y BIT(4) #define INTEL_PLANE_CAP_TILING_Yf BIT(5) +#define INTEL_PLANE_CAP_TILING_4 BIT(6) 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_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 87f4af3fd523..f7dca327c294 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -946,6 +946,7 @@ static bool tiling_is_valid(const struct intel_plane_state *plane_state) 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_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index e1ecf38db0ef..4de4c174a987 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -20,6 +20,7 @@ #include "intel_connector.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_hdcp.h" #include "intel_pcode.h" diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index d7b1de4cc205..e207d12286b5 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -127,6 +127,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/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 7e6245b97fed..0dd4775e8195 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -32,10 +32,14 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) if (!intel_phy_is_snps(i915, phy)) continue; + /* + * If calibration does not complete successfully, we'll remember + * which phy was affected and skip setup of the corresponding + * output later. + */ if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy), DG2_PHY_DP_TX_ACK_MASK, 25)) - drm_err(&i915->drm, "SNPS PHY %c failed to calibrate after 25ms.\n", - phy_name(phy)); + i915->snps_phy_failed_calibration |= BIT(phy); } } diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 2d71294aaceb..f6875a49b8cb 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -430,9 +430,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane, 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); - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id), plane_state->view.color_plane[0].mapping_stride); @@ -440,8 +437,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane, SP_POS_Y(crtc_y) | SP_POS_X(crtc_x)); intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id), SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -457,14 +452,11 @@ vlv_sprite_update_arm(struct intel_plane *plane, 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); @@ -494,8 +486,6 @@ vlv_sprite_update_arm(struct intel_plane *plane, vlv_sprite_update_clrc(plane_state); vlv_sprite_update_gamma(plane_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -505,14 +495,9 @@ vlv_sprite_disable_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0); intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool @@ -862,15 +847,12 @@ ivb_sprite_update_noarm(struct intel_plane *plane, u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 sprscale = 0; - unsigned long irqflags; if (crtc_w != src_w || crtc_h != src_h) sprscale = SPRITE_SCALE_ENABLE | SPRITE_SRC_WIDTH(src_w - 1) | SPRITE_SRC_HEIGHT(src_h - 1); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, SPRSTRIDE(pipe), plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, SPRPOS(pipe), @@ -879,8 +861,6 @@ ivb_sprite_update_noarm(struct intel_plane *plane, SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1)); if (IS_IVYBRIDGE(dev_priv)) intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -895,14 +875,11 @@ ivb_sprite_update_arm(struct intel_plane *plane, 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), @@ -931,8 +908,6 @@ ivb_sprite_update_arm(struct intel_plane *plane, intel_plane_ggtt_offset(plane_state) + sprsurf_offset); ivb_sprite_update_gamma(plane_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -941,17 +916,12 @@ ivb_sprite_disable_arm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPRCTL(pipe), 0); /* Disable the scaler */ if (IS_IVYBRIDGE(dev_priv)) intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0); intel_de_write_fw(dev_priv, SPRSURF(pipe), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool @@ -1204,15 +1174,12 @@ g4x_sprite_update_noarm(struct intel_plane *plane, u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 dvsscale = 0; - unsigned long irqflags; if (crtc_w != src_w || crtc_h != src_h) dvsscale = DVS_SCALE_ENABLE | DVS_SRC_WIDTH(src_w - 1) | DVS_SRC_HEIGHT(src_h - 1); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, DVSSTRIDE(pipe), plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, DVSPOS(pipe), @@ -1220,8 +1187,6 @@ g4x_sprite_update_noarm(struct intel_plane *plane, intel_de_write_fw(dev_priv, DVSSIZE(pipe), DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1)); intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1236,14 +1201,11 @@ g4x_sprite_update_arm(struct intel_plane *plane, 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), @@ -1267,8 +1229,6 @@ g4x_sprite_update_arm(struct intel_plane *plane, g4x_sprite_update_gamma(plane_state); else ilk_sprite_update_gamma(plane_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1277,16 +1237,11 @@ g4x_sprite_disable_arm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0); /* Disable the scaler */ intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0); intel_de_write_fw(dev_priv, DVSSURF(pipe), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 545eff5bf158..e7120900bc45 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -378,10 +378,18 @@ calculate_rc_params(struct rc_parameters *rc, { int bpc = vdsc_cfg->bits_per_component; int bpp = vdsc_cfg->bits_per_pixel >> 4; - int ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 }; - int ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 }; - int ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 }; - int ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 }; + static const s8 ofs_und6[] = { + 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 + }; + static const s8 ofs_und8[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und12[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und15[] = { + 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 + }; int qp_bpc_modifier = (bpc - 8) * 2; u32 res, buf_i, bpp_i; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 1223075595ff..fdade206f056 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -615,9 +615,20 @@ skl_plane_disable_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - unsigned long irqflags; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + skl_write_plane_wm(plane, crtc_state); + + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0); + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0); +} + +static void +icl_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; + enum pipe pipe = plane->pipe; if (icl_is_hdr_plane(dev_priv, plane_id)) intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0); @@ -627,8 +638,6 @@ skl_plane_disable_arm(struct intel_plane *plane, intel_psr2_disable_plane_sel_fetch(plane, crtc_state); intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool @@ -762,6 +771,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; @@ -1065,7 +1076,7 @@ static void icl_plane_csc_load_black(struct intel_plane *plane) intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0); } -static int skl_plane_color_plane(const struct intel_plane_state *plane_state) +static int icl_plane_color_plane(const struct intel_plane_state *plane_state) { /* Program the UV plane on planar master */ if (plane_state->planar_linked_plane && !plane_state->planar_slave) @@ -1082,14 +1093,11 @@ skl_plane_update_noarm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - int color_plane = skl_plane_color_plane(plane_state); - u32 stride = skl_plane_stride(plane_state, color_plane); - const struct drm_framebuffer *fb = plane_state->hw.fb; + u32 stride = skl_plane_stride(plane_state, 0); int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - unsigned long irqflags; /* The scaler will handle the output position */ if (plane_state->scaler_id >= 0) { @@ -1097,14 +1105,99 @@ skl_plane_update_noarm(struct intel_plane *plane, crtc_y = 0; } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), + PLANE_STRIDE_(stride)); + intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), + PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x)); + intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id), + PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); + + skl_write_plane_wm(plane, crtc_state); +} + +static void +skl_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 plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + u32 x = plane_state->view.color_plane[0].x; + u32 y = plane_state->view.color_plane[0].y; + u32 plane_ctl, plane_color_ctl = 0; + + plane_ctl = plane_state->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); + + intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state)); + intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state)); + intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state)); + + intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id), + PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); + + intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), + skl_plane_aux_dist(plane_state, 0)); + + intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id), + PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) | + PLANE_OFFSET_X(plane_state->view.color_plane[1].x)); + + if (DISPLAY_VER(dev_priv) >= 10) + intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); /* - * FIXME: pxp session invalidation can hit any time even at time of commit - * or after the commit, display content will be garbage. + * 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->force_black) - icl_plane_csc_load_black(plane); + if (plane_state->scaler_id >= 0) + skl_program_plane_scaler(plane, crtc_state, plane_state); + + /* + * The control register self-arms if the plane was previously + * disabled. Try to make the plane enable atomic by writing + * the control register just before the surface register. + */ + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), + skl_plane_surf(plane_state, 0)); +} + +static void +icl_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 plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + int color_plane = icl_plane_color_plane(plane_state); + u32 stride = skl_plane_stride(plane_state, color_plane); + const struct drm_framebuffer *fb = plane_state->hw.fb; + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + int x = plane_state->view.color_plane[color_plane].x; + int y = plane_state->view.color_plane[color_plane].y; + int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; + u32 plane_color_ctl; + + plane_color_ctl = plane_state->color_ctl | + glk_plane_color_ctl_crtc(crtc_state); + + /* The scaler will handle the output position */ + if (plane_state->scaler_id >= 0) { + crtc_x = 0; + crtc_y = 0; + } intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), PLANE_STRIDE_(stride)); @@ -1113,6 +1206,13 @@ skl_plane_update_noarm(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id), PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); + intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state)); + intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state)); + intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state)); + + intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id), + PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); + if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) { intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0), lower_32_bits(plane_state->ccval)); @@ -1120,60 +1220,43 @@ skl_plane_update_noarm(struct intel_plane *plane, upper_32_bits(plane_state->ccval)); } + intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), + skl_plane_aux_dist(plane_state, color_plane)); + 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); + 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); skl_write_plane_wm(plane, crtc_state); - intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); + /* + * FIXME: pxp session invalidation can hit any time even at time of commit + * or after the commit, display content will be garbage. + */ + if (plane_state->force_black) + icl_plane_csc_load_black(plane); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); } static void -skl_plane_update_arm(struct intel_plane *plane, +icl_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 plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - int color_plane = skl_plane_color_plane(plane_state); - u32 x = plane_state->view.color_plane[color_plane].x; - u32 y = plane_state->view.color_plane[color_plane].y; - u32 plane_color_ctl = 0; - 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); - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state)); - intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state)); - intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state)); - - intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id), - PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); - - intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), - skl_plane_aux_dist(plane_state, color_plane)); + int color_plane = icl_plane_color_plane(plane_state); + u32 plane_ctl; - if (DISPLAY_VER(dev_priv) < 11) - intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id), - PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) | - PLANE_OFFSET_X(plane_state->view.color_plane[1].x)); - - if (DISPLAY_VER(dev_priv) >= 10) - intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); + plane_ctl = plane_state->ctl | + skl_plane_ctl_crtc(crtc_state); /* * Enable the scaler before the plane so that we don't @@ -1193,8 +1276,6 @@ skl_plane_update_arm(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), skl_plane_surf(plane_state, color_plane)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1204,7 +1285,6 @@ skl_plane_async_flip(struct intel_plane *plane, bool async_flip) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - unsigned long irqflags; enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; u32 plane_ctl = plane_state->ctl; @@ -1214,13 +1294,9 @@ skl_plane_async_flip(struct intel_plane *plane, if (async_flip) plane_ctl |= PLANE_CTL_ASYNC_FLIP; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), skl_plane_surf(plane_state, 0)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool intel_format_is_p01x(u32 format) @@ -2011,9 +2087,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: @@ -2106,6 +2180,8 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915, caps |= INTEL_PLANE_CAP_TILING_Y; if (DISPLAY_VER(i915) < 12) caps |= INTEL_PLANE_CAP_TILING_Yf; + if (HAS_4TILE(i915)) + caps |= INTEL_PLANE_CAP_TILING_4; if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) { caps |= INTEL_PLANE_CAP_CCS_RC; @@ -2162,9 +2238,15 @@ 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; + if (DISPLAY_VER(dev_priv) >= 11) { + plane->update_noarm = icl_plane_update_noarm; + plane->update_arm = icl_plane_update_arm; + plane->disable_arm = icl_plane_disable_arm; + } else { + 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; plane->check_plane = skl_plane_check; @@ -2278,6 +2360,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; + static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4); if (!plane->get_hw_state(plane, &pipe)) return; @@ -2340,11 +2423,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 f600d1cb01b3..5cfe69b30841 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -837,8 +837,16 @@ struct drm_i915_private { bool irq_enabled; - /* perform PHY state sanity checks? */ - bool chv_phy_assert[2]; + union { + /* perform PHY state sanity checks? */ + bool chv_phy_assert[2]; + + /* + * DG2: Mask of PHYs that were not calibrated by the firmware + * and should not be used. + */ + u8 snps_phy_failed_calibration; + }; bool ipc_enabled; @@ -1252,6 +1260,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 8246cbe9b01d..a95ae08b071c 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1046,6 +1046,7 @@ static const struct intel_device_info dg2_info = { DGFX_FEATURES, .graphics.rel = 55, .media.rel = 55, + .has_4tile = 1, PLATFORM(INTEL_DG2), .has_guc_deprivilege = 1, .has_64k_pages = 1, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2b8a3086ed35..5f6c307f476a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4844,6 +4844,7 @@ #define PLANE_CTL_TILED_X REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 1) #define PLANE_CTL_TILED_Y REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 4) #define PLANE_CTL_TILED_YF REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) +#define PLANE_CTL_TILED_4 REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) #define PLANE_CTL_ASYNC_FLIP REG_BIT(9) #define PLANE_CTL_FLIP_HORIZONTAL REG_BIT(8) #define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE REG_BIT(4) /* TGL+ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 27dcfe6f2429..8026e805ff12 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -133,6 +133,7 @@ enum intel_ppgtt_type { func(has_64k_pages); \ func(gpu_reset_clobbers_display); \ func(has_reset_engine); \ + func(has_4tile); \ func(has_global_mocs); \ func(has_gt_uc); \ func(has_guc_deprivilege); \ diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index 4f7a61d5502e..4cce044efde2 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -108,6 +108,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) /* Comet Lake V PCH is based on KBP, which is SPT compatible */ return PCH_SPT; case INTEL_PCH_ICP_DEVICE_ID_TYPE: + case INTEL_PCH_ICP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); return PCH_ICP; @@ -123,7 +124,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) !IS_GEN9_BC(dev_priv)); return PCH_TGP; case INTEL_PCH_JSP_DEVICE_ID_TYPE: - case INTEL_PCH_JSP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); return PCH_JSP; diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h index 6fd20408f7bf..b7a8cf409d48 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/intel_pch.h @@ -50,11 +50,11 @@ enum intel_pch { #define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 #define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 #define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 +#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 #define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 #define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 #define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 -#define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80 #define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 #define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5af16ca4dabd..b9d711246f1e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5415,6 +5415,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; @@ -5930,7 +5931,7 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv, val |= PLANE_WM_EN; if (level->ignore_lines) val |= PLANE_WM_IGNORE_LINES; - val |= level->blocks; + val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); intel_de_write_fw(dev_priv, reg, val); @@ -6578,7 +6579,7 @@ static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level) { level->enable = val & PLANE_WM_EN; level->ignore_lines = val & PLANE_WM_IGNORE_LINES; - level->blocks = val & PLANE_WM_BLOCKS_MASK; + level->blocks = REG_FIELD_GET(PLANE_WM_BLOCKS_MASK, val); level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val); } |