diff options
Diffstat (limited to 'drivers/gpu/drm')
82 files changed, 2495 insertions, 2091 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a26edcdadc21..cea00aaca04b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -282,6 +282,7 @@ i915-y += \ display/intel_ddi.o \ display/intel_ddi_buf_trans.o \ display/intel_display_trace.o \ + display/intel_dkl_phy.o \ display/intel_dp.o \ display/intel_dp_aux.o \ display/intel_dp_aux_backlight.o \ diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 2b73f5ff0d02..8aadf96fa5e9 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -585,7 +585,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, } else { intel_encoder->pipe_mask = ~0; } - intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG; + intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG); intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); /* * BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems @@ -593,7 +593,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, * only one port anyway, nothing is lost by allowing it. */ if (IS_G4X(dev_priv)) - intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; + intel_encoder->cloneable |= BIT(INTEL_OUTPUT_HDMI); dig_port->hdmi.hdmi_reg = hdmi_reg; dig_port->dp.output_reg = INVALID_MMIO_REG; diff --git a/drivers/gpu/drm/i915/display/hsw_ips.c b/drivers/gpu/drm/i915/display/hsw_ips.c index a5be4af792cb..83aa3800245f 100644 --- a/drivers/gpu/drm/i915/display/hsw_ips.c +++ b/drivers/gpu/drm/i915/display/hsw_ips.c @@ -104,8 +104,7 @@ static bool hsw_ips_need_disable(struct intel_atomic_state *state, * Disable IPS before we program the LUT. */ if (IS_HASWELL(i915) && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe) && + intel_crtc_needs_color_update(new_crtc_state) && new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) return true; @@ -146,8 +145,7 @@ static bool hsw_ips_need_enable(struct intel_atomic_state *state, * Re-enable IPS after the LUT has been programmed. */ if (IS_HASWELL(i915) && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe) && + intel_crtc_needs_color_update(new_crtc_state) && new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) return true; @@ -155,7 +153,7 @@ static bool hsw_ips_need_enable(struct intel_atomic_state *state, * We can't read out IPS on broadwell, assume the worst and * forcibly enable IPS on the first fastset. */ - if (new_crtc_state->update_pipe && old_crtc_state->inherited) + if (intel_crtc_needs_fastset(new_crtc_state) && old_crtc_state->inherited) return true; return !old_crtc_state->ips_enabled; diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ed4d93942dbd..e05e7cd6c412 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1974,16 +1974,8 @@ static void icl_dsi_add_properties(struct intel_connector *connector) { const struct drm_display_mode *fixed_mode = intel_panel_preferred_fixed_mode(connector); - u32 allowed_scalers; - allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | - BIT(DRM_MODE_SCALE_FULLSCREEN) | - BIT(DRM_MODE_SCALE_CENTER); - - drm_connector_attach_scaling_mode_property(&connector->base, - allowed_scalers); - - connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; + intel_attach_scaling_mode_property(&connector->base); drm_connector_set_panel_orientation_with_quirk(&connector->base, intel_dsi_get_panel_orientation(connector), @@ -1993,7 +1985,6 @@ static void icl_dsi_add_properties(struct intel_connector *connector) void icl_dsi_init(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_dsi *intel_dsi; struct intel_encoder *encoder; struct intel_connector *intel_connector; @@ -2018,7 +2009,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) connector = &intel_connector->base; /* register DSI encoder with DRM subsystem */ - drm_encoder_init(dev, &encoder->base, &gen11_dsi_encoder_funcs, + drm_encoder_init(&dev_priv->drm, &encoder->base, &gen11_dsi_encoder_funcs, DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port)); encoder->pre_pll_enable = gen11_dsi_pre_pll_enable; @@ -2042,12 +2033,10 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) encoder->is_clock_enabled = gen11_dsi_is_clock_enabled; /* register DSI connector with DRM subsystem */ - drm_connector_init(dev, connector, &gen11_dsi_connector_funcs, + drm_connector_init(&dev_priv->drm, connector, &gen11_dsi_connector_funcs, DRM_MODE_CONNECTOR_DSI); drm_connector_helper_add(connector, &gen11_dsi_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; intel_connector->get_hw_state = intel_connector_get_hw_state; /* attach connector to encoder */ @@ -2055,9 +2044,9 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); intel_panel_add_vbt_lfp_fixed_mode(intel_connector); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&dev_priv->drm.mode_config.mutex); if (!intel_panel_preferred_fixed_mode(intel_connector)) { drm_err(&dev_priv->drm, "DSI fixed mode info missing\n"); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 18f0a5ae3bac..6621aa245caf 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -252,6 +252,11 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) if (crtc_state->hw.gamma_lut) drm_property_blob_get(crtc_state->hw.gamma_lut); + if (crtc_state->pre_csc_lut) + drm_property_blob_get(crtc_state->pre_csc_lut); + if (crtc_state->post_csc_lut) + drm_property_blob_get(crtc_state->post_csc_lut); + crtc_state->update_pipe = false; crtc_state->disable_lp_wm = false; crtc_state->disable_cxsr = false; @@ -274,6 +279,9 @@ static void intel_crtc_put_color_blobs(struct intel_crtc_state *crtc_state) drm_property_blob_put(crtc_state->hw.degamma_lut); drm_property_blob_put(crtc_state->hw.gamma_lut); drm_property_blob_put(crtc_state->hw.ctm); + + drm_property_blob_put(crtc_state->pre_csc_lut); + drm_property_blob_put(crtc_state->post_csc_lut); } void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index aaa6708256d5..bcf0239b9533 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -425,6 +425,47 @@ static bool intel_plane_do_async_flip(struct intel_plane *plane, return DISPLAY_VER(i915) < 13 || old_crtc_state->uapi.async_flip; } +static bool i9xx_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state, + const struct intel_plane_state *old_plane_state, + const struct intel_plane_state *new_plane_state) +{ + struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); + bool old_visible = old_plane_state->uapi.visible; + bool new_visible = new_plane_state->uapi.visible; + u32 old_ctl = old_plane_state->ctl; + u32 new_ctl = new_plane_state->ctl; + bool modeset, turn_on, turn_off; + + if (plane->id == PLANE_CURSOR) + return false; + + modeset = intel_crtc_needs_modeset(new_crtc_state); + turn_off = old_visible && (!new_visible || modeset); + turn_on = new_visible && (!old_visible || modeset); + + /* Must disable CxSR around plane enable/disable */ + if (turn_on || turn_off) + return true; + + if (!old_visible || !new_visible) + return false; + + /* + * Most plane control register updates are blocked while in CxSR. + * + * Tiling mode is one exception where the primary plane can + * apparently handle it, whereas the sprites can not (the + * sprite issue being only relevant on VLV/CHV where CxSR + * is actually possible with a sprite enabled). + */ + if (plane->id == PLANE_PRIMARY) { + old_ctl &= ~DISP_TILED; + new_ctl &= ~DISP_TILED; + } + + return old_ctl != new_ctl; +} + static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state, const struct intel_plane_state *old_plane_state, @@ -482,17 +523,9 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr if (turn_on) { if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) new_crtc_state->update_wm_pre = true; - - /* must disable cxsr around plane enable/disable */ - if (plane->id != PLANE_CURSOR) - new_crtc_state->disable_cxsr = true; } else if (turn_off) { if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) new_crtc_state->update_wm_post = true; - - /* must disable cxsr around plane enable/disable */ - if (plane->id != PLANE_CURSOR) - new_crtc_state->disable_cxsr = true; } else if (intel_wm_need_update(old_plane_state, new_plane_state)) { if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) { /* FIXME bollocks */ @@ -504,6 +537,10 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr if (visible || was_visible) new_crtc_state->fb_bits |= plane->frontbuffer_bit; + if (HAS_GMCH(dev_priv) && + i9xx_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state)) + new_crtc_state->disable_cxsr = true; + /* * ILK/SNB DVSACNTR/Sprite Enable * IVB SPR_CTL/Sprite Enable @@ -1005,7 +1042,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane, */ if (intel_crtc_needs_modeset(crtc_state)) { ret = i915_sw_fence_await_reservation(&state->commit_ready, - old_obj->base.resv, NULL, + old_obj->base.resv, false, 0, GFP_KERNEL); if (ret < 0) @@ -1039,8 +1076,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane, struct dma_fence *fence; ret = i915_sw_fence_await_reservation(&state->commit_ready, - obj->base.resv, NULL, - false, + obj->base.resv, false, i915_fence_timeout(dev_priv), GFP_KERNEL); if (ret < 0) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index aacbc6da84ef..c3176c9c89a6 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -250,7 +250,7 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = { /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int i; @@ -260,17 +260,17 @@ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_sta break; } - if (DISPLAY_VER(dev_priv) < 12 && adjusted_mode->crtc_clock > 148500) + if (DISPLAY_VER(i915) < 12 && adjusted_mode->crtc_clock > 148500) i = ARRAY_SIZE(hdmi_audio_clock); if (i == ARRAY_SIZE(hdmi_audio_clock)) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "HDMI audio pixel clock setting for %d not found, falling back to defaults\n", adjusted_mode->crtc_clock); i = 1; } - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "Configuring HDMI audio for pixel clock %d (0x%08x)\n", hdmi_audio_clock[i].clock, hdmi_audio_clock[i].config); @@ -304,96 +304,67 @@ static int audio_config_hdmi_get_n(const struct intel_crtc_state *crtc_state, return 0; } -static bool intel_eld_uptodate(struct drm_connector *connector, - i915_reg_t reg_eldv, u32 bits_eldv, - i915_reg_t reg_elda, u32 bits_elda, - i915_reg_t reg_edid) +/* ELD buffer size in dwords */ +static int g4x_eld_buffer_size(struct drm_i915_private *i915) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); - const u8 *eld = connector->eld; u32 tmp; - int i; - - tmp = intel_de_read(dev_priv, reg_eldv); - tmp &= bits_eldv; - - if (!tmp) - return false; - tmp = intel_de_read(dev_priv, reg_elda); - tmp &= ~bits_elda; - intel_de_write(dev_priv, reg_elda, tmp); + tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); - for (i = 0; i < drm_eld_size(eld) / 4; i++) - if (intel_de_read(dev_priv, reg_edid) != *((const u32 *)eld + i)) - return false; - - return true; + return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp); } static void g4x_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 eldv, tmp; - - tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID); - if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL) - eldv = G4X_ELDV_DEVCL_DEVBLC; - else - eldv = G4X_ELDV_DEVCTG; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); /* Invalidate ELD */ - tmp = intel_de_read(dev_priv, G4X_AUD_CNTL_ST); - tmp &= ~eldv; - intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp); + intel_de_rmw(i915, G4X_AUD_CNTL_ST, + G4X_ELD_VALID, 0); + + intel_crtc_wait_for_next_vblank(crtc); + intel_crtc_wait_for_next_vblank(crtc); } static void g4x_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; - const u8 *eld = connector->eld; - u32 eldv; - u32 tmp; - int len, i; + const u32 *eld = (const u32 *)connector->eld; + int eld_buffer_size, len, i; - tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID); - if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL) - eldv = G4X_ELDV_DEVCL_DEVBLC; - else - eldv = G4X_ELDV_DEVCTG; + intel_crtc_wait_for_next_vblank(crtc); - if (intel_eld_uptodate(connector, - G4X_AUD_CNTL_ST, eldv, - G4X_AUD_CNTL_ST, G4X_ELD_ADDR_MASK, - G4X_HDMIW_HDMIEDID)) - return; + intel_de_rmw(i915, G4X_AUD_CNTL_ST, + G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0); - tmp = intel_de_read(dev_priv, G4X_AUD_CNTL_ST); - tmp &= ~(eldv | G4X_ELD_ADDR_MASK); - len = (tmp >> 9) & 0x1f; /* ELD buffer size */ - intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp); + eld_buffer_size = g4x_eld_buffer_size(i915); + len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); - len = min(drm_eld_size(eld) / 4, len); for (i = 0; i < len; i++) - intel_de_write(dev_priv, G4X_HDMIW_HDMIEDID, - *((const u32 *)eld + i)); + intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]); + for (; i < eld_buffer_size; i++) + intel_de_write(i915, G4X_HDMIW_HDMIEDID, 0); - tmp = intel_de_read(dev_priv, G4X_AUD_CNTL_ST); - tmp |= eldv; - intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp); + drm_WARN_ON(&i915->drm, + (intel_de_read(i915, G4X_AUD_CNTL_ST) & G4X_ELD_ADDRESS_MASK) != 0); + + intel_de_rmw(i915, G4X_AUD_CNTL_ST, + 0, G4X_ELD_VALID); } static void hsw_dp_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->display.audio.component; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct i915_audio_component *acomp = i915->display.audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; const struct dp_aud_n_m *nm; @@ -403,12 +374,12 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder, rate = acomp ? acomp->aud_sample_rate[port] : 0; nm = audio_config_dp_get_n_m(crtc_state, rate); if (nm) - drm_dbg_kms(&dev_priv->drm, "using Maud %u, Naud %u\n", nm->m, + drm_dbg_kms(&i915->drm, "using Maud %u, Naud %u\n", nm->m, nm->n); else - drm_dbg_kms(&dev_priv->drm, "using automatic Maud, Naud\n"); + drm_dbg_kms(&i915->drm, "using automatic Maud, Naud\n"); - tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder)); + tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder)); tmp &= ~AUD_CONFIG_N_VALUE_INDEX; tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; tmp &= ~AUD_CONFIG_N_PROG_ENABLE; @@ -420,9 +391,9 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder, tmp |= AUD_CONFIG_N_PROG_ENABLE; } - intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp); + intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp); - tmp = intel_de_read(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); + tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); tmp &= ~AUD_CONFIG_M_MASK; tmp &= ~AUD_M_CTS_M_VALUE_INDEX; tmp &= ~AUD_M_CTS_M_PROG_ENABLE; @@ -433,15 +404,15 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder, tmp |= AUD_M_CTS_M_PROG_ENABLE; } - intel_de_write(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); + intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); } static void hsw_hdmi_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->display.audio.component; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct i915_audio_component *acomp = i915->display.audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; int n, rate; @@ -449,7 +420,7 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder, rate = acomp ? acomp->aud_sample_rate[port] : 0; - tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder)); + tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder)); tmp &= ~AUD_CONFIG_N_VALUE_INDEX; tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; tmp &= ~AUD_CONFIG_N_PROG_ENABLE; @@ -457,25 +428,25 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder, n = audio_config_hdmi_get_n(crtc_state, rate); if (n != 0) { - drm_dbg_kms(&dev_priv->drm, "using N %d\n", n); + drm_dbg_kms(&i915->drm, "using N %d\n", n); tmp &= ~AUD_CONFIG_N_MASK; tmp |= AUD_CONFIG_N(n); tmp |= AUD_CONFIG_N_PROG_ENABLE; } else { - drm_dbg_kms(&dev_priv->drm, "using automatic N\n"); + drm_dbg_kms(&i915->drm, "using automatic N\n"); } - intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp); + intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp); /* * Let's disable "Enable CTS or M Prog bit" * and let HW calculate the value */ - tmp = intel_de_read(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); + tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); tmp &= ~AUD_M_CTS_M_PROG_ENABLE; tmp &= ~AUD_M_CTS_M_VALUE_INDEX; - intel_de_write(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); + intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); } static void @@ -488,33 +459,48 @@ hsw_audio_config_update(struct intel_encoder *encoder, hsw_hdmi_audio_config_update(encoder, crtc_state); } +/* ELD buffer size in dwords */ +static int hsw_eld_buffer_size(struct drm_i915_private *i915, + enum transcoder cpu_transcoder) +{ + u32 tmp; + + tmp = intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)); + + return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp); +} + static void hsw_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - u32 tmp; - mutex_lock(&dev_priv->display.audio.mutex); + mutex_lock(&i915->display.audio.mutex); /* Disable timestamps */ - tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder)); - tmp &= ~AUD_CONFIG_N_VALUE_INDEX; - tmp |= AUD_CONFIG_N_PROG_ENABLE; - tmp &= ~AUD_CONFIG_UPPER_N_MASK; - tmp &= ~AUD_CONFIG_LOWER_N_MASK; - if (intel_crtc_has_dp_encoder(old_crtc_state)) - tmp |= AUD_CONFIG_N_VALUE_INDEX; - intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp); + intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), + AUD_CONFIG_N_VALUE_INDEX | + AUD_CONFIG_UPPER_N_MASK | + AUD_CONFIG_LOWER_N_MASK, + AUD_CONFIG_N_PROG_ENABLE | + (intel_crtc_has_dp_encoder(old_crtc_state) ? + AUD_CONFIG_N_VALUE_INDEX : 0)); /* Invalidate ELD */ - tmp = intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD); - tmp &= ~AUDIO_ELD_VALID(cpu_transcoder); - tmp &= ~AUDIO_OUTPUT_ENABLE(cpu_transcoder); - intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp); + intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + AUDIO_ELD_VALID(cpu_transcoder), 0); + + intel_crtc_wait_for_next_vblank(crtc); + intel_crtc_wait_for_next_vblank(crtc); - mutex_unlock(&dev_priv->display.audio.mutex); + /* Disable audio presence detect */ + intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0); + + mutex_unlock(&i915->display.audio.mutex); } static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, @@ -626,178 +612,190 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder, intel_de_write(i915, AUD_CONFIG_BE, val); } -#undef ROUNDING_FACTOR - static void hsw_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - const u8 *eld = connector->eld; - u32 tmp; - int len, i; + const u32 *eld = (const u32 *)connector->eld; + int eld_buffer_size, len, i; - mutex_lock(&dev_priv->display.audio.mutex); + mutex_lock(&i915->display.audio.mutex); /* Enable Audio WA for 4k DSC usecases */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) enable_audio_dsc_wa(encoder, crtc_state); - /* Enable audio presence detect, invalidate ELD */ - tmp = intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD); - tmp |= AUDIO_OUTPUT_ENABLE(cpu_transcoder); - tmp &= ~AUDIO_ELD_VALID(cpu_transcoder); - intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp); + /* Enable audio presence detect */ + intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + 0, AUDIO_OUTPUT_ENABLE(cpu_transcoder)); - /* - * FIXME: We're supposed to wait for vblank here, but we have vblanks - * disabled during the mode set. The proper fix would be to push the - * rest of the setup into a vblank work item, queued here, but the - * infrastructure is not there yet. - */ + intel_crtc_wait_for_next_vblank(crtc); + + /* Invalidate ELD */ + intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + AUDIO_ELD_VALID(cpu_transcoder), 0); + + /* Reset ELD address */ + intel_de_rmw(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder), + IBX_ELD_ADDRESS_MASK, 0); - /* Reset ELD write address */ - tmp = intel_de_read(dev_priv, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)); - tmp &= ~IBX_ELD_ADDRESS_MASK; - intel_de_write(dev_priv, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder), tmp); + eld_buffer_size = hsw_eld_buffer_size(i915, cpu_transcoder); + len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); - /* Up to 84 bytes of hw ELD buffer */ - len = min(drm_eld_size(eld), 84); - for (i = 0; i < len / 4; i++) - intel_de_write(dev_priv, HSW_AUD_EDID_DATA(cpu_transcoder), - *((const u32 *)eld + i)); + for (i = 0; i < len; i++) + intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), eld[i]); + for (; i < eld_buffer_size; i++) + intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), 0); + + drm_WARN_ON(&i915->drm, + (intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)) & + IBX_ELD_ADDRESS_MASK) != 0); /* ELD valid */ - tmp = intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD); - tmp |= AUDIO_ELD_VALID(cpu_transcoder); - intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp); + intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + 0, AUDIO_ELD_VALID(cpu_transcoder)); /* Enable timestamps */ hsw_audio_config_update(encoder, crtc_state); - mutex_unlock(&dev_priv->display.audio.mutex); + mutex_unlock(&i915->display.audio.mutex); +} + +struct ilk_audio_regs { + i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; +}; + +static void ilk_audio_regs_init(struct drm_i915_private *i915, + enum pipe pipe, + struct ilk_audio_regs *regs) +{ + if (HAS_PCH_IBX(i915)) { + regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); + regs->aud_config = IBX_AUD_CFG(pipe); + regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); + regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; + } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); + regs->aud_config = VLV_AUD_CFG(pipe); + regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe); + regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2; + } else { + regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); + regs->aud_config = CPT_AUD_CFG(pipe); + regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe); + regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; + } +} + +/* ELD buffer size in dwords */ +static int ilk_eld_buffer_size(struct drm_i915_private *i915, + enum pipe pipe) +{ + struct ilk_audio_regs regs; + u32 tmp; + + ilk_audio_regs_init(i915, pipe, ®s); + + tmp = intel_de_read(i915, regs.aud_cntl_st); + + return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp); } static void ilk_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - enum pipe pipe = crtc->pipe; enum port port = encoder->port; - u32 tmp, eldv; - i915_reg_t aud_config, aud_cntrl_st2; + enum pipe pipe = crtc->pipe; + struct ilk_audio_regs regs; - if (drm_WARN_ON(&dev_priv->drm, port == PORT_A)) + if (drm_WARN_ON(&i915->drm, port == PORT_A)) return; - if (HAS_PCH_IBX(dev_priv)) { - aud_config = IBX_AUD_CFG(pipe); - aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - aud_config = VLV_AUD_CFG(pipe); - aud_cntrl_st2 = VLV_AUD_CNTL_ST2; - } else { - aud_config = CPT_AUD_CFG(pipe); - aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; - } + ilk_audio_regs_init(i915, pipe, ®s); - /* Disable timestamps */ - tmp = intel_de_read(dev_priv, aud_config); - tmp &= ~AUD_CONFIG_N_VALUE_INDEX; - tmp |= AUD_CONFIG_N_PROG_ENABLE; - tmp &= ~AUD_CONFIG_UPPER_N_MASK; - tmp &= ~AUD_CONFIG_LOWER_N_MASK; - if (intel_crtc_has_dp_encoder(old_crtc_state)) - tmp |= AUD_CONFIG_N_VALUE_INDEX; - intel_de_write(dev_priv, aud_config, tmp); + mutex_lock(&i915->display.audio.mutex); - eldv = IBX_ELD_VALID(port); + /* Disable timestamps */ + intel_de_rmw(i915, regs.aud_config, + AUD_CONFIG_N_VALUE_INDEX | + AUD_CONFIG_UPPER_N_MASK | + AUD_CONFIG_LOWER_N_MASK, + AUD_CONFIG_N_PROG_ENABLE | + (intel_crtc_has_dp_encoder(old_crtc_state) ? + AUD_CONFIG_N_VALUE_INDEX : 0)); /* Invalidate ELD */ - tmp = intel_de_read(dev_priv, aud_cntrl_st2); - tmp &= ~eldv; - intel_de_write(dev_priv, aud_cntrl_st2, tmp); + intel_de_rmw(i915, regs.aud_cntrl_st2, + IBX_ELD_VALID(port), 0); + + mutex_unlock(&i915->display.audio.mutex); + + intel_crtc_wait_for_next_vblank(crtc); + intel_crtc_wait_for_next_vblank(crtc); } static void ilk_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; - enum pipe pipe = crtc->pipe; + const u32 *eld = (const u32 *)connector->eld; enum port port = encoder->port; - const u8 *eld = connector->eld; - u32 tmp, eldv; - int len, i; - i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; + enum pipe pipe = crtc->pipe; + int eld_buffer_size, len, i; + struct ilk_audio_regs regs; - if (drm_WARN_ON(&dev_priv->drm, port == PORT_A)) + if (drm_WARN_ON(&i915->drm, port == PORT_A)) return; - /* - * FIXME: We're supposed to wait for vblank here, but we have vblanks - * disabled during the mode set. The proper fix would be to push the - * rest of the setup into a vblank work item, queued here, but the - * infrastructure is not there yet. - */ + intel_crtc_wait_for_next_vblank(crtc); - if (HAS_PCH_IBX(dev_priv)) { - hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); - aud_config = IBX_AUD_CFG(pipe); - aud_cntl_st = IBX_AUD_CNTL_ST(pipe); - aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(dev_priv) || - IS_CHERRYVIEW(dev_priv)) { - hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); - aud_config = VLV_AUD_CFG(pipe); - aud_cntl_st = VLV_AUD_CNTL_ST(pipe); - aud_cntrl_st2 = VLV_AUD_CNTL_ST2; - } else { - hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); - aud_config = CPT_AUD_CFG(pipe); - aud_cntl_st = CPT_AUD_CNTL_ST(pipe); - aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; - } + ilk_audio_regs_init(i915, pipe, ®s); - eldv = IBX_ELD_VALID(port); + mutex_lock(&i915->display.audio.mutex); /* Invalidate ELD */ - tmp = intel_de_read(dev_priv, aud_cntrl_st2); - tmp &= ~eldv; - intel_de_write(dev_priv, aud_cntrl_st2, tmp); + intel_de_rmw(i915, regs.aud_cntrl_st2, + IBX_ELD_VALID(port), 0); - /* Reset ELD write address */ - tmp = intel_de_read(dev_priv, aud_cntl_st); - tmp &= ~IBX_ELD_ADDRESS_MASK; - intel_de_write(dev_priv, aud_cntl_st, tmp); + /* Reset ELD address */ + intel_de_rmw(i915, regs.aud_cntl_st, + IBX_ELD_ADDRESS_MASK, 0); - /* Up to 84 bytes of hw ELD buffer */ - len = min(drm_eld_size(eld), 84); - for (i = 0; i < len / 4; i++) - intel_de_write(dev_priv, hdmiw_hdmiedid, - *((const u32 *)eld + i)); + eld_buffer_size = ilk_eld_buffer_size(i915, pipe); + len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); + + for (i = 0; i < len; i++) + intel_de_write(i915, regs.hdmiw_hdmiedid, eld[i]); + for (; i < eld_buffer_size; i++) + intel_de_write(i915, regs.hdmiw_hdmiedid, 0); + + drm_WARN_ON(&i915->drm, + (intel_de_read(i915, regs.aud_cntl_st) & IBX_ELD_ADDRESS_MASK) != 0); /* ELD valid */ - tmp = intel_de_read(dev_priv, aud_cntrl_st2); - tmp |= eldv; - intel_de_write(dev_priv, aud_cntrl_st2, tmp); + intel_de_rmw(i915, regs.aud_cntrl_st2, + 0, IBX_ELD_VALID(port)); /* Enable timestamps */ - tmp = intel_de_read(dev_priv, aud_config); - tmp &= ~AUD_CONFIG_N_VALUE_INDEX; - tmp &= ~AUD_CONFIG_N_PROG_ENABLE; - tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; - if (intel_crtc_has_dp_encoder(crtc_state)) - tmp |= AUD_CONFIG_N_VALUE_INDEX; - else - tmp |= audio_config_hdmi_pixel_clock(crtc_state); - intel_de_write(dev_priv, aud_config, tmp); + intel_de_rmw(i915, regs.aud_config, + AUD_CONFIG_N_VALUE_INDEX | + AUD_CONFIG_N_PROG_ENABLE | + AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, + (intel_crtc_has_dp_encoder(crtc_state) ? + AUD_CONFIG_N_VALUE_INDEX : + audio_config_hdmi_pixel_clock(crtc_state))); + + mutex_unlock(&i915->display.audio.mutex); } /** @@ -813,8 +811,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->display.audio.component; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; const struct drm_display_mode *adjusted_mode = @@ -825,30 +823,30 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, if (!crtc_state->has_audio) return; - drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n", + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n", connector->base.id, connector->name, encoder->base.base.id, encoder->base.name, pipe_name(pipe), drm_eld_size(connector->eld)); /* FIXME precompute the ELD in .compute_config() */ if (!connector->eld[0]) - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "Bogus ELD on [CONNECTOR:%d:%s]\n", connector->base.id, connector->name); connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; - if (dev_priv->display.funcs.audio) - dev_priv->display.funcs.audio->audio_codec_enable(encoder, + if (i915->display.funcs.audio) + i915->display.funcs.audio->audio_codec_enable(encoder, crtc_state, conn_state); - mutex_lock(&dev_priv->display.audio.mutex); + mutex_lock(&i915->display.audio.mutex); encoder->audio_connector = connector; /* referred in audio callbacks */ - dev_priv->display.audio.encoder_map[pipe] = encoder; - mutex_unlock(&dev_priv->display.audio.mutex); + i915->display.audio.encoder_map[pipe] = encoder; + mutex_unlock(&i915->display.audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -859,7 +857,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, (int) port, (int) pipe); } - intel_lpe_audio_notify(dev_priv, pipe, port, connector->eld, + intel_lpe_audio_notify(i915, pipe, port, connector->eld, crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state)); } @@ -877,8 +875,8 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->display.audio.component; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_connector *connector = old_conn_state->connector; enum port port = encoder->port; @@ -887,19 +885,19 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, if (!old_crtc_state->has_audio) return; - drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n", + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n", connector->base.id, connector->name, encoder->base.base.id, encoder->base.name, pipe_name(pipe)); - if (dev_priv->display.funcs.audio) - dev_priv->display.funcs.audio->audio_codec_disable(encoder, + if (i915->display.funcs.audio) + i915->display.funcs.audio->audio_codec_disable(encoder, old_crtc_state, old_conn_state); - mutex_lock(&dev_priv->display.audio.mutex); + mutex_lock(&i915->display.audio.mutex); encoder->audio_connector = NULL; - dev_priv->display.audio.encoder_map[pipe] = NULL; - mutex_unlock(&dev_priv->display.audio.mutex); + i915->display.audio.encoder_map[pipe] = NULL; + mutex_unlock(&i915->display.audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -910,7 +908,7 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, (int) port, (int) pipe); } - intel_lpe_audio_notify(dev_priv, pipe, port, NULL, 0, false); + intel_lpe_audio_notify(i915, pipe, port, NULL, 0, false); } static const struct intel_audio_funcs g4x_audio_funcs = { @@ -930,19 +928,18 @@ static const struct intel_audio_funcs hsw_audio_funcs = { /** * intel_audio_hooks_init - Set up chip specific audio hooks - * @dev_priv: device private + * @i915: device private */ -void intel_audio_hooks_init(struct drm_i915_private *dev_priv) +void intel_audio_hooks_init(struct drm_i915_private *i915) { - if (IS_G4X(dev_priv)) { - dev_priv->display.funcs.audio = &g4x_audio_funcs; - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - dev_priv->display.funcs.audio = &ilk_audio_funcs; - } else if (IS_HASWELL(dev_priv) || DISPLAY_VER(dev_priv) >= 8) { - dev_priv->display.funcs.audio = &hsw_audio_funcs; - } else if (HAS_PCH_SPLIT(dev_priv)) { - dev_priv->display.funcs.audio = &ilk_audio_funcs; - } + if (IS_G4X(i915)) + i915->display.funcs.audio = &g4x_audio_funcs; + else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + i915->display.funcs.audio = &ilk_audio_funcs; + else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) + i915->display.funcs.audio = &hsw_audio_funcs; + else if (HAS_PCH_SPLIT(i915)) + i915->display.funcs.audio = &ilk_audio_funcs; } struct aud_ts_cdclk_m_n { @@ -1000,7 +997,7 @@ static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state, return drm_atomic_commit(&state->base); } -static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv, +static void glk_force_audio_cdclk(struct drm_i915_private *i915, bool enable) { struct drm_modeset_acquire_ctx ctx; @@ -1008,13 +1005,13 @@ static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv, struct intel_crtc *crtc; int ret; - crtc = intel_first_crtc(dev_priv); + crtc = intel_first_crtc(i915); if (!crtc) return; drm_modeset_acquire_init(&ctx, 0); - state = drm_atomic_state_alloc(&dev_priv->drm); - if (drm_WARN_ON(&dev_priv->drm, !state)) + state = drm_atomic_state_alloc(&i915->drm); + if (drm_WARN_ON(&i915->drm, !state)) return; state->acquire_ctx = &ctx; @@ -1028,7 +1025,7 @@ retry: goto retry; } - drm_WARN_ON(&dev_priv->drm, ret); + drm_WARN_ON(&i915->drm, ret); drm_atomic_state_put(state); @@ -1038,30 +1035,30 @@ retry: static unsigned long i915_audio_component_get_power(struct device *kdev) { - struct drm_i915_private *dev_priv = kdev_to_i915(kdev); + struct drm_i915_private *i915 = kdev_to_i915(kdev); intel_wakeref_t ret; /* Catch potential impedance mismatches before they occur! */ BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long)); - ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK); + ret = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK); - if (dev_priv->display.audio.power_refcount++ == 0) { - if (DISPLAY_VER(dev_priv) >= 9) { - intel_de_write(dev_priv, AUD_FREQ_CNTRL, - dev_priv->display.audio.freq_cntrl); - drm_dbg_kms(&dev_priv->drm, + if (i915->display.audio.power_refcount++ == 0) { + if (DISPLAY_VER(i915) >= 9) { + intel_de_write(i915, AUD_FREQ_CNTRL, + i915->display.audio.freq_cntrl); + drm_dbg_kms(&i915->drm, "restored AUD_FREQ_CNTRL to 0x%x\n", - dev_priv->display.audio.freq_cntrl); + i915->display.audio.freq_cntrl); } /* Force CDCLK to 2*BCLK as long as we need audio powered. */ - if (IS_GEMINILAKE(dev_priv)) - glk_force_audio_cdclk(dev_priv, true); + if (IS_GEMINILAKE(i915)) + glk_force_audio_cdclk(i915, true); - if (DISPLAY_VER(dev_priv) >= 10) - intel_de_write(dev_priv, AUD_PIN_BUF_CTL, - (intel_de_read(dev_priv, AUD_PIN_BUF_CTL) | AUD_PIN_BUF_ENABLE)); + if (DISPLAY_VER(i915) >= 10) + intel_de_rmw(i915, AUD_PIN_BUF_CTL, + 0, AUD_PIN_BUF_ENABLE); } return ret; @@ -1070,24 +1067,23 @@ static unsigned long i915_audio_component_get_power(struct device *kdev) static void i915_audio_component_put_power(struct device *kdev, unsigned long cookie) { - struct drm_i915_private *dev_priv = kdev_to_i915(kdev); + struct drm_i915_private *i915 = kdev_to_i915(kdev); /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ - if (--dev_priv->display.audio.power_refcount == 0) - if (IS_GEMINILAKE(dev_priv)) - glk_force_audio_cdclk(dev_priv, false); + if (--i915->display.audio.power_refcount == 0) + if (IS_GEMINILAKE(i915)) + glk_force_audio_cdclk(i915, false); - intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK, cookie); + intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, cookie); } static void i915_audio_component_codec_wake_override(struct device *kdev, bool enable) { - struct drm_i915_private *dev_priv = kdev_to_i915(kdev); + struct drm_i915_private *i915 = kdev_to_i915(kdev); unsigned long cookie; - u32 tmp; - if (DISPLAY_VER(dev_priv) < 9) + if (DISPLAY_VER(i915) < 9) return; cookie = i915_audio_component_get_power(kdev); @@ -1096,15 +1092,13 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, * Enable/disable generating the codec wake signal, overriding the * internal logic to generate the codec wake to controller. */ - tmp = intel_de_read(dev_priv, HSW_AUD_CHICKENBIT); - tmp &= ~SKL_AUD_CODEC_WAKE_SIGNAL; - intel_de_write(dev_priv, HSW_AUD_CHICKENBIT, tmp); + intel_de_rmw(i915, HSW_AUD_CHICKENBIT, + SKL_AUD_CODEC_WAKE_SIGNAL, 0); usleep_range(1000, 1500); if (enable) { - tmp = intel_de_read(dev_priv, HSW_AUD_CHICKENBIT); - tmp |= SKL_AUD_CODEC_WAKE_SIGNAL; - intel_de_write(dev_priv, HSW_AUD_CHICKENBIT, tmp); + intel_de_rmw(i915, HSW_AUD_CHICKENBIT, + 0, SKL_AUD_CODEC_WAKE_SIGNAL); usleep_range(1000, 1500); } @@ -1114,12 +1108,12 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, /* Get CDCLK in kHz */ static int i915_audio_component_get_cdclk_freq(struct device *kdev) { - struct drm_i915_private *dev_priv = kdev_to_i915(kdev); + struct drm_i915_private *i915 = kdev_to_i915(kdev); - if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DDI(dev_priv))) + if (drm_WARN_ON_ONCE(&i915->drm, !HAS_DDI(i915))) return -ENODEV; - return dev_priv->display.cdclk.hw.cdclk; + return i915->display.cdclk.hw.cdclk; } /* @@ -1132,18 +1126,18 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) * will get the right intel_encoder with port matched * Non-MST & (pipe < 0): get the right intel_encoder with port matched */ -static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, - int port, int pipe) +static struct intel_encoder *get_saved_enc(struct drm_i915_private *i915, + int port, int pipe) { struct intel_encoder *encoder; /* MST */ if (pipe >= 0) { - if (drm_WARN_ON(&dev_priv->drm, - pipe >= ARRAY_SIZE(dev_priv->display.audio.encoder_map))) + if (drm_WARN_ON(&i915->drm, + pipe >= ARRAY_SIZE(i915->display.audio.encoder_map))) return NULL; - encoder = dev_priv->display.audio.encoder_map[pipe]; + encoder = i915->display.audio.encoder_map[pipe]; /* * when bootup, audio driver may not know it is * MST or not. So it will poll all the port & pipe @@ -1158,8 +1152,8 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, if (pipe > 0) return NULL; - for_each_pipe(dev_priv, pipe) { - encoder = dev_priv->display.audio.encoder_map[pipe]; + for_each_pipe(i915, pipe) { + encoder = i915->display.audio.encoder_map[pipe]; if (encoder == NULL) continue; @@ -1176,23 +1170,23 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, int pipe, int rate) { - struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct i915_audio_component *acomp = dev_priv->display.audio.component; + struct drm_i915_private *i915 = kdev_to_i915(kdev); + struct i915_audio_component *acomp = i915->display.audio.component; struct intel_encoder *encoder; struct intel_crtc *crtc; unsigned long cookie; int err = 0; - if (!HAS_DDI(dev_priv)) + if (!HAS_DDI(i915)) return 0; cookie = i915_audio_component_get_power(kdev); - mutex_lock(&dev_priv->display.audio.mutex); + mutex_lock(&i915->display.audio.mutex); /* 1. get the pipe */ - encoder = get_saved_enc(dev_priv, port, pipe); + encoder = get_saved_enc(i915, port, pipe); if (!encoder || !encoder->base.crtc) { - drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n", + drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); err = -ENODEV; goto unlock; @@ -1206,7 +1200,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, hsw_audio_config_update(encoder, crtc->config); unlock: - mutex_unlock(&dev_priv->display.audio.mutex); + mutex_unlock(&i915->display.audio.mutex); i915_audio_component_put_power(kdev, cookie); return err; } @@ -1215,18 +1209,18 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, int pipe, bool *enabled, unsigned char *buf, int max_bytes) { - struct drm_i915_private *dev_priv = kdev_to_i915(kdev); + struct drm_i915_private *i915 = kdev_to_i915(kdev); struct intel_encoder *intel_encoder; const u8 *eld; int ret = -EINVAL; - mutex_lock(&dev_priv->display.audio.mutex); + mutex_lock(&i915->display.audio.mutex); - intel_encoder = get_saved_enc(dev_priv, port, pipe); + intel_encoder = get_saved_enc(i915, port, pipe); if (!intel_encoder) { - drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n", + drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); - mutex_unlock(&dev_priv->display.audio.mutex); + mutex_unlock(&i915->display.audio.mutex); return ret; } @@ -1238,7 +1232,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, memcpy(buf, eld, min(max_bytes, ret)); } - mutex_unlock(&dev_priv->display.audio.mutex); + mutex_unlock(&i915->display.audio.mutex); return ret; } @@ -1256,25 +1250,25 @@ static int i915_audio_component_bind(struct device *i915_kdev, struct device *hda_kdev, void *data) { struct i915_audio_component *acomp = data; - struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); + struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); int i; - if (drm_WARN_ON(&dev_priv->drm, acomp->base.ops || acomp->base.dev)) + if (drm_WARN_ON(&i915->drm, acomp->base.ops || acomp->base.dev)) return -EEXIST; - if (drm_WARN_ON(&dev_priv->drm, + if (drm_WARN_ON(&i915->drm, !device_link_add(hda_kdev, i915_kdev, DL_FLAG_STATELESS))) return -ENOMEM; - drm_modeset_lock_all(&dev_priv->drm); + drm_modeset_lock_all(&i915->drm); acomp->base.ops = &i915_audio_component_ops; acomp->base.dev = i915_kdev; BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; - dev_priv->display.audio.component = acomp; - drm_modeset_unlock_all(&dev_priv->drm); + i915->display.audio.component = acomp; + drm_modeset_unlock_all(&i915->drm); return 0; } @@ -1283,19 +1277,19 @@ static void i915_audio_component_unbind(struct device *i915_kdev, struct device *hda_kdev, void *data) { struct i915_audio_component *acomp = data; - struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); + struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); - drm_modeset_lock_all(&dev_priv->drm); + drm_modeset_lock_all(&i915->drm); acomp->base.ops = NULL; acomp->base.dev = NULL; - dev_priv->display.audio.component = NULL; - drm_modeset_unlock_all(&dev_priv->drm); + i915->display.audio.component = NULL; + drm_modeset_unlock_all(&i915->drm); device_link_remove(hda_kdev, i915_kdev); - if (dev_priv->display.audio.power_refcount) - drm_err(&dev_priv->drm, "audio power refcount %d after unbind\n", - dev_priv->display.audio.power_refcount); + if (i915->display.audio.power_refcount) + drm_err(&i915->drm, "audio power refcount %d after unbind\n", + i915->display.audio.power_refcount); } static const struct component_ops i915_audio_component_bind_ops = { @@ -1314,7 +1308,7 @@ static const struct component_ops i915_audio_component_bind_ops = { /** * i915_audio_component_init - initialize and register the audio component - * @dev_priv: i915 device instance + * @i915: i915 device instance * * This will register with the component framework a child component which * will bind dynamically to the snd_hda_intel driver's corresponding master @@ -1328,83 +1322,83 @@ static const struct component_ops i915_audio_component_bind_ops = { * We ignore any error during registration and continue with reduced * functionality (i.e. without HDMI audio). */ -static void i915_audio_component_init(struct drm_i915_private *dev_priv) +static void i915_audio_component_init(struct drm_i915_private *i915) { u32 aud_freq, aud_freq_init; int ret; - ret = component_add_typed(dev_priv->drm.dev, + ret = component_add_typed(i915->drm.dev, &i915_audio_component_bind_ops, I915_COMPONENT_AUDIO); if (ret < 0) { - drm_err(&dev_priv->drm, + drm_err(&i915->drm, "failed to add audio component (%d)\n", ret); /* continue with reduced functionality */ return; } - if (DISPLAY_VER(dev_priv) >= 9) { - aud_freq_init = intel_de_read(dev_priv, AUD_FREQ_CNTRL); + if (DISPLAY_VER(i915) >= 9) { + aud_freq_init = intel_de_read(i915, AUD_FREQ_CNTRL); - if (DISPLAY_VER(dev_priv) >= 12) + if (DISPLAY_VER(i915) >= 12) aud_freq = AUD_FREQ_GEN12; else aud_freq = aud_freq_init; /* use BIOS provided value for TGL and RKL unless it is a known bad value */ - if ((IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) && + if ((IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915)) && aud_freq_init != AUD_FREQ_TGL_BROKEN) aud_freq = aud_freq_init; - drm_dbg_kms(&dev_priv->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", + drm_dbg_kms(&i915->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", aud_freq, aud_freq_init); - dev_priv->display.audio.freq_cntrl = aud_freq; + i915->display.audio.freq_cntrl = aud_freq; } /* init with current cdclk */ - intel_audio_cdclk_change_post(dev_priv); + intel_audio_cdclk_change_post(i915); - dev_priv->display.audio.component_registered = true; + i915->display.audio.component_registered = true; } /** * i915_audio_component_cleanup - deregister the audio component - * @dev_priv: i915 device instance + * @i915: i915 device instance * * Deregisters the audio component, breaking any existing binding to the * corresponding snd_hda_intel driver's master component. */ -static void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) +static void i915_audio_component_cleanup(struct drm_i915_private *i915) { - if (!dev_priv->display.audio.component_registered) + if (!i915->display.audio.component_registered) return; - component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops); - dev_priv->display.audio.component_registered = false; + component_del(i915->drm.dev, &i915_audio_component_bind_ops); + i915->display.audio.component_registered = false; } /** * intel_audio_init() - Initialize the audio driver either using * component framework or using lpe audio bridge - * @dev_priv: the i915 drm device private data + * @i915: the i915 drm device private data * */ -void intel_audio_init(struct drm_i915_private *dev_priv) +void intel_audio_init(struct drm_i915_private *i915) { - if (intel_lpe_audio_init(dev_priv) < 0) - i915_audio_component_init(dev_priv); + if (intel_lpe_audio_init(i915) < 0) + i915_audio_component_init(i915); } /** * intel_audio_deinit() - deinitialize the audio driver - * @dev_priv: the i915 drm device private data + * @i915: the i915 drm device private data * */ -void intel_audio_deinit(struct drm_i915_private *dev_priv) +void intel_audio_deinit(struct drm_i915_private *i915) { - if (dev_priv->display.audio.lpe.platdev != NULL) - intel_lpe_audio_teardown(dev_priv); + if (i915->display.audio.lpe.platdev != NULL) + intel_lpe_audio_teardown(i915); else - i915_audio_component_cleanup(dev_priv); + i915_audio_component_cleanup(i915); } diff --git a/drivers/gpu/drm/i915/display/intel_audio_regs.h b/drivers/gpu/drm/i915/display/intel_audio_regs.h index d1e5844e3484..4f432c2eb543 100644 --- a/drivers/gpu/drm/i915/display/intel_audio_regs.h +++ b/drivers/gpu/drm/i915/display/intel_audio_regs.h @@ -8,16 +8,11 @@ #include "i915_reg_defs.h" -#define G4X_AUD_VID_DID _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x62020) -#define INTEL_AUDIO_DEVCL 0x808629FB -#define INTEL_AUDIO_DEVBLC 0x80862801 -#define INTEL_AUDIO_DEVCTG 0x80862802 - #define G4X_AUD_CNTL_ST _MMIO(0x620B4) -#define G4X_ELDV_DEVCL_DEVBLC (1 << 13) -#define G4X_ELDV_DEVCTG (1 << 14) -#define G4X_ELD_ADDR_MASK (0xf << 5) -#define G4X_ELD_ACK (1 << 4) +#define G4X_ELD_VALID REG_BIT(14) +#define G4X_ELD_BUFFER_SIZE_MASK REG_GENMASK(13, 9) +#define G4X_ELD_ADDRESS_MASK REG_GENMASK(8, 5) +#define G4X_ELD_ACK REG_BIT(4) #define G4X_HDMIW_HDMIEDID _MMIO(0x6210C) #define _IBX_HDMIW_HDMIEDID_A 0xE2050 @@ -28,12 +23,12 @@ #define _IBX_AUD_CNTL_ST_B 0xE21B4 #define IBX_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CNTL_ST_A, \ _IBX_AUD_CNTL_ST_B) -#define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10) -#define IBX_ELD_ADDRESS_MASK (0x1f << 5) -#define IBX_ELD_ACK (1 << 4) +#define IBX_ELD_BUFFER_SIZE_MASK REG_GENMASK(14, 10) +#define IBX_ELD_ADDRESS_MASK REG_GENMASK(9, 5) +#define IBX_ELD_ACK REG_BIT(4) #define IBX_AUD_CNTL_ST2 _MMIO(0xE20C0) -#define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4)) -#define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4)) +#define IBX_CP_READY(port) REG_BIT(((port) - 1) * 4 + 1) +#define IBX_ELD_VALID(port) REG_BIT(((port) - 1) * 4 + 0) #define _CPT_HDMIW_HDMIEDID_A 0xE5050 #define _CPT_HDMIW_HDMIEDID_B 0xE5150 @@ -60,34 +55,30 @@ #define _VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000) #define _VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100) #define VLV_AUD_CFG(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CONFIG_A, _VLV_AUD_CONFIG_B) - -#define AUD_CONFIG_N_VALUE_INDEX (1 << 29) -#define AUD_CONFIG_N_PROG_ENABLE (1 << 28) -#define AUD_CONFIG_UPPER_N_SHIFT 20 -#define AUD_CONFIG_UPPER_N_MASK (0xff << 20) -#define AUD_CONFIG_LOWER_N_SHIFT 4 -#define AUD_CONFIG_LOWER_N_MASK (0xfff << 4) -#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK) -#define AUD_CONFIG_N(n) \ - (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \ - (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT)) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 (1 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 (2 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 (3 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 (4 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 (5 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 (6 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 (7 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 (8 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 (9 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 (10 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 (11 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 (12 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 (13 << 16) -#define AUD_CONFIG_DISABLE_NCTS (1 << 3) +#define AUD_CONFIG_N_VALUE_INDEX REG_BIT(29) +#define AUD_CONFIG_N_PROG_ENABLE REG_BIT(28) +#define AUD_CONFIG_UPPER_N_MASK REG_GENMASK(27, 20) +#define AUD_CONFIG_LOWER_N_MASK REG_GENMASK(15, 4) +#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | \ + AUD_CONFIG_LOWER_N_MASK) +#define AUD_CONFIG_N(n) (REG_FIELD_PREP(AUD_CONFIG_UPPER_N_MASK, (n) >> 12) | \ + REG_FIELD_PREP(AUD_CONFIG_LOWER_N_MASK, (n) & 0xfff)) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK REG_GENMASK(19, 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 0) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 1) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 2) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 3) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 4) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 5) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 6) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 7) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 8) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 9) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 10) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 11) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 12) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 13) +#define AUD_CONFIG_DISABLE_NCTS REG_BIT(3) #define _HSW_AUD_CONFIG_A 0x65000 #define _HSW_AUD_CONFIG_B 0x65100 @@ -100,9 +91,9 @@ #define _HSW_AUD_M_CTS_ENABLE_A 0x65028 #define _HSW_AUD_M_CTS_ENABLE_B 0x65128 #define HSW_AUD_M_CTS_ENABLE(trans) _MMIO_TRANS(trans, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B) -#define AUD_M_CTS_M_VALUE_INDEX (1 << 21) -#define AUD_M_CTS_M_PROG_ENABLE (1 << 20) -#define AUD_CONFIG_M_MASK 0xfffff +#define AUD_M_CTS_M_VALUE_INDEX REG_BIT(21) +#define AUD_M_CTS_M_PROG_ENABLE REG_BIT(20) +#define AUD_CONFIG_M_MASK REG_GENMASK(19, 0) #define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 #define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 @@ -130,11 +121,11 @@ #define AUD_DP_2DOT0_CTRL(trans) _MMIO_TRANS(trans, _AUD_TCA_DP_2DOT0_CTRL, _AUD_TCB_DP_2DOT0_CTRL) #define AUD_ENABLE_SDP_SPLIT REG_BIT(31) -#define HSW_AUD_CHICKENBIT _MMIO(0x65f10) -#define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) +#define HSW_AUD_CHICKENBIT _MMIO(0x65f10) +#define SKL_AUD_CODEC_WAKE_SIGNAL REG_BIT(15) #define AUD_FREQ_CNTRL _MMIO(0x65900) -#define AUD_PIN_BUF_CTL _MMIO(0x48414) +#define AUD_PIN_BUF_CTL _MMIO(0x48414) #define AUD_PIN_BUF_ENABLE REG_BIT(31) #define AUD_TS_CDCLK_M _MMIO(0x65ea0) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 28bdb936cd1f..c2987f2c2b2e 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2188,7 +2188,7 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) const u8 *ddc_pin_map; int n_entries; - if (IS_ALDERLAKE_P(i915)) { + if (HAS_PCH_MTP(i915) || IS_ALDERLAKE_P(i915)) { ddc_pin_map = adlp_ddc_pin_map; n_entries = ARRAY_SIZE(adlp_ddc_pin_map); } else if (IS_ALDERLAKE_S(i915)) { @@ -2676,6 +2676,14 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata, drm_dbg_kms(&i915->drm, "Port %c VBT DP max link rate: %d\n", port_name(port), dp_max_link_rate); + + /* + * FIXME need to implement support for VBT + * vswing/preemph tables should this ever trigger. + */ + drm_WARN(&i915->drm, child->use_vbt_vswing, + "Port %c asks to use VBT vswing/preemph tables\n", + port_name(port)); } static void parse_ddi_port(struct intel_bios_encoder_data *devdata) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index ed05070b7307..eada931cb1c8 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1220,11 +1220,6 @@ static void skl_cdclk_uninit_hw(struct drm_i915_private *dev_priv) skl_set_cdclk(dev_priv, &cdclk_config, INVALID_PIPE); } -static bool has_cdclk_squasher(struct drm_i915_private *i915) -{ - return IS_DG2(i915); -} - struct intel_cdclk_vals { u32 cdclk; u16 refclk; @@ -1520,7 +1515,7 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv, return; } - if (has_cdclk_squasher(dev_priv)) + if (HAS_CDCLK_SQUASH(dev_priv)) squash_ctl = intel_de_read(dev_priv, CDCLK_SQUASH_CTL); if (squash_ctl & CDCLK_SQUASH_ENABLE) { @@ -1689,6 +1684,38 @@ static u32 cdclk_squash_waveform(struct drm_i915_private *dev_priv, return 0xffff; } +static void icl_cdclk_pll_update(struct drm_i915_private *i915, int vco) +{ + if (i915->display.cdclk.hw.vco != 0 && + i915->display.cdclk.hw.vco != vco) + icl_cdclk_pll_disable(i915); + + if (i915->display.cdclk.hw.vco != vco) + icl_cdclk_pll_enable(i915, vco); +} + +static void bxt_cdclk_pll_update(struct drm_i915_private *i915, int vco) +{ + if (i915->display.cdclk.hw.vco != 0 && + i915->display.cdclk.hw.vco != vco) + bxt_de_pll_disable(i915); + + if (i915->display.cdclk.hw.vco != vco) + bxt_de_pll_enable(i915, vco); +} + +static void dg2_cdclk_squash_program(struct drm_i915_private *i915, + u16 waveform) +{ + u32 squash_ctl = 0; + + if (waveform) + squash_ctl = CDCLK_SQUASH_ENABLE | + CDCLK_SQUASH_WINDOW_SIZE(0xf) | waveform; + + intel_de_write(i915, CDCLK_SQUASH_CTL, squash_ctl); +} + static void bxt_set_cdclk(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) @@ -1724,21 +1751,10 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0) { if (dev_priv->display.cdclk.hw.vco != vco) adlp_cdclk_pll_crawl(dev_priv, vco); - } else if (DISPLAY_VER(dev_priv) >= 11) { - if (dev_priv->display.cdclk.hw.vco != 0 && - dev_priv->display.cdclk.hw.vco != vco) - icl_cdclk_pll_disable(dev_priv); - - if (dev_priv->display.cdclk.hw.vco != vco) - icl_cdclk_pll_enable(dev_priv, vco); - } else { - if (dev_priv->display.cdclk.hw.vco != 0 && - dev_priv->display.cdclk.hw.vco != vco) - bxt_de_pll_disable(dev_priv); - - if (dev_priv->display.cdclk.hw.vco != vco) - bxt_de_pll_enable(dev_priv, vco); - } + } else if (DISPLAY_VER(dev_priv) >= 11) + icl_cdclk_pll_update(dev_priv, vco); + else + bxt_cdclk_pll_update(dev_priv, vco); waveform = cdclk_squash_waveform(dev_priv, cdclk); @@ -1747,15 +1763,8 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, else clock = cdclk; - if (has_cdclk_squasher(dev_priv)) { - u32 squash_ctl = 0; - - if (waveform) - squash_ctl = CDCLK_SQUASH_ENABLE | - CDCLK_SQUASH_WINDOW_SIZE(0xf) | waveform; - - intel_de_write(dev_priv, CDCLK_SQUASH_CTL, squash_ctl); - } + if (HAS_CDCLK_SQUASH(dev_priv)) + dg2_cdclk_squash_program(dev_priv, waveform); val = bxt_cdclk_cd2x_div_sel(dev_priv, clock, vco) | bxt_cdclk_cd2x_pipe(dev_priv, pipe) | @@ -1845,7 +1854,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) expected = skl_cdclk_decimal(cdclk); /* Figure out what CD2X divider we should be using for this cdclk */ - if (has_cdclk_squasher(dev_priv)) + if (HAS_CDCLK_SQUASH(dev_priv)) clock = dev_priv->display.cdclk.hw.vco / 2; else clock = dev_priv->display.cdclk.hw.cdclk; @@ -1976,7 +1985,7 @@ static bool intel_cdclk_can_squash(struct drm_i915_private *dev_priv, * the moment all platforms with squasher use a fixed cd2x * divider. */ - if (!has_cdclk_squasher(dev_priv)) + if (!HAS_CDCLK_SQUASH(dev_priv)) return false; return a->cdclk != b->cdclk && @@ -2028,7 +2037,7 @@ static bool intel_cdclk_can_cd2x_update(struct drm_i915_private *dev_priv, * the moment all platforms with squasher use a fixed cd2x * divider. */ - if (has_cdclk_squasher(dev_priv)) + if (HAS_CDCLK_SQUASH(dev_priv)) return false; return a->cdclk != b->cdclk && @@ -2464,10 +2473,6 @@ static int bdw_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) if (min_cdclk < 0) return min_cdclk; - /* - * FIXME should also account for plane ratio - * once 64bpp pixel formats are supported. - */ cdclk = bdw_calc_cdclk(min_cdclk); cdclk_state->logical.cdclk = cdclk; @@ -2534,10 +2539,6 @@ static int skl_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) vco = skl_dpll0_vco(cdclk_state); - /* - * FIXME should also account for plane ratio - * once 64bpp pixel formats are supported. - */ cdclk = skl_calc_cdclk(min_cdclk, vco); cdclk_state->logical.vco = vco; @@ -2762,12 +2763,12 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) &old_cdclk_state->actual, &new_cdclk_state->actual)) { drm_dbg_kms(&dev_priv->drm, - "Can change cdclk via squasher\n"); + "Can change cdclk via squashing\n"); } else if (intel_cdclk_can_crawl(dev_priv, &old_cdclk_state->actual, &new_cdclk_state->actual)) { drm_dbg_kms(&dev_priv->drm, - "Can change cdclk via crawl\n"); + "Can change cdclk via crawling\n"); } else if (pipe != INVALID_PIPE) { new_cdclk_state->pipe = pipe; @@ -2777,7 +2778,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) } else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual, &new_cdclk_state->actual)) { /* All pipes must be switched off while we change the cdclk. */ - ret = intel_modeset_all_pipes(state); + ret = intel_modeset_all_pipes(state, "CDCLK change"); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 6bda4274eae9..4bb113c39f4b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -25,9 +25,7 @@ #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" -#include "intel_dpll.h" #include "intel_dsb.h" -#include "vlv_dsi_pll.h" struct intel_color_funcs { int (*color_check)(struct intel_crtc_state *crtc_state); @@ -559,6 +557,32 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state) crtc_state->csc_mode); } +static struct drm_property_blob * +create_linear_lut(struct drm_i915_private *i915, int lut_size) +{ + struct drm_property_blob *blob; + struct drm_color_lut *lut; + int i; + + blob = drm_property_create_blob(&i915->drm, + sizeof(struct drm_color_lut) * lut_size, + NULL); + if (IS_ERR(blob)) + return blob; + + lut = blob->data; + + for (i = 0; i < lut_size; i++) { + u16 val = 0xffff * i / (lut_size - 1); + + lut[i].red = val; + lut[i].green = val; + lut[i].blue = val; + } + + return blob; +} + static void i9xx_load_lut_8(struct intel_crtc *crtc, const struct drm_property_blob *blob) { @@ -580,12 +604,9 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc, static void i9xx_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - assert_pll_enabled(dev_priv, crtc->pipe); - - i9xx_load_lut_8(crtc, gamma_lut); + i9xx_load_lut_8(crtc, post_csc_lut); } static void i965_load_lut_10p6(struct intel_crtc *crtc, @@ -611,18 +632,12 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc, static void i965_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; - - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) - assert_dsi_pll_enabled(dev_priv); - else - assert_pll_enabled(dev_priv, crtc->pipe); + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) - i9xx_load_lut_8(crtc, gamma_lut); + i9xx_load_lut_8(crtc, post_csc_lut); else - i965_load_lut_10p6(crtc, gamma_lut); + i965_load_lut_10p6(crtc, post_csc_lut); } static void ilk_load_lut_8(struct intel_crtc *crtc, @@ -659,14 +674,16 @@ static void ilk_load_lut_10(struct intel_crtc *crtc, static void ilk_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; + const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; + const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, gamma_lut); + ilk_load_lut_8(crtc, blob); break; case GAMMA_MODE_MODE_10BIT: - ilk_load_lut_10(crtc, gamma_lut); + ilk_load_lut_10(crtc, blob); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -773,19 +790,19 @@ static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) static void ivb_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; - const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; - const struct drm_property_blob *blob = gamma_lut ?: degamma_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; + const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; + const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: ilk_load_lut_8(crtc, blob); break; case GAMMA_MODE_MODE_SPLIT: - ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE | + ivb_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); - ivb_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE | + ivb_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: @@ -802,19 +819,19 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) static void bdw_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; - const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; - const struct drm_property_blob *blob = gamma_lut ?: degamma_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; + const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; + const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: ilk_load_lut_8(crtc, blob); break; case GAMMA_MODE_MODE_SPLIT: - bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE | + bdw_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); - bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE | + bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: @@ -837,13 +854,14 @@ static int glk_degamma_lut_size(struct drm_i915_private *i915) return 35; } -static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) +static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct drm_color_lut *lut = blob->data; + int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; - int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; - const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data; /* * When setting the auto-increment bit, the hardware seems to @@ -879,59 +897,21 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); } -static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; - - /* - * When setting the auto-increment bit, the hardware seems to - * ignore the index bits, so we need to reset it to index 0 - * separately. - */ - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT); - - for (i = 0; i < lut_size; i++) { - u32 v = (i << 16) / (lut_size - 1); - - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), v); - } - - /* Clamp values > 1.0. */ - while (i++ < 35) - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16); - - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); -} - static void glk_load_luts(const struct intel_crtc_state *crtc_state) { - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - /* - * On GLK+ both pipe CSC and degamma LUT are controlled - * by csc_enable. Hence for the cases where the CSC is - * needed but degamma LUT is not we need to load a - * linear degamma LUT. In fact we'll just always load - * the degama LUT so that we don't have to reload - * it every time the pipe CSC is being enabled. - */ - if (crtc_state->hw.degamma_lut) - glk_load_degamma_lut(crtc_state); - else - glk_load_degamma_lut_linear(crtc_state); + if (pre_csc_lut) + glk_load_degamma_lut(crtc_state, pre_csc_lut); switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, gamma_lut); + ilk_load_lut_8(crtc, post_csc_lut); break; case GAMMA_MODE_MODE_10BIT: - bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0)); + bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); break; default: @@ -971,7 +951,7 @@ static void icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; + const struct drm_property_blob *blob = crtc_state->post_csc_lut; const struct drm_color_lut *lut = blob->data; enum pipe pipe = crtc->pipe; int i; @@ -1000,7 +980,7 @@ static void icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; + const struct drm_property_blob *blob = crtc_state->post_csc_lut; const struct drm_color_lut *lut = blob->data; const struct drm_color_lut *entry; enum pipe pipe = crtc->pipe; @@ -1054,22 +1034,23 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) static void icl_load_luts(const struct intel_crtc_state *crtc_state) { - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (crtc_state->hw.degamma_lut) - glk_load_degamma_lut(crtc_state); + if (pre_csc_lut) + glk_load_degamma_lut(crtc_state, pre_csc_lut); switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, gamma_lut); + ilk_load_lut_8(crtc, post_csc_lut); break; case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: icl_program_gamma_superfine_segment(crtc_state); icl_program_gamma_multi_segment(crtc_state); break; case GAMMA_MODE_MODE_10BIT: - bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0)); + bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); break; default: @@ -1145,18 +1126,18 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; - const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; + const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *ctm = crtc_state->hw.ctm; if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) chv_load_cgm_csc(crtc, ctm); if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA) - chv_load_cgm_degamma(crtc, degamma_lut); + chv_load_cgm_degamma(crtc, pre_csc_lut); if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) - chv_load_cgm_gamma(crtc, gamma_lut); + chv_load_cgm_gamma(crtc, post_csc_lut); else i965_load_luts(crtc_state); @@ -1194,8 +1175,8 @@ static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); - return !old_crtc_state->hw.gamma_lut && - !old_crtc_state->hw.degamma_lut; + return !old_crtc_state->post_csc_lut && + !old_crtc_state->pre_csc_lut; } static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) @@ -1214,25 +1195,7 @@ static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode) return false; - return !old_crtc_state->hw.gamma_lut; -} - -static bool glk_can_preload_luts(const struct intel_crtc_state *new_crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->uapi.state); - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - - /* - * The hardware degamma is active whenever the pipe - * CSC is active. Thus even if the old state has no - * software degamma we need to avoid clobbering the - * linear hardware degamma mid scanout. - */ - return !old_crtc_state->csc_enable && - !old_crtc_state->hw.gamma_lut; + return !old_crtc_state->post_csc_lut; } int intel_color_check(struct intel_crtc_state *crtc_state) @@ -1295,6 +1258,10 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) return PTR_ERR(plane_state); new_crtc_state->update_planes |= BIT(plane->id); + + /* plane control register changes blocked by CxSR */ + if (HAS_GMCH(dev_priv)) + new_crtc_state->disable_cxsr = true; } return 0; @@ -1361,6 +1328,40 @@ static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state) return GAMMA_MODE_MODE_10BIT; /* i965+ only */ } +void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + /* make sure {pre,post}_csc_lut were correctly assigned */ + if (DISPLAY_VER(i915) >= 11 || HAS_GMCH(i915)) { + drm_WARN_ON(&i915->drm, + crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut); + drm_WARN_ON(&i915->drm, + crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); + } else if (DISPLAY_VER(i915) == 10) { + drm_WARN_ON(&i915->drm, + crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && + crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut); + drm_WARN_ON(&i915->drm, + crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); + } else { + drm_WARN_ON(&i915->drm, + crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && + crtc_state->pre_csc_lut != crtc_state->hw.gamma_lut); + drm_WARN_ON(&i915->drm, + crtc_state->post_csc_lut != crtc_state->hw.degamma_lut && + crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); + } +} + +static void intel_assign_luts(struct intel_crtc_state *crtc_state) +{ + drm_property_replace_blob(&crtc_state->pre_csc_lut, + crtc_state->hw.degamma_lut); + drm_property_replace_blob(&crtc_state->post_csc_lut, + crtc_state->hw.gamma_lut); +} + static int i9xx_color_check(struct intel_crtc_state *crtc_state) { int ret; @@ -1379,6 +1380,8 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + intel_assign_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); return 0; @@ -1433,6 +1436,8 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + intel_assign_luts(crtc_state); + crtc_state->preload_luts = chv_can_preload_luts(crtc_state); return 0; @@ -1458,10 +1463,29 @@ static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state) if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) return CSC_BLACK_SCREEN_OFFSET; + if (crtc_state->hw.degamma_lut) + return CSC_MODE_YUV_TO_RGB; + return CSC_MODE_YUV_TO_RGB | CSC_POSITION_BEFORE_GAMMA; } +static void ilk_assign_luts(struct intel_crtc_state *crtc_state) +{ + if (crtc_state->hw.degamma_lut || + crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) { + drm_property_replace_blob(&crtc_state->pre_csc_lut, + crtc_state->hw.degamma_lut); + drm_property_replace_blob(&crtc_state->post_csc_lut, + crtc_state->hw.gamma_lut); + } else { + drm_property_replace_blob(&crtc_state->pre_csc_lut, + crtc_state->hw.gamma_lut); + drm_property_replace_blob(&crtc_state->post_csc_lut, + NULL); + } +} + static int ilk_color_check(struct intel_crtc_state *crtc_state) { int ret; @@ -1489,6 +1513,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + ilk_assign_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); return 0; @@ -1556,6 +1582,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + ilk_assign_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); return 0; @@ -1570,6 +1598,23 @@ static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state) return GAMMA_MODE_MODE_10BIT; } +static void glk_assign_luts(struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + intel_assign_luts(crtc_state); + + /* + * On GLK+ both pipe CSC and degamma LUT are controlled + * by csc_enable. Hence for the cases where the CSC is + * needed but degamma LUT is not we need to load a + * linear degamma LUT. + */ + if (crtc_state->csc_enable && !crtc_state->pre_csc_lut) + drm_property_replace_blob(&crtc_state->pre_csc_lut, + i915->display.color.glk_linear_degamma_lut); +} + static int glk_color_check(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); @@ -1604,7 +1649,9 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; - crtc_state->preload_luts = glk_can_preload_luts(crtc_state); + glk_assign_luts(crtc_state); + + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); return 0; } @@ -1664,6 +1711,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) crtc_state->csc_mode = icl_csc_mode(crtc_state); + intel_assign_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); return 0; @@ -1869,7 +1918,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state) if (!crtc_state->gamma_enable) return; - crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc); + crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); } static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) @@ -1910,9 +1959,9 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) return; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) - crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc); + crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); else - crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc); + crtc_state->post_csc_lut = i965_read_lut_10p6(crtc); } static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) @@ -1946,7 +1995,7 @@ static void chv_read_luts(struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) - crtc_state->hw.gamma_lut = chv_read_cgm_gamma(crtc); + crtc_state->post_csc_lut = chv_read_cgm_gamma(crtc); else i965_read_luts(crtc_state); } @@ -2013,10 +2062,10 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state) switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc); + crtc_state->post_csc_lut = ilk_read_lut_8(crtc); break; case GAMMA_MODE_MODE_10BIT: - crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc); + crtc_state->post_csc_lut = ilk_read_lut_10(crtc); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -2068,10 +2117,10 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state) switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc); + crtc_state->post_csc_lut = ilk_read_lut_8(crtc); break; case GAMMA_MODE_MODE_10BIT: - crtc_state->hw.gamma_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); + crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -2126,13 +2175,13 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { case GAMMA_MODE_MODE_8BIT: - crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc); + crtc_state->post_csc_lut = ilk_read_lut_8(crtc); break; case GAMMA_MODE_MODE_10BIT: - crtc_state->hw.gamma_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); + crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); break; case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: - crtc_state->hw.gamma_lut = icl_read_lut_multi_segment(crtc); + crtc_state->post_csc_lut = icl_read_lut_multi_segment(crtc); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -2217,41 +2266,58 @@ static const struct intel_color_funcs ilk_color_funcs = { .read_luts = ilk_read_luts, }; -void intel_color_init(struct intel_crtc *crtc) +void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool has_ctm = INTEL_INFO(dev_priv)->display.color.degamma_lut_size != 0; drm_mode_crtc_set_gamma_size(&crtc->base, 256); - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) { - dev_priv->display.funcs.color = &chv_color_funcs; - } else if (DISPLAY_VER(dev_priv) >= 4) { - dev_priv->display.funcs.color = &i965_color_funcs; - } else { - dev_priv->display.funcs.color = &i9xx_color_funcs; - } - } else { - if (DISPLAY_VER(dev_priv) >= 11) - dev_priv->display.funcs.color = &icl_color_funcs; - else if (DISPLAY_VER(dev_priv) == 10) - dev_priv->display.funcs.color = &glk_color_funcs; - else if (DISPLAY_VER(dev_priv) == 9) - dev_priv->display.funcs.color = &skl_color_funcs; - else if (DISPLAY_VER(dev_priv) == 8) - dev_priv->display.funcs.color = &bdw_color_funcs; - else if (DISPLAY_VER(dev_priv) == 7) { - if (IS_HASWELL(dev_priv)) - dev_priv->display.funcs.color = &hsw_color_funcs; - else - dev_priv->display.funcs.color = &ivb_color_funcs; - } else - dev_priv->display.funcs.color = &ilk_color_funcs; - } - drm_crtc_enable_color_mgmt(&crtc->base, INTEL_INFO(dev_priv)->display.color.degamma_lut_size, has_ctm, INTEL_INFO(dev_priv)->display.color.gamma_lut_size); } + +int intel_color_init(struct drm_i915_private *i915) +{ + struct drm_property_blob *blob; + + if (DISPLAY_VER(i915) != 10) + return 0; + + blob = create_linear_lut(i915, INTEL_INFO(i915)->display.color.degamma_lut_size); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + i915->display.color.glk_linear_degamma_lut = blob; + + return 0; +} + +void intel_color_init_hooks(struct drm_i915_private *i915) +{ + if (HAS_GMCH(i915)) { + if (IS_CHERRYVIEW(i915)) + i915->display.funcs.color = &chv_color_funcs; + else if (DISPLAY_VER(i915) >= 4) + i915->display.funcs.color = &i965_color_funcs; + else + i915->display.funcs.color = &i9xx_color_funcs; + } else { + if (DISPLAY_VER(i915) >= 11) + i915->display.funcs.color = &icl_color_funcs; + else if (DISPLAY_VER(i915) == 10) + i915->display.funcs.color = &glk_color_funcs; + else if (DISPLAY_VER(i915) == 9) + i915->display.funcs.color = &skl_color_funcs; + else if (DISPLAY_VER(i915) == 8) + i915->display.funcs.color = &bdw_color_funcs; + else if (IS_HASWELL(i915)) + i915->display.funcs.color = &hsw_color_funcs; + else if (DISPLAY_VER(i915) == 7) + i915->display.funcs.color = &ivb_color_funcs; + else + i915->display.funcs.color = &ilk_color_funcs; + } +} diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index fd873425e082..2a5ada67774d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -10,9 +10,12 @@ struct intel_crtc_state; struct intel_crtc; +struct drm_i915_private; struct drm_property_blob; -void intel_color_init(struct intel_crtc *crtc); +void intel_color_init_hooks(struct drm_i915_private *i915); +int intel_color_init(struct drm_i915_private *i915); +void intel_color_crtc_init(struct intel_crtc *crtc); int intel_color_check(struct intel_crtc_state *crtc_state); void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state); void intel_color_commit_arm(const struct intel_crtc_state *crtc_state); @@ -22,5 +25,6 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat bool intel_color_lut_equal(struct drm_property_blob *blob1, struct drm_property_blob *blob2, u32 gamma_mode, u32 bit_precision); +void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 64890f39c3cc..71d7aece1dc6 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -53,7 +53,6 @@ static const struct icl_procmon { static const struct icl_procmon * icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy) { - const struct icl_procmon *procmon; u32 val; val = intel_de_read(dev_priv, ICL_PORT_COMP_DW3(phy)); @@ -62,23 +61,16 @@ icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy) MISSING_CASE(val); fallthrough; case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0: - procmon = &icl_procmon_values[PROCMON_0_85V_DOT_0]; - break; + return &icl_procmon_values[PROCMON_0_85V_DOT_0]; case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0: - procmon = &icl_procmon_values[PROCMON_0_95V_DOT_0]; - break; + return &icl_procmon_values[PROCMON_0_95V_DOT_0]; case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1: - procmon = &icl_procmon_values[PROCMON_0_95V_DOT_1]; - break; + return &icl_procmon_values[PROCMON_0_95V_DOT_1]; case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0: - procmon = &icl_procmon_values[PROCMON_1_05V_DOT_0]; - break; + return &icl_procmon_values[PROCMON_1_05V_DOT_0]; case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1: - procmon = &icl_procmon_values[PROCMON_1_05V_DOT_1]; - break; + return &icl_procmon_values[PROCMON_1_05V_DOT_1]; } - - return procmon; } static void icl_set_procmon_ref_values(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index 6d5cbeb8df4d..6205ddd3ded0 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -293,3 +293,21 @@ intel_attach_dp_colorspace_property(struct drm_connector *connector) if (!drm_mode_create_dp_colorspace_property(connector)) drm_connector_attach_colorspace_property(connector); } + +void +intel_attach_scaling_mode_property(struct drm_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->dev); + u32 scaling_modes; + + scaling_modes = BIT(DRM_MODE_SCALE_ASPECT) | + BIT(DRM_MODE_SCALE_FULLSCREEN); + + /* On GMCH platforms borders are only possible on the LVDS port */ + if (!HAS_GMCH(i915) || connector->connector_type == DRM_MODE_CONNECTOR_LVDS) + scaling_modes |= BIT(DRM_MODE_SCALE_CENTER); + + drm_connector_attach_scaling_mode_property(connector, scaling_modes); + + connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT; +} diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h index 661a37a3c6d8..7d7b588d2286 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.h +++ b/drivers/gpu/drm/i915/display/intel_connector.h @@ -32,5 +32,6 @@ void intel_attach_broadcast_rgb_property(struct drm_connector *connector); void intel_attach_aspect_ratio_property(struct drm_connector *connector); void intel_attach_hdmi_colorspace_property(struct drm_connector *connector); void intel_attach_dp_colorspace_property(struct drm_connector *connector); +void intel_attach_scaling_mode_property(struct drm_connector *connector); #endif /* __INTEL_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 4a8ff2f97608..94d0a5e1dd03 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -1044,17 +1044,14 @@ void intel_crt_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, &crt->base); crt->base.type = INTEL_OUTPUT_ANALOG; - crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI); + crt->base.cloneable = BIT(INTEL_OUTPUT_DVO) | BIT(INTEL_OUTPUT_HDMI); if (IS_I830(dev_priv)) crt->base.pipe_mask = BIT(PIPE_A); else crt->base.pipe_mask = ~0; - if (DISPLAY_VER(dev_priv) == 2) - connector->interlace_allowed = 0; - else - connector->interlace_allowed = 1; - connector->doublescan_allowed = 0; + if (DISPLAY_VER(dev_priv) != 2) + connector->interlace_allowed = true; crt->adpa_reg = adpa_reg; diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 6792a9056f46..037fc140b585 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -365,9 +365,8 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) BIT(DRM_SCALING_FILTER_DEFAULT) | BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); - intel_color_init(crtc); - - intel_crtc_drrs_init(crtc); + intel_color_crtc_init(crtc); + intel_drrs_crtc_init(crtc); intel_crtc_crc_init(crtc); cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE); @@ -387,8 +386,7 @@ static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_sta return crtc_state->hw.active && !intel_crtc_needs_modeset(crtc_state) && !crtc_state->preload_luts && - (crtc_state->uapi.color_mgmt_changed || - crtc_state->update_pipe); + intel_crtc_needs_color_update(crtc_state); } static void intel_crtc_vblank_work(struct kthread_work *base) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index e9212f69c360..e3273fe8ddac 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -298,11 +298,13 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, pipe_config->csc_mode, pipe_config->gamma_mode, pipe_config->gamma_enable, pipe_config->csc_enable); - drm_dbg_kms(&i915->drm, "degamma lut: %d entries, gamma lut: %d entries\n", - pipe_config->hw.degamma_lut ? - drm_color_lut_size(pipe_config->hw.degamma_lut) : 0, - pipe_config->hw.gamma_lut ? - drm_color_lut_size(pipe_config->hw.gamma_lut) : 0); + drm_dbg_kms(&i915->drm, "pre csc lut: %s%d entries, post csc lut: %d entries\n", + pipe_config->pre_csc_lut && pipe_config->pre_csc_lut == + i915->display.color.glk_linear_degamma_lut ? "(linear) " : "", + pipe_config->pre_csc_lut ? + drm_color_lut_size(pipe_config->pre_csc_lut) : 0, + pipe_config->post_csc_lut ? + drm_color_lut_size(pipe_config->post_csc_lut) : 0); dump_planes: if (!state) diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 87899e89b3a7..96422c98656a 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -631,8 +631,10 @@ intel_legacy_cursor_update(struct drm_plane *_plane, * * FIXME bigjoiner fastpath would be good */ - if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) || - crtc_state->update_pipe || crtc_state->bigjoiner_pipes) + if (!crtc_state->hw.active || + intel_crtc_needs_modeset(crtc_state) || + intel_crtc_needs_fastset(crtc_state) || + crtc_state->bigjoiner_pipes) goto slow; /* diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index da8472cdc135..e95bde5cf060 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -43,6 +43,8 @@ #include "intel_de.h" #include "intel_display_power.h" #include "intel_display_types.h" +#include "intel_dkl_phy.h" +#include "intel_dkl_phy_regs.h" #include "intel_dp.h" #include "intel_dp_link_training.h" #include "intel_dp_mst.h" @@ -55,13 +57,13 @@ #include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_lspcon.h" +#include "intel_mg_phy_regs.h" #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" #include "intel_snps_phy.h" #include "intel_sprite.h" #include "intel_tc.h" -#include "intel_tc_phy_regs.h" #include "intel_vdsc.h" #include "intel_vrr.h" #include "skl_scaler.h" @@ -1262,33 +1264,30 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, for (ln = 0; ln < 2; ln++) { int level; - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, ln)); - - intel_de_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), 0); + intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0); level = intel_ddi_level(encoder, crtc_state, 2*ln+0); - intel_de_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), - DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK, - DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | - DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | - DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln), + DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK, + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); level = intel_ddi_level(encoder, crtc_state, 2*ln+1); - intel_de_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), - DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK, - DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | - DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | - DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln), + DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK, + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); - intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), - DKL_TX_DP20BITMODE, 0); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln), + DKL_TX_DP20BITMODE, 0); if (IS_ALDERLAKE_P(dev_priv)) { u32 val; @@ -1306,10 +1305,10 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0); } - intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), - DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK | - DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, - val); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln), + DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK | + DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, + val); } } } @@ -2019,12 +2018,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, return; if (DISPLAY_VER(dev_priv) >= 12) { - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x0)); - ln0 = intel_de_read(dev_priv, DKL_DP_MODE(tc_port)); - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x1)); - ln1 = intel_de_read(dev_priv, DKL_DP_MODE(tc_port)); + ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0)); + ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1)); } else { ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port)); ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port)); @@ -2085,12 +2080,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, } if (DISPLAY_VER(dev_priv) >= 12) { - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x0)); - intel_de_write(dev_priv, DKL_DP_MODE(tc_port), ln0); - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x1)); - intel_de_write(dev_priv, DKL_DP_MODE(tc_port), ln1); + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0); + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1); } else { intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0); intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1); @@ -3094,10 +3085,8 @@ static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder) enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); int ln; - for (ln = 0; ln < 2; ln++) { - intel_de_write(i915, HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, ln)); - intel_de_rmw(i915, DKL_PCS_DW5(tc_port), DKL_PCS_DW5_CORE_SOFTRESET, 0); - } + for (ln = 0; ln < 2; ln++) + intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0); } static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, @@ -3536,7 +3525,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, if (drm_WARN_ON(&i915->drm, !pll)) return; - if (intel_get_shared_dpll_id(i915, pll) == DPLL_ID_ICL_TBTPLL) + if (pll->info->id == DPLL_ID_ICL_TBTPLL) port_dpll_id = ICL_PORT_DPLL_DEFAULT; else port_dpll_id = ICL_PORT_DPLL_MG_PHY; @@ -3549,7 +3538,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, icl_set_active_port_dpll(crtc_state, port_dpll_id); - if (intel_get_shared_dpll_id(i915, crtc_state->shared_dpll) == DPLL_ID_ICL_TBTPLL) + if (crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL) crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port); else crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll, @@ -3591,7 +3580,7 @@ static void intel_ddi_sync_state(struct intel_encoder *encoder, enum phy phy = intel_port_to_phy(i915, encoder->port); if (intel_phy_is_tc(i915, phy)) - intel_tc_port_sanitize(enc_to_dig_port(encoder)); + intel_tc_port_sanitize_mode(enc_to_dig_port(encoder)); if (crtc_state && intel_crtc_has_dp_encoder(crtc_state)) intel_dp_sync_state(encoder, crtc_state); @@ -3801,11 +3790,17 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) static void intel_ddi_encoder_reset(struct drm_encoder *encoder) { + struct drm_i915_private *i915 = to_i915(encoder->dev); struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder)); + struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); intel_dp->reset_link_params = true; intel_pps_encoder_reset(intel_dp); + + if (intel_phy_is_tc(i915, phy)) + intel_tc_port_init_mode(dig_port); } static const struct drm_encoder_funcs intel_ddi_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 461c62c88413..b9393f9fc764 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -831,13 +831,27 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state) } static int +intel_display_commit_duplicated_state(struct intel_atomic_state *state, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + int ret; + + ret = drm_atomic_helper_commit_duplicated_state(&state->base, ctx); + + drm_WARN_ON(&i915->drm, ret == -EDEADLK); + + return ret; +} + +static int __intel_display_resume(struct drm_i915_private *i915, struct drm_atomic_state *state, struct drm_modeset_acquire_ctx *ctx) { struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; - int i, ret; + int i; intel_modeset_setup_hw_state(i915, ctx); intel_vga_redisable(i915); @@ -863,11 +877,7 @@ __intel_display_resume(struct drm_i915_private *i915, if (!HAS_GMCH(i915)) to_intel_atomic_state(state)->skip_intermediate_wm = true; - ret = drm_atomic_helper_commit_duplicated_state(state, ctx); - - drm_WARN_ON(&i915->drm, ret == -EDEADLK); - - return ret; + return intel_display_commit_duplicated_state(to_intel_atomic_state(state), ctx); } static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv) @@ -878,7 +888,6 @@ static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv) void intel_display_prepare_reset(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; struct drm_atomic_state *state; int ret; @@ -906,10 +915,10 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv) * Need mode_config.mutex so that we don't * trample ongoing ->detect() and whatnot. */ - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); drm_modeset_acquire_init(ctx, 0); while (1) { - ret = drm_modeset_lock_all_ctx(dev, ctx); + ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx); if (ret != -EDEADLK) break; @@ -919,7 +928,7 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv) * Disabling the crtcs gracefully seems nicer. Also the * g33 docs say we should at least disable all the planes. */ - state = drm_atomic_helper_duplicate_state(dev, ctx); + state = drm_atomic_helper_duplicate_state(&dev_priv->drm, ctx); if (IS_ERR(state)) { ret = PTR_ERR(state); drm_err(&dev_priv->drm, "Duplicating state failed with %i\n", @@ -927,7 +936,7 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv) return; } - ret = drm_atomic_helper_disable_all(dev, ctx); + ret = drm_atomic_helper_disable_all(&dev_priv->drm, ctx); if (ret) { drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n", ret); @@ -959,7 +968,7 @@ void intel_display_finish_reset(struct drm_i915_private *i915) /* reset doesn't touch the display */ if (!gpu_reset_clobbers_display(i915)) { /* for testing only restore the display */ - ret = __intel_display_resume(i915, state, ctx); + ret = intel_display_commit_duplicated_state(to_intel_atomic_state(state), ctx); if (ret) drm_err(&i915->drm, "Restoring old state failed with %i\n", ret); @@ -1252,8 +1261,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state, if (needs_cursorclk_wa(old_crtc_state) && !needs_cursorclk_wa(new_crtc_state)) icl_wa_cursorclkgating(dev_priv, pipe, false); - - intel_drrs_activate(new_crtc_state); } static void intel_crtc_enable_flip_done(struct intel_atomic_state *state, @@ -4572,8 +4579,8 @@ static bool encoders_cloneable(const struct intel_encoder *a, const struct intel_encoder *b) { /* masks could be asymmetric, so check both ways */ - return a == b || (a->cloneable & (1 << b->type) && - b->cloneable & (1 << a->type)); + return a == b || (a->cloneable & BIT(b->type) && + b->cloneable & BIT(a->type)); } static bool check_single_encoder_cloning(struct intel_atomic_state *state, @@ -4824,14 +4831,14 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - bool mode_changed = intel_crtc_needs_modeset(crtc_state); int ret; if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv) && - mode_changed && !crtc_state->hw.active) + intel_crtc_needs_modeset(crtc_state) && + !crtc_state->hw.active) crtc_state->update_wm_post = true; - if (mode_changed) { + if (intel_crtc_needs_modeset(crtc_state)) { ret = intel_dpll_crtc_get_shared_dpll(state, crtc); if (ret) return ret; @@ -4844,8 +4851,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, if (c8_planes_changed(crtc_state)) crtc_state->uapi.color_mgmt_changed = true; - if (mode_changed || crtc_state->update_pipe || - crtc_state->uapi.color_mgmt_changed) { + if (intel_crtc_needs_color_update(crtc_state)) { ret = intel_color_check(crtc_state); if (ret) return ret; @@ -4871,7 +4877,8 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, } if (DISPLAY_VER(dev_priv) >= 9) { - if (mode_changed || crtc_state->update_pipe) { + if (intel_crtc_needs_modeset(crtc_state) || + intel_crtc_needs_fastset(crtc_state)) { ret = skl_update_scaler_crtc(crtc_state); if (ret) return ret; @@ -5637,39 +5644,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(name.y2); \ } while (0) -/* This is required for BDW+ where there is only one set of registers for - * switching between high and low RR. - * This macro can be used whenever a comparison has to be made between one - * hw state and multiple sw state variables. - */ -#define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) do { \ - if (!intel_compare_link_m_n(¤t_config->name, \ - &pipe_config->name) && \ - !intel_compare_link_m_n(¤t_config->alt_name, \ - &pipe_config->name)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ - "(expected tu %i data %i/%i link %i/%i, " \ - "or tu %i data %i/%i link %i/%i, " \ - "found tu %i, data %i/%i link %i/%i)", \ - current_config->name.tu, \ - current_config->name.data_m, \ - current_config->name.data_n, \ - current_config->name.link_m, \ - current_config->name.link_n, \ - current_config->alt_name.tu, \ - current_config->alt_name.data_m, \ - current_config->alt_name.data_n, \ - current_config->alt_name.link_m, \ - current_config->alt_name.link_n, \ - pipe_config->name.tu, \ - pipe_config->name.data_m, \ - pipe_config->name.data_n, \ - pipe_config->name.link_m, \ - pipe_config->name.link_n); \ - ret = false; \ - } \ -} while (0) - #define PIPE_CONF_CHECK_FLAGS(name, mask) do { \ if ((current_config->name ^ pipe_config->name) & (mask)) { \ pipe_config_mismatch(fastset, crtc, __stringify(name), \ @@ -5738,7 +5712,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) { if (!fastset || !pipe_config->seamless_m_n) - PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2); + PIPE_CONF_CHECK_M_N(dp_m_n); } else { PIPE_CONF_CHECK_M_N(dp_m_n); PIPE_CONF_CHECK_M_N(dp_m2_n2); @@ -5815,7 +5789,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, bp_gamma = intel_color_get_gamma_bit_precision(pipe_config); if (bp_gamma) - PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma); + PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma); if (current_config->active_planes) { PIPE_CONF_CHECK_BOOL(has_psr); @@ -5937,7 +5911,8 @@ intel_verify_planes(struct intel_atomic_state *state) plane_state->uapi.visible); } -int intel_modeset_all_pipes(struct intel_atomic_state *state) +int intel_modeset_all_pipes(struct intel_atomic_state *state, + const char *reason) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc *crtc; @@ -5958,7 +5933,11 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state) drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) continue; + drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n", + crtc->base.base.id, crtc->base.name, reason); + crtc_state->uapi.mode_changed = true; + crtc_state->update_pipe = false; ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base); @@ -6134,7 +6113,8 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta return; new_crtc_state->uapi.mode_changed = false; - new_crtc_state->update_pipe = true; + if (!intel_crtc_needs_modeset(new_crtc_state)) + new_crtc_state->update_pipe = true; } static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, @@ -6906,12 +6886,19 @@ static int intel_atomic_check(struct drm_device *dev, for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + intel_color_assert_luts(new_crtc_state); + ret = intel_async_flip_check_hw(state, crtc); if (ret) goto fail; + /* Either full modeset or fastset (or neither), never both */ + drm_WARN_ON(&dev_priv->drm, + intel_crtc_needs_modeset(new_crtc_state) && + intel_crtc_needs_fastset(new_crtc_state)); + if (!intel_crtc_needs_modeset(new_crtc_state) && - !new_crtc_state->update_pipe) + !intel_crtc_needs_fastset(new_crtc_state)) continue; intel_crtc_state_dump(new_crtc_state, state, @@ -6947,12 +6934,8 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state) return ret; for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - bool mode_changed = intel_crtc_needs_modeset(crtc_state); - - if (mode_changed || crtc_state->update_pipe || - crtc_state->uapi.color_mgmt_changed) { + if (intel_crtc_needs_color_update(crtc_state)) intel_dsb_prepare(crtc_state); - } } return 0; @@ -7033,14 +7016,13 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state, * CRTC was enabled. */ if (!modeset) { - if (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe) + if (intel_crtc_needs_color_update(new_crtc_state)) intel_color_commit_arm(new_crtc_state); if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(new_crtc_state); - if (new_crtc_state->update_pipe) + if (intel_crtc_needs_fastset(new_crtc_state)) intel_pipe_fastset(old_crtc_state, new_crtc_state); } @@ -7099,25 +7081,23 @@ static void intel_update_crtc(struct intel_atomic_state *state, if (!modeset) { if (new_crtc_state->preload_luts && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe)) + intel_crtc_needs_color_update(new_crtc_state)) intel_color_load_luts(new_crtc_state); intel_pre_plane_update(state, crtc); - if (new_crtc_state->update_pipe) + if (intel_crtc_needs_fastset(new_crtc_state)) intel_encoders_update_pipe(state, crtc); if (DISPLAY_VER(i915) >= 11 && - new_crtc_state->update_pipe) + intel_crtc_needs_fastset(new_crtc_state)) icl_set_pipe_chicken(new_crtc_state); } intel_fbc_update(state, crtc); if (!modeset && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe)) + intel_crtc_needs_color_update(new_crtc_state)) intel_color_commit_noarm(new_crtc_state); intel_crtc_planes_update_noarm(state, crtc); @@ -7139,7 +7119,7 @@ static void intel_update_crtc(struct intel_atomic_state *state, * valid pipe configuration from the BIOS we need to take care * of enabling them on the CRTC's first fastset. */ - if (new_crtc_state->update_pipe && !modeset && + if (intel_crtc_needs_fastset(new_crtc_state) && !modeset && old_crtc_state->inherited) intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } @@ -7162,9 +7142,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, intel_fbc_disable(crtc); intel_disable_shared_dpll(old_crtc_state); - /* FIXME unify this for all platforms */ - if (!new_crtc_state->hw.active && - !HAS_GMCH(dev_priv)) + if (!new_crtc_state->hw.active) intel_initial_watermarks(state, crtc); } @@ -7499,9 +7477,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (intel_crtc_needs_modeset(new_crtc_state) || - new_crtc_state->update_pipe) { + intel_crtc_needs_fastset(new_crtc_state)) intel_modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]); - } } intel_commit_modeset_disables(state); @@ -7605,6 +7582,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); /* + * Activate DRRS after state readout to avoid + * dp_m_n vs. dp_m2_n2 confusion on BDW+. + */ + intel_drrs_activate(new_crtc_state); + + /* * DSB cleanup is done in cleanup_work aligning with framebuffer * cleanup. So copy and reset the dsb structure to sync with * commit_done and later do dsb cleanup in cleanup_work. @@ -8344,6 +8327,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; + intel_color_init_hooks(dev_priv); intel_init_cdclk_hooks(dev_priv); intel_audio_hooks_init(dev_priv); @@ -8674,6 +8658,10 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) if (ret) goto cleanup_vga_client_pw_domain_dmc; + ret = intel_color_init(i915); + if (ret) + goto cleanup_vga_client_pw_domain_dmc; + ret = intel_dbuf_init(i915); if (ret) goto cleanup_vga_client_pw_domain_dmc; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 884e8e67b17c..c803330a276d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -469,10 +469,6 @@ enum hpd_pin { list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ for_each_if((intel_encoder)->base.crtc == (__crtc)) -#define for_each_connector_on_encoder(dev, __encoder, intel_connector) \ - list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \ - for_each_if((intel_connector)->base.encoder == (__encoder)) - #define for_each_old_intel_plane_in_state(__state, plane, old_plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->base.dev->mode_config.num_total_plane && \ @@ -683,7 +679,8 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915); void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915); void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915); void intel_display_resume(struct drm_device *dev); -int intel_modeset_all_pipes(struct intel_atomic_state *state); +int intel_modeset_all_pipes(struct intel_atomic_state *state, + const char *reason); void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state, struct intel_power_domain_mask *old_domains); void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 96cf994b0ad1..337d8e08ba43 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -28,6 +28,7 @@ struct drm_i915_private; struct drm_property; +struct drm_property_blob; struct i915_audio_component; struct i915_hdcp_comp_master; struct intel_atomic_state; @@ -309,6 +310,10 @@ struct intel_display { } cdclk; struct { + struct drm_property_blob *glk_linear_degamma_lut; + } color; + + struct { /* The current hardware dbuf configuration */ u8 enabled_slices; @@ -316,6 +321,14 @@ struct intel_display { } dbuf; struct { + /* + * dkl.phy_lock protects against concurrent access of the + * Dekel TypeC PHYs. + */ + spinlock_t phy_lock; + } dkl; + + struct { /* VLV/CHV/BXT/GLK DSI MMIO register base address */ u32 mmio_base; } dsi; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7c7253a2541c..cfc056a05bbf 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -22,6 +22,7 @@ #include "intel_fbdev.h" #include "intel_hdcp.h" #include "intel_hdmi.h" +#include "intel_hotplug.h" #include "intel_panel.h" #include "intel_pm.h" #include "intel_psr.h" @@ -127,7 +128,6 @@ static int i915_vbt(struct seq_file *m, void *unused) static int i915_gem_framebuffer_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; struct intel_framebuffer *fbdev_fb = NULL; struct drm_framebuffer *drm_fb; @@ -146,8 +146,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) } #endif - mutex_lock(&dev->mode_config.fb_lock); - drm_for_each_fb(drm_fb, dev) { + mutex_lock(&dev_priv->drm.mode_config.fb_lock); + drm_for_each_fb(drm_fb, &dev_priv->drm) { struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb); if (fb == fbdev_fb) continue; @@ -162,7 +162,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) i915_debugfs_describe_obj(m, intel_fb_obj(&fb->base)); seq_putc(m, '\n'); } - mutex_unlock(&dev->mode_config.fb_lock); + mutex_unlock(&dev_priv->drm.mode_config.fb_lock); return 0; } @@ -897,7 +897,6 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) static int i915_display_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; @@ -905,22 +904,22 @@ static int i915_display_info(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); - drm_modeset_lock_all(dev); + drm_modeset_lock_all(&dev_priv->drm); seq_printf(m, "CRTC info\n"); seq_printf(m, "---------\n"); - for_each_intel_crtc(dev, crtc) + for_each_intel_crtc(&dev_priv->drm, crtc) intel_crtc_info(m, crtc); seq_printf(m, "\n"); seq_printf(m, "Connector info\n"); seq_printf(m, "--------------\n"); - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) intel_connector_info(m, connector); drm_connector_list_iter_end(&conn_iter); - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); @@ -930,10 +929,9 @@ static int i915_display_info(struct seq_file *m, void *unused) static int i915_shared_dplls_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; int i; - drm_modeset_lock_all(dev); + drm_modeset_lock_all(&dev_priv->drm); seq_printf(m, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n", dev_priv->display.dpll.ref_clks.nssc, @@ -978,7 +976,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n", pll->state.hw_state.mg_pll_tdc_coldst_bias); } - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); return 0; } @@ -986,14 +984,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) static int i915_ddb_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; struct skl_ddb_entry *entry; struct intel_crtc *crtc; if (DISPLAY_VER(dev_priv) < 9) return -ENODEV; - drm_modeset_lock_all(dev); + drm_modeset_lock_all(&dev_priv->drm); seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size"); @@ -1017,53 +1014,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused) entry->end, skl_ddb_entry_size(entry)); } - drm_modeset_unlock_all(dev); - - return 0; -} - -static int i915_drrs_status(struct seq_file *m, void *unused) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_connector_list_iter conn_iter; - struct intel_connector *connector; - struct intel_crtc *crtc; - - drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); - for_each_intel_connector_iter(connector, &conn_iter) { - seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n", - connector->base.base.id, connector->base.name, - intel_drrs_type_str(intel_panel_drrs_type(connector))); - } - drm_connector_list_iter_end(&conn_iter); - - seq_puts(m, "\n"); - - for_each_intel_crtc(&dev_priv->drm, crtc) { - const struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - seq_printf(m, "[CRTC:%d:%s]:\n", - crtc->base.base.id, crtc->base.name); - - mutex_lock(&crtc->drrs.mutex); - - /* DRRS Supported */ - seq_printf(m, "\tDRRS Enabled: %s\n", - str_yes_no(crtc_state->has_drrs)); - - seq_printf(m, "\tDRRS Active: %s\n", - str_yes_no(intel_drrs_is_active(crtc))); - - seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n", - crtc->drrs.busy_frontbuffer_bits); - - seq_printf(m, "\tDRRS refresh rate: %s\n", - crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? - "low" : "high"); - - mutex_unlock(&crtc->drrs.mutex); - } + drm_modeset_unlock_all(&dev_priv->drm); return 0; } @@ -1107,13 +1058,12 @@ static int i915_lpsp_status(struct seq_file *m, void *unused) static int i915_dp_mst_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; struct intel_encoder *intel_encoder; struct intel_digital_port *dig_port; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; @@ -1200,12 +1150,11 @@ static ssize_t i915_displayport_test_active_write(struct file *file, static int i915_displayport_test_active_show(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = m->private; - struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; struct intel_dp *intel_dp; - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { struct intel_encoder *encoder; @@ -1250,12 +1199,11 @@ static const struct file_operations i915_displayport_test_active_fops = { static int i915_displayport_test_data_show(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = m->private; - struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; struct intel_dp *intel_dp; - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { struct intel_encoder *encoder; @@ -1304,12 +1252,11 @@ DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data); static int i915_displayport_test_type_show(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = m->private; - struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; struct intel_dp *intel_dp; - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { struct intel_encoder *encoder; @@ -1336,7 +1283,6 @@ DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type); static void wm_latency_show(struct seq_file *m, const u16 wm[8]) { struct drm_i915_private *dev_priv = m->private; - struct drm_device *dev = &dev_priv->drm; int level; int num_levels; @@ -1349,7 +1295,7 @@ static void wm_latency_show(struct seq_file *m, const u16 wm[8]) else num_levels = ilk_wm_max_level(dev_priv) + 1; - drm_modeset_lock_all(dev); + drm_modeset_lock_all(&dev_priv->drm); for (level = 0; level < num_levels; level++) { unsigned int latency = wm[level]; @@ -1370,7 +1316,7 @@ static void wm_latency_show(struct seq_file *m, const u16 wm[8]) level, wm[level], latency / 10, latency % 10); } - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); } static int pri_wm_latency_show(struct seq_file *m, void *data) @@ -1453,7 +1399,6 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, { struct seq_file *m = file->private_data; struct drm_i915_private *dev_priv = m->private; - struct drm_device *dev = &dev_priv->drm; u16 new[8] = { 0 }; int num_levels; int level; @@ -1483,12 +1428,12 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, if (ret != num_levels) return -EINVAL; - drm_modeset_lock_all(dev); + drm_modeset_lock_all(&dev_priv->drm); for (level = 0; level < num_levels; level++) wm[level] = new[level]; - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); return len; } @@ -1566,209 +1511,6 @@ static const struct file_operations i915_cur_wm_latency_fops = { .write = cur_wm_latency_write }; -static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) -{ - struct drm_i915_private *dev_priv = m->private; - struct intel_hotplug *hotplug = &dev_priv->display.hotplug; - - /* Synchronize with everything first in case there's been an HPD - * storm, but we haven't finished handling it in the kernel yet - */ - intel_synchronize_irq(dev_priv); - flush_work(&dev_priv->display.hotplug.dig_port_work); - flush_delayed_work(&dev_priv->display.hotplug.hotplug_work); - - seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold); - seq_printf(m, "Detected: %s\n", - str_yes_no(delayed_work_pending(&hotplug->reenable_work))); - - return 0; -} - -static ssize_t i915_hpd_storm_ctl_write(struct file *file, - const char __user *ubuf, size_t len, - loff_t *offp) -{ - struct seq_file *m = file->private_data; - struct drm_i915_private *dev_priv = m->private; - struct intel_hotplug *hotplug = &dev_priv->display.hotplug; - unsigned int new_threshold; - int i; - char *newline; - char tmp[16]; - - if (len >= sizeof(tmp)) - return -EINVAL; - - if (copy_from_user(tmp, ubuf, len)) - return -EFAULT; - - tmp[len] = '\0'; - - /* Strip newline, if any */ - newline = strchr(tmp, '\n'); - if (newline) - *newline = '\0'; - - if (strcmp(tmp, "reset") == 0) - new_threshold = HPD_STORM_DEFAULT_THRESHOLD; - else if (kstrtouint(tmp, 10, &new_threshold) != 0) - return -EINVAL; - - if (new_threshold > 0) - drm_dbg_kms(&dev_priv->drm, - "Setting HPD storm detection threshold to %d\n", - new_threshold); - else - drm_dbg_kms(&dev_priv->drm, "Disabling HPD storm detection\n"); - - spin_lock_irq(&dev_priv->irq_lock); - hotplug->hpd_storm_threshold = new_threshold; - /* Reset the HPD storm stats so we don't accidentally trigger a storm */ - for_each_hpd_pin(i) - hotplug->stats[i].count = 0; - spin_unlock_irq(&dev_priv->irq_lock); - - /* Re-enable hpd immediately if we were in an irq storm */ - flush_delayed_work(&dev_priv->display.hotplug.reenable_work); - - return len; -} - -static int i915_hpd_storm_ctl_open(struct inode *inode, struct file *file) -{ - return single_open(file, i915_hpd_storm_ctl_show, inode->i_private); -} - -static const struct file_operations i915_hpd_storm_ctl_fops = { - .owner = THIS_MODULE, - .open = i915_hpd_storm_ctl_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = i915_hpd_storm_ctl_write -}; - -static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data) -{ - struct drm_i915_private *dev_priv = m->private; - - seq_printf(m, "Enabled: %s\n", - str_yes_no(dev_priv->display.hotplug.hpd_short_storm_enabled)); - - return 0; -} - -static int -i915_hpd_short_storm_ctl_open(struct inode *inode, struct file *file) -{ - return single_open(file, i915_hpd_short_storm_ctl_show, - inode->i_private); -} - -static ssize_t i915_hpd_short_storm_ctl_write(struct file *file, - const char __user *ubuf, - size_t len, loff_t *offp) -{ - struct seq_file *m = file->private_data; - struct drm_i915_private *dev_priv = m->private; - struct intel_hotplug *hotplug = &dev_priv->display.hotplug; - char *newline; - char tmp[16]; - int i; - bool new_state; - - if (len >= sizeof(tmp)) - return -EINVAL; - - if (copy_from_user(tmp, ubuf, len)) - return -EFAULT; - - tmp[len] = '\0'; - - /* Strip newline, if any */ - newline = strchr(tmp, '\n'); - if (newline) - *newline = '\0'; - - /* Reset to the "default" state for this system */ - if (strcmp(tmp, "reset") == 0) - new_state = !HAS_DP_MST(dev_priv); - else if (kstrtobool(tmp, &new_state) != 0) - return -EINVAL; - - drm_dbg_kms(&dev_priv->drm, "%sabling HPD short storm detection\n", - new_state ? "En" : "Dis"); - - spin_lock_irq(&dev_priv->irq_lock); - hotplug->hpd_short_storm_enabled = new_state; - /* Reset the HPD storm stats so we don't accidentally trigger a storm */ - for_each_hpd_pin(i) - hotplug->stats[i].count = 0; - spin_unlock_irq(&dev_priv->irq_lock); - - /* Re-enable hpd immediately if we were in an irq storm */ - flush_delayed_work(&dev_priv->display.hotplug.reenable_work); - - return len; -} - -static const struct file_operations i915_hpd_short_storm_ctl_fops = { - .owner = THIS_MODULE, - .open = i915_hpd_short_storm_ctl_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = i915_hpd_short_storm_ctl_write, -}; - -static int i915_drrs_ctl_set(void *data, u64 val) -{ - struct drm_i915_private *dev_priv = data; - struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc; - - for_each_intel_crtc(dev, crtc) { - struct intel_crtc_state *crtc_state; - struct drm_crtc_commit *commit; - int ret; - - ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex); - if (ret) - return ret; - - crtc_state = to_intel_crtc_state(crtc->base.state); - - if (!crtc_state->hw.active || - !crtc_state->has_drrs) - goto out; - - commit = crtc_state->uapi.commit; - if (commit) { - ret = wait_for_completion_interruptible(&commit->hw_done); - if (ret) - goto out; - } - - drm_dbg(&dev_priv->drm, - "Manually %sactivating DRRS\n", val ? "" : "de"); - - if (val) - intel_drrs_activate(crtc_state); - else - intel_drrs_deactivate(crtc_state); - -out: - drm_modeset_unlock(&crtc->base.mutex); - if (ret) - return ret; - } - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n"); - static ssize_t i915_fifo_underrun_reset_write(struct file *filp, const char __user *ubuf, @@ -1776,7 +1518,6 @@ i915_fifo_underrun_reset_write(struct file *filp, { struct drm_i915_private *dev_priv = filp->private_data; struct intel_crtc *crtc; - struct drm_device *dev = &dev_priv->drm; int ret; bool reset; @@ -1787,7 +1528,7 @@ i915_fifo_underrun_reset_write(struct file *filp, if (!reset) return cnt; - for_each_intel_crtc(dev, crtc) { + for_each_intel_crtc(&dev_priv->drm, crtc) { struct drm_crtc_commit *commit; struct intel_crtc_state *crtc_state; @@ -1842,7 +1583,6 @@ static const struct drm_info_list intel_display_debugfs_list[] = { {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, {"i915_dp_mst_info", i915_dp_mst_info, 0}, {"i915_ddb_info", i915_ddb_info, 0}, - {"i915_drrs_status", i915_drrs_status, 0}, {"i915_lpsp_status", i915_lpsp_status, 0}, }; @@ -1857,9 +1597,6 @@ static const struct { {"i915_dp_test_data", &i915_displayport_test_data_fops}, {"i915_dp_test_type", &i915_displayport_test_type_fops}, {"i915_dp_test_active", &i915_displayport_test_active_fops}, - {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, - {"i915_hpd_short_storm_ctl", &i915_hpd_short_storm_ctl_fops}, - {"i915_drrs_ctl", &i915_drrs_ctl_fops}, {"i915_edp_psr_debug", &i915_edp_psr_debug_fops}, }; @@ -1882,6 +1619,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915) intel_dmc_debugfs_register(i915); intel_fbc_debugfs_register(i915); + intel_hpd_debugfs_register(i915); skl_watermark_ipc_debugfs_register(i915); } @@ -2195,6 +1933,8 @@ void intel_connector_debugfs_add(struct intel_connector *intel_connector) if (!root) return; + intel_drrs_connector_debugfs_add(intel_connector); + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { debugfs_create_file("i915_panel_timings", S_IRUGO, root, connector, &i915_panel_fops); @@ -2247,6 +1987,7 @@ void intel_crtc_debugfs_add(struct drm_crtc *crtc) return; crtc_updates_add(crtc); + intel_drrs_crtc_debugfs_add(to_intel_crtc(crtc)); intel_fbc_crtc_debugfs_add(to_intel_crtc(crtc)); debugfs_create_file("i915_current_bpc", 0444, crtc->debugfs_entry, crtc, diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 1e608b9e5055..4c1de91e56ff 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1148,10 +1148,9 @@ static void hsw_assert_cdclk(struct drm_i915_private *dev_priv) static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc; - for_each_intel_crtc(dev, crtc) + for_each_intel_crtc(&dev_priv->drm, crtc) I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index df7ee4969ef1..8710dd41ffd4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -12,6 +12,8 @@ #include "intel_de.h" #include "intel_display_power_well.h" #include "intel_display_types.h" +#include "intel_dkl_phy.h" +#include "intel_dkl_phy_regs.h" #include "intel_dmc.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" @@ -529,11 +531,9 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, enum tc_port tc_port; tc_port = TGL_AUX_PW_TO_TC_PORT(i915_power_well_instance(power_well)->hsw.idx); - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x2)); - if (intel_de_wait_for_set(dev_priv, DKL_CMN_UC_DW_27(tc_port), - DKL_CMN_UC_DW27_UC_HEALTH, 1)) + if (wait_for(intel_dkl_phy_read(dev_priv, DKL_CMN_UC_DW_27(tc_port)) & + DKL_CMN_UC_DW27_UC_HEALTH, 1)) drm_warn(&dev_priv->drm, "Timeout waiting TC uC health\n"); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 298d00a11f47..7f18c052ec16 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1001,11 +1001,15 @@ struct intel_crtc_state { */ struct { bool active, enable; + /* logical state of LUTs */ struct drm_property_blob *degamma_lut, *gamma_lut, *ctm; struct drm_display_mode mode, pipe_mode, adjusted_mode; enum drm_scaling_filter scaling_filter; } hw; + /* actual state of LUTs */ + struct drm_property_blob *pre_csc_lut, *post_csc_lut; + /** * quirks - bitfield with hw state readout quirks * @@ -2040,15 +2044,16 @@ static inline bool intel_crtc_has_type(const struct intel_crtc_state *crtc_state, enum intel_output_type type) { - return crtc_state->output_types & (1 << type); + return crtc_state->output_types & BIT(type); } + static inline bool intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state) { return crtc_state->output_types & - ((1 << INTEL_OUTPUT_DP) | - (1 << INTEL_OUTPUT_DP_MST) | - (1 << INTEL_OUTPUT_EDP)); + (BIT(INTEL_OUTPUT_DP) | + BIT(INTEL_OUTPUT_DP_MST) | + BIT(INTEL_OUTPUT_EDP)); } static inline bool @@ -2057,6 +2062,20 @@ intel_crtc_needs_modeset(const struct intel_crtc_state *crtc_state) return drm_atomic_crtc_needs_modeset(&crtc_state->uapi); } +static inline bool +intel_crtc_needs_fastset(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->update_pipe; +} + +static inline bool +intel_crtc_needs_color_update(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->uapi.color_mgmt_changed || + intel_crtc_needs_fastset(crtc_state) || + intel_crtc_needs_modeset(crtc_state); +} + static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *plane_state) { return i915_ggtt_offset(plane_state->ggtt_vma); diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c new file mode 100644 index 000000000000..57cc3edba016 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" + +#include "intel_de.h" +#include "intel_display.h" +#include "intel_dkl_phy.h" +#include "intel_dkl_phy_regs.h" + +static void +dkl_phy_set_hip_idx(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg) +{ + enum tc_port tc_port = DKL_REG_TC_PORT(reg); + + drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS); + + intel_de_write(i915, + HIP_INDEX_REG(tc_port), + HIP_INDEX_VAL(tc_port, reg.bank_idx)); +} + +/** + * intel_dkl_phy_read - read a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * + * Read the @reg Dekel PHY register. + * + * Returns the read value. + */ +u32 +intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg) +{ + u32 val; + + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg); + val = intel_de_read(i915, DKL_REG_MMIO(reg)); + + spin_unlock(&i915->display.dkl.phy_lock); + + return val; +} + +/** + * intel_dkl_phy_write - write a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * @val: value to write + * + * Write @val to the @reg Dekel PHY register. + */ +void +intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val) +{ + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg); + intel_de_write(i915, DKL_REG_MMIO(reg), val); + + spin_unlock(&i915->display.dkl.phy_lock); +} + +/** + * intel_dkl_phy_rmw - read-modify-write a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * @clear: mask to clear + * @set: mask to set + * + * Read the @reg Dekel PHY register, clearing then setting the @clear/@set bits in it, and writing + * this value back to the register if the value differs from the read one. + */ +void +intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set) +{ + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg); + intel_de_rmw(i915, DKL_REG_MMIO(reg), clear, set); + + spin_unlock(&i915->display.dkl.phy_lock); +} + +/** + * intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * + * Read the @reg Dekel PHY register without returning the read value. + */ +void +intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg) +{ + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg); + intel_de_posting_read(i915, DKL_REG_MMIO(reg)); + + spin_unlock(&i915->display.dkl.phy_lock); +} diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.h b/drivers/gpu/drm/i915/display/intel_dkl_phy.h new file mode 100644 index 000000000000..570ee36f9386 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DKL_PHY_H__ +#define __INTEL_DKL_PHY_H__ + +#include <linux/types.h> + +#include "intel_dkl_phy_regs.h" + +struct drm_i915_private; + +u32 +intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg); +void +intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val); +void +intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set); +void +intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg); + +#endif /* __INTEL_DKL_PHY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h b/drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h new file mode 100644 index 000000000000..56085b32956d --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DKL_PHY_REGS__ +#define __INTEL_DKL_PHY_REGS__ + +#include <linux/types.h> + +struct intel_dkl_phy_reg { + u32 reg:24; + u32 bank_idx:4; +}; + +#define _DKL_PHY1_BASE 0x168000 +#define _DKL_PHY2_BASE 0x169000 +#define _DKL_PHY3_BASE 0x16A000 +#define _DKL_PHY4_BASE 0x16B000 +#define _DKL_PHY5_BASE 0x16C000 +#define _DKL_PHY6_BASE 0x16D000 + +#define DKL_REG_TC_PORT(__reg) \ + (TC_PORT_1 + ((__reg).reg - _DKL_PHY1_BASE) / (_DKL_PHY2_BASE - _DKL_PHY1_BASE)) + +/* DEKEL PHY MMIO Address = Phy base + (internal address & ~index_mask) */ +#define DKL_REG_MMIO(__reg) _MMIO((__reg).reg) + +#define _DKL_REG_PHY_BASE(tc_port) _PORT(tc_port, \ + _DKL_PHY1_BASE, \ + _DKL_PHY2_BASE) + +#define _DKL_BANK_SHIFT 12 +#define _DKL_REG_BANK_OFFSET(phy_offset) \ + ((phy_offset) & ((1 << _DKL_BANK_SHIFT) - 1)) +#define _DKL_REG_BANK_IDX(phy_offset) \ + (((phy_offset) >> _DKL_BANK_SHIFT) & 0xf) + +#define _DKL_REG(tc_port, phy_offset) \ + ((const struct intel_dkl_phy_reg) { \ + .reg = _DKL_REG_PHY_BASE(tc_port) + \ + _DKL_REG_BANK_OFFSET(phy_offset), \ + .bank_idx = _DKL_REG_BANK_IDX(phy_offset), \ + }) + +#define _DKL_REG_LN(tc_port, ln_idx, ln0_offs, ln1_offs) \ + _DKL_REG(tc_port, (ln0_offs) + (ln_idx) * ((ln1_offs) - (ln0_offs))) + +#define _DKL_PCS_DW5_LN0 0x0014 +#define _DKL_PCS_DW5_LN1 0x1014 +#define DKL_PCS_DW5(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_PCS_DW5_LN0, \ + _DKL_PCS_DW5_LN1) +#define DKL_PCS_DW5_CORE_SOFTRESET REG_BIT(11) + +#define _DKL_PLL_DIV0 0x2200 +#define DKL_PLL_DIV0(tc_port) _DKL_REG(tc_port, \ + _DKL_PLL_DIV0) +#define DKL_PLL_DIV0_AFC_STARTUP_MASK REG_GENMASK(27, 25) +#define DKL_PLL_DIV0_AFC_STARTUP(val) REG_FIELD_PREP(DKL_PLL_DIV0_AFC_STARTUP_MASK, (val)) +#define DKL_PLL_DIV0_INTEG_COEFF(x) ((x) << 16) +#define DKL_PLL_DIV0_INTEG_COEFF_MASK (0x1F << 16) +#define DKL_PLL_DIV0_PROP_COEFF(x) ((x) << 12) +#define DKL_PLL_DIV0_PROP_COEFF_MASK (0xF << 12) +#define DKL_PLL_DIV0_FBPREDIV_SHIFT (8) +#define DKL_PLL_DIV0_FBPREDIV(x) ((x) << DKL_PLL_DIV0_FBPREDIV_SHIFT) +#define DKL_PLL_DIV0_FBPREDIV_MASK (0xF << DKL_PLL_DIV0_FBPREDIV_SHIFT) +#define DKL_PLL_DIV0_FBDIV_INT(x) ((x) << 0) +#define DKL_PLL_DIV0_FBDIV_INT_MASK (0xFF << 0) +#define DKL_PLL_DIV0_MASK (DKL_PLL_DIV0_INTEG_COEFF_MASK | \ + DKL_PLL_DIV0_PROP_COEFF_MASK | \ + DKL_PLL_DIV0_FBPREDIV_MASK | \ + DKL_PLL_DIV0_FBDIV_INT_MASK) + +#define _DKL_PLL_DIV1 0x2204 +#define DKL_PLL_DIV1(tc_port) _DKL_REG(tc_port, \ + _DKL_PLL_DIV1) +#define DKL_PLL_DIV1_IREF_TRIM(x) ((x) << 16) +#define DKL_PLL_DIV1_IREF_TRIM_MASK (0x1F << 16) +#define DKL_PLL_DIV1_TDC_TARGET_CNT(x) ((x) << 0) +#define DKL_PLL_DIV1_TDC_TARGET_CNT_MASK (0xFF << 0) + +#define _DKL_PLL_SSC 0x2210 +#define DKL_PLL_SSC(tc_port) _DKL_REG(tc_port, \ + _DKL_PLL_SSC) +#define DKL_PLL_SSC_IREF_NDIV_RATIO(x) ((x) << 29) +#define DKL_PLL_SSC_IREF_NDIV_RATIO_MASK (0x7 << 29) +#define DKL_PLL_SSC_STEP_LEN(x) ((x) << 16) +#define DKL_PLL_SSC_STEP_LEN_MASK (0xFF << 16) +#define DKL_PLL_SSC_STEP_NUM(x) ((x) << 11) +#define DKL_PLL_SSC_STEP_NUM_MASK (0x7 << 11) +#define DKL_PLL_SSC_EN (1 << 9) + +#define _DKL_PLL_BIAS 0x2214 +#define DKL_PLL_BIAS(tc_port) _DKL_REG(tc_port, \ + _DKL_PLL_BIAS) +#define DKL_PLL_BIAS_FRAC_EN_H (1 << 30) +#define DKL_PLL_BIAS_FBDIV_SHIFT (8) +#define DKL_PLL_BIAS_FBDIV_FRAC(x) ((x) << DKL_PLL_BIAS_FBDIV_SHIFT) +#define DKL_PLL_BIAS_FBDIV_FRAC_MASK (0x3FFFFF << DKL_PLL_BIAS_FBDIV_SHIFT) + +#define _DKL_PLL_TDC_COLDST_BIAS 0x2218 +#define DKL_PLL_TDC_COLDST_BIAS(tc_port) _DKL_REG(tc_port, \ + _DKL_PLL_TDC_COLDST_BIAS) +#define DKL_PLL_TDC_SSC_STEP_SIZE(x) ((x) << 8) +#define DKL_PLL_TDC_SSC_STEP_SIZE_MASK (0xFF << 8) +#define DKL_PLL_TDC_FEED_FWD_GAIN(x) ((x) << 0) +#define DKL_PLL_TDC_FEED_FWD_GAIN_MASK (0xFF << 0) + +#define _DKL_REFCLKIN_CTL 0x212C +#define DKL_REFCLKIN_CTL(tc_port) _DKL_REG(tc_port, \ + _DKL_REFCLKIN_CTL) +/* Bits are the same as MG_REFCLKIN_CTL */ + +#define _DKL_CLKTOP2_HSCLKCTL 0x20D4 +#define DKL_CLKTOP2_HSCLKCTL(rc_port) _DKL_REG(tc_port, \ + _DKL_CLKTOP2_HSCLKCTL) +/* Bits are the same as MG_CLKTOP2_HSCLKCTL */ + +#define _DKL_CLKTOP2_CORECLKCTL1 0x20D8 +#define DKL_CLKTOP2_CORECLKCTL1(tc_port) _DKL_REG(tc_port, \ + _DKL_CLKTOP2_CORECLKCTL1) +/* Bits are the same as MG_CLKTOP2_CORECLKCTL1 */ + +#define _DKL_TX_DPCNTL0_LN0 0x02C0 +#define _DKL_TX_DPCNTL0_LN1 0x12C0 +#define DKL_TX_DPCNTL0(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_DPCNTL0_LN0, \ + _DKL_TX_DPCNTL0_LN1) +#define DKL_TX_PRESHOOT_COEFF(x) ((x) << 13) +#define DKL_TX_PRESHOOT_COEFF_MASK (0x1f << 13) +#define DKL_TX_DE_EMPHASIS_COEFF(x) ((x) << 8) +#define DKL_TX_DE_EMPAHSIS_COEFF_MASK (0x1f << 8) +#define DKL_TX_VSWING_CONTROL(x) ((x) << 0) +#define DKL_TX_VSWING_CONTROL_MASK (0x7 << 0) + +#define _DKL_TX_DPCNTL1_LN0 0x02C4 +#define _DKL_TX_DPCNTL1_LN1 0x12C4 +#define DKL_TX_DPCNTL1(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_DPCNTL1_LN0, \ + _DKL_TX_DPCNTL1_LN1) +/* Bits are the same as DKL_TX_DPCNTRL0 */ + +#define _DKL_TX_DPCNTL2_LN0 0x02C8 +#define _DKL_TX_DPCNTL2_LN1 0x12C8 +#define DKL_TX_DPCNTL2(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_DPCNTL2_LN0, \ + _DKL_TX_DPCNTL2_LN1) +#define DKL_TX_DP20BITMODE REG_BIT(2) +#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK REG_GENMASK(4, 3) +#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK, (val)) +#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK REG_GENMASK(6, 5) +#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, (val)) + +#define _DKL_TX_FW_CALIB_LN0 0x02F8 +#define _DKL_TX_FW_CALIB_LN1 0x12F8 +#define DKL_TX_FW_CALIB(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_FW_CALIB_LN0, \ + _DKL_TX_FW_CALIB_LN1) +#define DKL_TX_CFG_DISABLE_WAIT_INIT (1 << 7) + +#define _DKL_TX_PMD_LANE_SUS_LN0 0x0D00 +#define _DKL_TX_PMD_LANE_SUS_LN1 0x1D00 +#define DKL_TX_PMD_LANE_SUS(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_PMD_LANE_SUS_LN0, \ + _DKL_TX_PMD_LANE_SUS_LN1) + +#define _DKL_TX_DW17_LN0 0x0DC4 +#define _DKL_TX_DW17_LN1 0x1DC4 +#define DKL_TX_DW17(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_DW17_LN0, \ + _DKL_TX_DW17_LN1) + +#define _DKL_TX_DW18_LN0 0x0DC8 +#define _DKL_TX_DW18_LN1 0x1DC8 +#define DKL_TX_DW18(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_TX_DW18_LN0, \ + _DKL_TX_DW18_LN1) + +#define _DKL_DP_MODE_LN0 0x00A0 +#define _DKL_DP_MODE_LN1 0x10A0 +#define DKL_DP_MODE(tc_port, ln) _DKL_REG_LN(tc_port, ln, \ + _DKL_DP_MODE_LN0, \ + _DKL_DP_MODE_LN1) + +#define _DKL_CMN_UC_DW27 0x236C +#define DKL_CMN_UC_DW_27(tc_port) _DKL_REG(tc_port, \ + _DKL_CMN_UC_DW27) +#define DKL_CMN_UC_DW27_UC_HEALTH (0x1 << 15) + +/* + * Each Dekel PHY is addressed through a 4KB aperture. Each PHY has more than + * 4KB of register space, so a separate index is programmed in HIP_INDEX_REG0 + * or HIP_INDEX_REG1, based on the port number, to set the upper 2 address + * bits that point the 4KB window into the full PHY register space. + */ +#define _HIP_INDEX_REG0 0x1010A0 +#define _HIP_INDEX_REG1 0x1010A4 +#define HIP_INDEX_REG(tc_port) _MMIO((tc_port) < 4 ? _HIP_INDEX_REG0 \ + : _HIP_INDEX_REG1) +#define _HIP_INDEX_SHIFT(tc_port) (8 * ((tc_port) % 4)) +#define HIP_INDEX_VAL(tc_port, val) ((val) << _HIP_INDEX_SHIFT(tc_port)) + +#endif /* __INTEL_DKL_PHY_REGS__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index e52ecc0738a6..081a4d0083b1 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -1065,12 +1065,13 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) seq_printf(m, "fw loaded: %s\n", str_yes_no(intel_dmc_has_payload(i915))); seq_printf(m, "path: %s\n", dmc->fw_path); - seq_printf(m, "Pipe A fw support: %s\n", + seq_printf(m, "Pipe A fw needed: %s\n", str_yes_no(GRAPHICS_VER(i915) >= 12)); seq_printf(m, "Pipe A fw loaded: %s\n", str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload)); - seq_printf(m, "Pipe B fw support: %s\n", - str_yes_no(IS_ALDERLAKE_P(i915))); + seq_printf(m, "Pipe B fw needed: %s\n", + str_yes_no(IS_ALDERLAKE_P(i915) || + DISPLAY_VER(i915) >= 14)); seq_printf(m, "Pipe B fw loaded: %s\n", str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload)); @@ -1081,22 +1082,19 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) DMC_VERSION_MINOR(dmc->version)); if (DISPLAY_VER(i915) >= 12) { - if (IS_DGFX(i915)) { + i915_reg_t dc3co_reg; + + if (IS_DGFX(i915) || DISPLAY_VER(i915) >= 14) { + dc3co_reg = DG1_DMC_DEBUG3; dc5_reg = DG1_DMC_DEBUG_DC5_COUNT; } else { + dc3co_reg = TGL_DMC_DEBUG3; dc5_reg = TGL_DMC_DEBUG_DC5_COUNT; dc6_reg = TGL_DMC_DEBUG_DC6_COUNT; } - /* - * NOTE: DMC_DEBUG3 is a general purpose reg. - * According to B.Specs:49196 DMC f/w reuses DC5/6 counter - * reg for DC3CO debugging and validation, - * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter. - */ seq_printf(m, "DC3CO count: %d\n", - intel_de_read(i915, IS_DGFX(i915) ? - DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3)); + intel_de_read(i915, dc3co_reg)); } else { dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT : SKL_DMC_DC3_DC5_COUNT; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c9be61d2348e..7400d6b4c587 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2306,6 +2306,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + bool fastset = true; /* * If BIOS has set an unsupported or non-standard link rate for some @@ -2313,9 +2314,10 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, */ if (intel_dp_rate_index(intel_dp->source_rates, intel_dp->num_source_rates, crtc_state->port_clock) < 0) { - drm_dbg_kms(&i915->drm, "Forcing full modeset due to unsupported link rate\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset due to unsupported link rate\n", + encoder->base.base.id, encoder->base.name); crtc_state->uapi.connectors_changed = true; - return false; + fastset = false; } /* @@ -2326,18 +2328,20 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, * Remove once we have readout for DSC. */ if (crtc_state->dsc.compression_enable) { - drm_dbg_kms(&i915->drm, "Forcing full modeset due to DSC being enabled\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset due to DSC being enabled\n", + encoder->base.base.id, encoder->base.name); crtc_state->uapi.mode_changed = true; - return false; + fastset = false; } if (CAN_PSR(intel_dp)) { - drm_dbg_kms(&i915->drm, "Forcing full modeset to compute PSR state\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute PSR state\n", + encoder->base.base.id, encoder->base.name); crtc_state->uapi.mode_changed = true; - return false; + fastset = false; } - return true; + return fastset; } static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) @@ -2686,7 +2690,6 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, str_enable_disable(tmp)); } - bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp) { u8 dprx = 0; @@ -3957,6 +3960,8 @@ intel_dp_handle_hdmi_link_status_change(struct intel_dp *intel_dp) drm_dp_pcon_hdmi_frl_link_error_count(&intel_dp->aux, &intel_dp->attached_connector->base); + intel_dp->frl.is_trained = false; + /* Restart FRL training or fall back to TMDS mode */ intel_dp_check_frl_training(intel_dp); } @@ -5172,19 +5177,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect if (has_gamut_metadata_dip(dev_priv, port)) drm_connector_attach_hdr_output_metadata_property(connector); - if (intel_dp_is_edp(intel_dp)) { - u32 allowed_scalers; - - allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); - if (!HAS_GMCH(dev_priv)) - allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER); - - drm_connector_attach_scaling_mode_property(connector, allowed_scalers); - - connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT; - - } - if (HAS_VRR(dev_priv)) drm_connector_attach_vrr_capable_property(connector); } @@ -5197,8 +5189,7 @@ intel_edp_add_properties(struct intel_dp *intel_dp) const struct drm_display_mode *fixed_mode = intel_panel_preferred_fixed_mode(connector); - if (!fixed_mode) - return; + intel_attach_scaling_mode_property(&connector->base); drm_connector_set_panel_orientation_with_quirk(&connector->base, i915->display.vbt.orientation, @@ -5206,16 +5197,43 @@ intel_edp_add_properties(struct intel_dp *intel_dp) fixed_mode->vdisplay); } +static void intel_edp_backlight_setup(struct intel_dp *intel_dp, + struct intel_connector *connector) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + enum pipe pipe = INVALID_PIPE; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + /* + * Figure out the current pipe for the initial backlight setup. + * If the current pipe isn't valid, try the PPS pipe, and if that + * fails just assume pipe A. + */ + pipe = vlv_active_pipe(intel_dp); + + if (pipe != PIPE_A && pipe != PIPE_B) + pipe = intel_dp->pps.pps_pipe; + + if (pipe != PIPE_A && pipe != PIPE_B) + pipe = PIPE_A; + + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] using pipe %c for initial backlight setup\n", + connector->base.base.id, connector->base.name, + pipe_name(pipe)); + } + + intel_backlight_setup(connector, pipe); +} + static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct intel_connector *intel_connector) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector = &intel_connector->base; struct drm_display_mode *fixed_mode; struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; bool has_dpcd; - enum pipe pipe = INVALID_PIPE; struct edid *edid; if (!intel_dp_is_edp(intel_dp)) @@ -5228,7 +5246,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, * with an already powered-on LVDS power sequencer. */ if (intel_get_lvds_encoder(dev_priv)) { - drm_WARN_ON(dev, + drm_WARN_ON(&dev_priv->drm, !(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))); drm_info(&dev_priv->drm, "LVDS was detected, not registering eDP\n"); @@ -5244,11 +5262,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (!has_dpcd) { /* if this fails, presume the device is a ghost */ drm_info(&dev_priv->drm, - "failed to retrieve link info, disabling eDP\n"); + "[ENCODER:%d:%s] failed to retrieve link info, disabling eDP\n", + encoder->base.base.id, encoder->base.name); goto out_vdd_off; } - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); edid = drm_get_edid(connector, &intel_dp->aux.ddc); if (!edid) { /* Fallback to EDID from ACPI OpRegion, if any */ @@ -5273,9 +5292,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_bios_init_panel(dev_priv, &intel_connector->panel, encoder->devdata, IS_ERR(edid) ? NULL : edid); - intel_panel_add_edid_fixed_modes(intel_connector, - intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, - intel_vrr_is_capable(intel_connector)); + intel_panel_add_edid_fixed_modes(intel_connector, true); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); @@ -5288,30 +5305,18 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (!intel_panel_preferred_fixed_mode(intel_connector)) intel_panel_add_vbt_lfp_fixed_mode(intel_connector); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&dev_priv->drm.mode_config.mutex); - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - /* - * Figure out the current pipe for the initial backlight setup. - * If the current pipe isn't valid, try the PPS pipe, and if that - * fails just assume pipe A. - */ - pipe = vlv_active_pipe(intel_dp); - - if (pipe != PIPE_A && pipe != PIPE_B) - pipe = intel_dp->pps.pps_pipe; - - if (pipe != PIPE_A && pipe != PIPE_B) - pipe = PIPE_A; - - drm_dbg_kms(&dev_priv->drm, - "using pipe %c for initial backlight setup\n", - pipe_name(pipe)); + if (!intel_panel_preferred_fixed_mode(intel_connector)) { + drm_info(&dev_priv->drm, + "[ENCODER:%d:%s] failed to find fixed mode for the panel, disabling eDP\n", + encoder->base.base.id, encoder->base.name); + goto out_vdd_off; } intel_panel_init(intel_connector); - intel_backlight_setup(intel_connector, pipe); + intel_edp_backlight_setup(intel_dp, intel_connector); intel_edp_add_properties(intel_dp); @@ -5413,7 +5418,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, if (!HAS_GMCH(dev_priv)) connector->interlace_allowed = true; - connector->doublescan_allowed = 0; intel_connector->polled = DRM_CONNECTOR_POLL_HPD; diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 88689124c013..35360dd543ac 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -19,28 +19,20 @@ #include "intel_hdcp.h" #include "intel_hdcp_regs.h" -static unsigned int transcoder_to_stream_enc_status(enum transcoder cpu_transcoder) +static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder) { - u32 stream_enc_mask; - switch (cpu_transcoder) { case TRANSCODER_A: - stream_enc_mask = HDCP_STATUS_STREAM_A_ENC; - break; + return HDCP_STATUS_STREAM_A_ENC; case TRANSCODER_B: - stream_enc_mask = HDCP_STATUS_STREAM_B_ENC; - break; + return HDCP_STATUS_STREAM_B_ENC; case TRANSCODER_C: - stream_enc_mask = HDCP_STATUS_STREAM_C_ENC; - break; + return HDCP_STATUS_STREAM_C_ENC; case TRANSCODER_D: - stream_enc_mask = HDCP_STATUS_STREAM_D_ENC; - break; + return HDCP_STATUS_STREAM_D_ENC; default: - stream_enc_mask = 0; + return 0; } - - return stream_enc_mask; } static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 03604a37931c..cd4e61026d98 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -793,7 +793,35 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector) return false; } -static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *pathprop) +static int intel_dp_mst_add_properties(struct intel_dp *intel_dp, + struct drm_connector *connector, + const char *pathprop) +{ + struct drm_i915_private *i915 = to_i915(connector->dev); + + drm_object_attach_property(&connector->base, + i915->drm.mode_config.path_property, 0); + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tile_property, 0); + + intel_attach_force_audio_property(connector); + intel_attach_broadcast_rgb_property(connector); + + /* + * Reuse the prop from the SST connector because we're + * not allowed to create new props after device registration. + */ + connector->max_bpc_property = + intel_dp->attached_connector->base.max_bpc_property; + if (connector->max_bpc_property) + drm_connector_attach_max_bpc_property(connector, 6, 12); + + return drm_connector_set_path_property(connector, pathprop); +} + +static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + const char *pathprop) { struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -833,28 +861,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo goto err; } - drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0); - drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0); - - ret = drm_connector_set_path_property(connector, pathprop); + ret = intel_dp_mst_add_properties(intel_dp, connector, pathprop); if (ret) goto err; - intel_attach_force_audio_property(connector); - intel_attach_broadcast_rgb_property(connector); - ret = intel_dp_hdcp_init(dig_port, intel_connector); if (ret) drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP MST init failed, skipping.\n", connector->name, connector->base.id); - /* - * Reuse the prop from the SST connector because we're - * not allowed to create new props after device registration. - */ - connector->max_bpc_property = - intel_dp->attached_connector->base.max_bpc_property; - if (connector->max_bpc_property) - drm_connector_attach_max_bpc_property(connector, 6, 12); return connector; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index e5fb66a5dd02..7c6c094a0a01 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -25,12 +25,14 @@ #include "intel_de.h" #include "intel_display_types.h" +#include "intel_dkl_phy.h" +#include "intel_dkl_phy_regs.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_dpll_mgr.h" +#include "intel_mg_phy_regs.h" #include "intel_pch_refclk.h" #include "intel_tc.h" -#include "intel_tc_phy_regs.h" /** * DOC: Display PLLs @@ -152,28 +154,6 @@ intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, return &dev_priv->display.dpll.shared_dplls[id]; } -/** - * intel_get_shared_dpll_id - get the id of a DPLL - * @dev_priv: i915 device instance - * @pll: the DPLL - * - * Returns: - * The id of @pll - */ -enum intel_dpll_id -intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - long pll_idx = pll - dev_priv->display.dpll.shared_dplls; - - if (drm_WARN_ON(&dev_priv->drm, - pll_idx < 0 || - pll_idx >= dev_priv->display.dpll.num_shared_dpll)) - return -1; - - return pll_idx; -} - /* For ILK+ */ void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, @@ -384,20 +364,30 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, if (shared_dpll[id].pipe_mask == 0) shared_dpll[id].hw_state = *pll_state; - drm_dbg(&i915->drm, "using %s for pipe %c\n", pll->info->name, - pipe_name(crtc->pipe)); + drm_WARN_ON(&i915->drm, (shared_dpll[id].pipe_mask & BIT(crtc->pipe)) != 0); shared_dpll[id].pipe_mask |= BIT(crtc->pipe); + + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] reserving %s\n", + crtc->base.base.id, crtc->base.name, pll->info->name); } static void intel_unreference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, const struct intel_shared_dpll *pll) { + struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_shared_dpll_state *shared_dpll; + const enum intel_dpll_id id = pll->info->id; shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); - shared_dpll[pll->info->id].pipe_mask &= ~BIT(crtc->pipe); + + drm_WARN_ON(&i915->drm, (shared_dpll[id].pipe_mask & BIT(crtc->pipe)) == 0); + + shared_dpll[id].pipe_mask &= ~BIT(crtc->pipe); + + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] releasing %s\n", + crtc->base.base.id, crtc->base.name, pll->info->name); } static void intel_put_dpll(struct intel_atomic_state *state, @@ -708,8 +698,6 @@ struct hsw_wrpll_rnp { static unsigned hsw_wrpll_get_budget_for_freq(int clock) { - unsigned budget; - switch (clock) { case 25175000: case 25200000: @@ -742,21 +730,18 @@ static unsigned hsw_wrpll_get_budget_for_freq(int clock) case 222750000: case 296703000: case 297000000: - budget = 0; - break; + return 0; case 233500000: case 245250000: case 247750000: case 253250000: case 298000000: - budget = 1500; - break; + return 1500; case 169128000: case 169500000: case 179500000: case 202000000: - budget = 2000; - break; + return 2000; case 256250000: case 262500000: case 270000000: @@ -766,18 +751,13 @@ static unsigned hsw_wrpll_get_budget_for_freq(int clock) case 281250000: case 286000000: case 291750000: - budget = 4000; - break; + return 4000; case 267250000: case 268500000: - budget = 5000; - break; + return 5000; default: - budget = 1000; - break; + return 1000; } - - return budget; } static void hsw_wrpll_update_rnp(u64 freq2k, unsigned int budget, @@ -3508,15 +3488,12 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv, * All registers read here have the same HIP_INDEX_REG even though * they are on different building blocks */ - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x2)); - - hw_state->mg_refclkin_ctl = intel_de_read(dev_priv, - DKL_REFCLKIN_CTL(tc_port)); + hw_state->mg_refclkin_ctl = intel_dkl_phy_read(dev_priv, + DKL_REFCLKIN_CTL(tc_port)); hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK; hw_state->mg_clktop2_hsclkctl = - intel_de_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); + intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); hw_state->mg_clktop2_hsclkctl &= MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | @@ -3524,32 +3501,32 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv, MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK; hw_state->mg_clktop2_coreclkctl1 = - intel_de_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); + intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); hw_state->mg_clktop2_coreclkctl1 &= MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; - hw_state->mg_pll_div0 = intel_de_read(dev_priv, DKL_PLL_DIV0(tc_port)); + hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port)); val = DKL_PLL_DIV0_MASK; if (dev_priv->display.vbt.override_afc_startup) val |= DKL_PLL_DIV0_AFC_STARTUP_MASK; hw_state->mg_pll_div0 &= val; - hw_state->mg_pll_div1 = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port)); + hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port)); hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK | DKL_PLL_DIV1_TDC_TARGET_CNT_MASK); - hw_state->mg_pll_ssc = intel_de_read(dev_priv, DKL_PLL_SSC(tc_port)); + hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port)); hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK | DKL_PLL_SSC_STEP_LEN_MASK | DKL_PLL_SSC_STEP_NUM_MASK | DKL_PLL_SSC_EN); - hw_state->mg_pll_bias = intel_de_read(dev_priv, DKL_PLL_BIAS(tc_port)); + hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port)); hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H | DKL_PLL_BIAS_FBDIV_FRAC_MASK); hw_state->mg_pll_tdc_coldst_bias = - intel_de_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); + intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK | DKL_PLL_TDC_FEED_FWD_GAIN_MASK); @@ -3737,61 +3714,58 @@ static void dkl_pll_write(struct drm_i915_private *dev_priv, * All registers programmed here have the same HIP_INDEX_REG even * though on different building block */ - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x2)); - /* All the registers are RMW */ - val = intel_de_read(dev_priv, DKL_REFCLKIN_CTL(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port)); val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK; val |= hw_state->mg_refclkin_ctl; - intel_de_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val); - val = intel_de_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; val |= hw_state->mg_clktop2_coreclkctl1; - intel_de_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val); - val = intel_de_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK | MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK); val |= hw_state->mg_clktop2_hsclkctl; - intel_de_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val); val = DKL_PLL_DIV0_MASK; if (dev_priv->display.vbt.override_afc_startup) val |= DKL_PLL_DIV0_AFC_STARTUP_MASK; - intel_de_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val, - hw_state->mg_pll_div0); + intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val, + hw_state->mg_pll_div0); - val = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port)); val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK | DKL_PLL_DIV1_TDC_TARGET_CNT_MASK); val |= hw_state->mg_pll_div1; - intel_de_write(dev_priv, DKL_PLL_DIV1(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), val); - val = intel_de_read(dev_priv, DKL_PLL_SSC(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port)); val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK | DKL_PLL_SSC_STEP_LEN_MASK | DKL_PLL_SSC_STEP_NUM_MASK | DKL_PLL_SSC_EN); val |= hw_state->mg_pll_ssc; - intel_de_write(dev_priv, DKL_PLL_SSC(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), val); - val = intel_de_read(dev_priv, DKL_PLL_BIAS(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port)); val &= ~(DKL_PLL_BIAS_FRAC_EN_H | DKL_PLL_BIAS_FBDIV_FRAC_MASK); val |= hw_state->mg_pll_bias; - intel_de_write(dev_priv, DKL_PLL_BIAS(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), val); - val = intel_de_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK | DKL_PLL_TDC_FEED_FWD_GAIN_MASK); val |= hw_state->mg_pll_tdc_coldst_bias; - intel_de_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val); - intel_de_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); + intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); } static void icl_pll_power_enable(struct drm_i915_private *dev_priv, @@ -4193,6 +4167,8 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv) const struct dpll_info *dpll_info; int i; + mutex_init(&dev_priv->display.dpll.lock); + if (IS_DG2(dev_priv)) /* No shared DPLLs on DG2; port PLLs are part of the PHY */ dpll_mgr = NULL; @@ -4237,7 +4213,6 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv) dev_priv->display.dpll.mgr = dpll_mgr; dev_priv->display.dpll.num_shared_dpll = i; - mutex_init(&dev_priv->display.dpll.lock); } /** diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 3247dc300ae4..3854f1b4299a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -328,9 +328,6 @@ struct intel_shared_dpll { struct intel_shared_dpll * intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, enum intel_dpll_id id); -enum intel_dpll_id -intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll); void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, bool state); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 7da4a9cbe4ba..e27408efaae2 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -284,16 +284,124 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv, } /** - * intel_crtc_drrs_init - Init DRRS for CRTC + * intel_drrs_crtc_init - Init DRRS for CRTC * @crtc: crtc * * This function is called only once at driver load to initialize basic * DRRS stuff. * */ -void intel_crtc_drrs_init(struct intel_crtc *crtc) +void intel_drrs_crtc_init(struct intel_crtc *crtc) { INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work); mutex_init(&crtc->drrs.mutex); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; } + +static int intel_drrs_debugfs_status_show(struct seq_file *m, void *unused) +{ + struct intel_crtc *crtc = m->private; + const struct intel_crtc_state *crtc_state; + int ret; + + ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex); + if (ret) + return ret; + + crtc_state = to_intel_crtc_state(crtc->base.state); + + mutex_lock(&crtc->drrs.mutex); + + seq_printf(m, "DRRS enabled: %s\n", + str_yes_no(crtc_state->has_drrs)); + + seq_printf(m, "DRRS active: %s\n", + str_yes_no(intel_drrs_is_active(crtc))); + + seq_printf(m, "DRRS refresh rate: %s\n", + crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? + "low" : "high"); + + seq_printf(m, "DRRS busy frontbuffer bits: 0x%x\n", + crtc->drrs.busy_frontbuffer_bits); + + mutex_unlock(&crtc->drrs.mutex); + + drm_modeset_unlock(&crtc->base.mutex); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(intel_drrs_debugfs_status); + +static int intel_drrs_debugfs_ctl_set(void *data, u64 val) +{ + struct intel_crtc *crtc = data; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc_state *crtc_state; + struct drm_crtc_commit *commit; + int ret; + + ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex); + if (ret) + return ret; + + crtc_state = to_intel_crtc_state(crtc->base.state); + + if (!crtc_state->hw.active || + !crtc_state->has_drrs) + goto out; + + commit = crtc_state->uapi.commit; + if (commit) { + ret = wait_for_completion_interruptible(&commit->hw_done); + if (ret) + goto out; + } + + drm_dbg(&i915->drm, + "Manually %sactivating DRRS\n", val ? "" : "de"); + + if (val) + intel_drrs_activate(crtc_state); + else + intel_drrs_deactivate(crtc_state); + +out: + drm_modeset_unlock(&crtc->base.mutex); + + return ret; +} + +DEFINE_SIMPLE_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, + NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); + +void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc) +{ + debugfs_create_file("i915_drrs_status", 0444, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_status_fops); + + debugfs_create_file("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_ctl_fops); +} + +static int intel_drrs_debugfs_type_show(struct seq_file *m, void *unused) +{ + struct intel_connector *connector = m->private; + + seq_printf(m, "DRRS type: %s\n", + intel_drrs_type_str(intel_panel_drrs_type(connector))); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(intel_drrs_debugfs_type); + +void intel_drrs_connector_debugfs_add(struct intel_connector *connector) +{ + if (intel_panel_drrs_type(connector) == DRRS_TYPE_NONE) + return; + + debugfs_create_file("i915_drrs_type", 0444, connector->base.debugfs_entry, + connector, &intel_drrs_debugfs_type_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 3ad1be1ad9c1..8ef5f93a80ff 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -23,6 +23,8 @@ void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); -void intel_crtc_drrs_init(struct intel_crtc *crtc); +void intel_drrs_crtc_init(struct intel_crtc *crtc); +void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc); +void intel_drrs_connector_debugfs_add(struct intel_connector *connector); #endif /* __INTEL_DRRS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 5572e43026e4..595087288922 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -491,8 +491,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_encoder->pipe_mask = ~0; if (dvo->type != INTEL_DVO_CHIP_LVDS) - intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) | - (1 << INTEL_OUTPUT_DVO); + intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | + BIT(INTEL_OUTPUT_DVO); switch (dvo->type) { case INTEL_DVO_CHIP_TMDS: @@ -515,8 +515,6 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) drm_connector_helper_add(connector, &intel_dvo_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; intel_connector_attach_encoder(intel_connector, intel_encoder); if (dvo->type == INTEL_DVO_CHIP_LVDS) { diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index eefa33c555ac..63137ae5ab21 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -301,6 +301,19 @@ static bool plane_caps_contain_all(u8 caps, u8 mask) } /** + * intel_fb_is_tiled_modifier: Check if a modifier is a tiled modifier type + * @modifier: Modifier to check + * + * Returns: + * Returns %true if @modifier is a tiled modifier. + */ +bool intel_fb_is_tiled_modifier(u64 modifier) +{ + return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, + INTEL_PLANE_CAP_TILING_MASK); +} + +/** * intel_fb_is_ccs_modifier: Check if a modifier is a CCS modifier type * @modifier: Modifier to check * diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 12386f13a4e0..4662b812b934 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -29,6 +29,7 @@ struct intel_plane_state; #define INTEL_PLANE_CAP_TILING_Yf BIT(5) #define INTEL_PLANE_CAP_TILING_4 BIT(6) +bool intel_fb_is_tiled_modifier(u64 modifier); bool intel_fb_is_ccs_modifier(u64 modifier); bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier); bool intel_fb_is_mc_ccs_modifier(u64 modifier); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index f38175304928..3f24f326b989 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -670,6 +670,7 @@ static void intel_fbc_nuke(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; + lockdep_assert_held(&fbc->lock); drm_WARN_ON(&i915->drm, fbc->flip_pending); trace_intel_fbc_nuke(fbc->state.plane); @@ -679,6 +680,8 @@ static void intel_fbc_nuke(struct intel_fbc *fbc) static void intel_fbc_activate(struct intel_fbc *fbc) { + lockdep_assert_held(&fbc->lock); + intel_fbc_hw_activate(fbc); intel_fbc_nuke(fbc); @@ -687,9 +690,7 @@ static void intel_fbc_activate(struct intel_fbc *fbc) static void intel_fbc_deactivate(struct intel_fbc *fbc, const char *reason) { - struct drm_i915_private *i915 = fbc->i915; - - drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); + lockdep_assert_held(&fbc->lock); if (fbc->active) intel_fbc_hw_deactivate(fbc); @@ -1009,7 +1010,8 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) { struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); - /* The use of a CPU fence is one of two ways to detect writes by the + /* + * The use of a CPU fence is one of two ways to detect writes by the * CPU to the scanout and trigger updates to the FBC. * * The other method is by software tracking (see @@ -1019,12 +1021,6 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) * Note that is possible for a tiled surface to be unmappable (and * so have no fence associated with it) due to aperture constraints * at the time of pinning. - * - * FIXME with 90/270 degree rotation we should use the fence on - * the normal GTT view (the rotated view doesn't even have a - * fence). Would need changes to the FBC fence Y offset as well. - * For now this will effectively disable FBC with 90/270 degree - * rotation. */ return DISPLAY_VER(i915) >= 9 || (plane_state->flags & PLANE_HAS_FENCE && @@ -1227,6 +1223,8 @@ static bool __intel_fbc_pre_update(struct intel_atomic_state *state, struct intel_fbc *fbc = plane->fbc; bool need_vblank_wait = false; + lockdep_assert_held(&fbc->lock); + fbc->flip_pending = true; if (intel_fbc_can_flip_nuke(state, crtc, plane)) @@ -1284,7 +1282,7 @@ static void __intel_fbc_disable(struct intel_fbc *fbc) struct drm_i915_private *i915 = fbc->i915; struct intel_plane *plane = fbc->state.plane; - drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); + lockdep_assert_held(&fbc->lock); drm_WARN_ON(&i915->drm, fbc->active); drm_dbg_kms(&i915->drm, "Disabling FBC on [PLANE:%d:%s]\n", @@ -1299,9 +1297,9 @@ static void __intel_fbc_disable(struct intel_fbc *fbc) static void __intel_fbc_post_update(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + lockdep_assert_held(&fbc->lock); - drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock)); + fbc->flip_pending = false; if (!fbc->busy_bits) intel_fbc_activate(fbc); @@ -1324,10 +1322,8 @@ void intel_fbc_post_update(struct intel_atomic_state *state, mutex_lock(&fbc->lock); - if (fbc->state.plane == plane) { - fbc->flip_pending = false; + if (fbc->state.plane == plane) __intel_fbc_post_update(fbc); - } mutex_unlock(&fbc->lock); } @@ -1437,6 +1433,8 @@ static void __intel_fbc_enable(struct intel_atomic_state *state, intel_atomic_get_new_plane_state(state, plane); struct intel_fbc *fbc = plane->fbc; + lockdep_assert_held(&fbc->lock); + if (fbc->state.plane) { if (fbc->state.plane != plane) return; @@ -1522,7 +1520,8 @@ void intel_fbc_update(struct intel_atomic_state *state, mutex_lock(&fbc->lock); - if (crtc_state->update_pipe && plane_state->no_fbc_reason) { + if (intel_crtc_needs_fastset(crtc_state) && + plane_state->no_fbc_reason) { if (fbc->state.plane == plane) __intel_fbc_disable(fbc); } else { diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 112aa0447a0d..ab385d18ddcc 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -175,7 +175,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, } if (IS_ERR(obj)) { - drm_err(&dev_priv->drm, "failed to allocate framebuffer\n"); + drm_err(&dev_priv->drm, "failed to allocate framebuffer (%pe)\n", obj); return PTR_ERR(obj); } @@ -256,7 +256,7 @@ static int intelfb_create(struct drm_fb_helper *helper, info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { - drm_err(&dev_priv->drm, "Failed to allocate fb_info\n"); + drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info); ret = PTR_ERR(info); goto out_unpin; } @@ -291,7 +291,7 @@ static int intelfb_create(struct drm_fb_helper *helper, vaddr = i915_vma_pin_iomap(vma); if (IS_ERR(vaddr)) { drm_err(&dev_priv->drm, - "Failed to remap framebuffer into virtual memory\n"); + "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); ret = PTR_ERR(vaddr); goto out_unpin; } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 18451f5d2548..02f8374ea51f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2950,9 +2950,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, ddc); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); - connector->interlace_allowed = 1; - connector->doublescan_allowed = 0; - connector->stereo_allowed = 1; + connector->interlace_allowed = true; + connector->stereo_allowed = true; if (DISPLAY_VER(dev_priv) >= 10) connector->ycbcr_420_allowed = true; diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index f7a2f485b177..907ab7526cb4 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -90,6 +90,9 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, return HPD_PORT_A + port - PORT_A; } +/* Threshold == 5 for long IRQs, 50 for short */ +#define HPD_STORM_DEFAULT_THRESHOLD 50 + #define HPD_STORM_DETECT_PERIOD 1000 #define HPD_STORM_REENABLE_DELAY (2 * 60 * 1000) #define HPD_RETRY_DELAY 1000 @@ -175,14 +178,13 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv, static void intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; bool hpd_disabled = false; lockdep_assert_held(&dev_priv->irq_lock); - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { enum hpd_pin pin; @@ -208,7 +210,7 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) /* Enable polling and queue hotplug re-enabling. */ if (hpd_disabled) { - drm_kms_helper_poll_enable(dev); + drm_kms_helper_poll_enable(&dev_priv->drm); mod_delayed_work(system_wq, &dev_priv->display.hotplug.reenable_work, msecs_to_jiffies(HPD_STORM_REENABLE_DELAY)); } @@ -219,7 +221,6 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), display.hotplug.reenable_work.work); - struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; intel_wakeref_t wakeref; @@ -229,7 +230,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) spin_lock_irq(&dev_priv->irq_lock); - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { pin = intel_connector_hpd_pin(connector); if (pin == HPD_NONE || @@ -367,14 +368,13 @@ static void i915_hotplug_work_func(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, display.hotplug.hotplug_work.work); - struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; u32 changed = 0, retry = 0; u32 hpd_event_bits; u32 hpd_retry_bits; - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); drm_dbg_kms(&dev_priv->drm, "running encoder hotplug functions\n"); spin_lock_irq(&dev_priv->irq_lock); @@ -389,7 +389,7 @@ static void i915_hotplug_work_func(struct work_struct *work) spin_unlock_irq(&dev_priv->irq_lock); - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { enum hpd_pin pin; u32 hpd_bit; @@ -426,10 +426,10 @@ static void i915_hotplug_work_func(struct work_struct *work) } } drm_connector_list_iter_end(&conn_iter); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&dev_priv->drm.mode_config.mutex); if (changed) - drm_kms_helper_hotplug_event(dev); + drm_kms_helper_hotplug_event(&dev_priv->drm); /* Remove shared HPD pins that have changed */ retry &= ~changed; @@ -612,16 +612,15 @@ static void i915_hpd_poll_init_work(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, display.hotplug.poll_init_work); - struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; bool enabled; - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); enabled = READ_ONCE(dev_priv->display.hotplug.poll_enabled); - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { enum hpd_pin pin; @@ -638,16 +637,16 @@ static void i915_hpd_poll_init_work(struct work_struct *work) drm_connector_list_iter_end(&conn_iter); if (enabled) - drm_kms_helper_poll_enable(dev); + drm_kms_helper_poll_enable(&dev_priv->drm); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&dev_priv->drm.mode_config.mutex); /* * We might have missed any hotplugs that happened while we were * in the middle of disabling polling */ if (!enabled) - drm_helper_hpd_irq_event(dev); + drm_helper_hpd_irq_event(&dev_priv->drm); } /** @@ -711,14 +710,23 @@ void intel_hpd_poll_disable(struct drm_i915_private *dev_priv) schedule_work(&dev_priv->display.hotplug.poll_init_work); } -void intel_hpd_init_work(struct drm_i915_private *dev_priv) +void intel_hpd_init_early(struct drm_i915_private *i915) { - INIT_DELAYED_WORK(&dev_priv->display.hotplug.hotplug_work, + INIT_DELAYED_WORK(&i915->display.hotplug.hotplug_work, i915_hotplug_work_func); - INIT_WORK(&dev_priv->display.hotplug.dig_port_work, i915_digport_work_func); - INIT_WORK(&dev_priv->display.hotplug.poll_init_work, i915_hpd_poll_init_work); - INIT_DELAYED_WORK(&dev_priv->display.hotplug.reenable_work, + INIT_WORK(&i915->display.hotplug.dig_port_work, i915_digport_work_func); + INIT_WORK(&i915->display.hotplug.poll_init_work, i915_hpd_poll_init_work); + INIT_DELAYED_WORK(&i915->display.hotplug.reenable_work, intel_hpd_irq_storm_reenable_work); + + i915->display.hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; + /* If we have MST support, we want to avoid doing short HPD IRQ storm + * detection, as short HPD storms will occur as a natural part of + * sideband messaging with MST. + * On older platforms however, IRQ storms can occur with both long and + * short pulses, as seen on some G4x systems. + */ + i915->display.hotplug.hpd_short_storm_enabled = !HAS_DP_MST(i915); } void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) @@ -767,3 +775,169 @@ void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin) dev_priv->display.hotplug.stats[pin].state = HPD_ENABLED; spin_unlock_irq(&dev_priv->irq_lock); } + +static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) +{ + struct drm_i915_private *dev_priv = m->private; + struct intel_hotplug *hotplug = &dev_priv->display.hotplug; + + /* Synchronize with everything first in case there's been an HPD + * storm, but we haven't finished handling it in the kernel yet + */ + intel_synchronize_irq(dev_priv); + flush_work(&dev_priv->display.hotplug.dig_port_work); + flush_delayed_work(&dev_priv->display.hotplug.hotplug_work); + + seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold); + seq_printf(m, "Detected: %s\n", + str_yes_no(delayed_work_pending(&hotplug->reenable_work))); + + return 0; +} + +static ssize_t i915_hpd_storm_ctl_write(struct file *file, + const char __user *ubuf, size_t len, + loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_i915_private *dev_priv = m->private; + struct intel_hotplug *hotplug = &dev_priv->display.hotplug; + unsigned int new_threshold; + int i; + char *newline; + char tmp[16]; + + if (len >= sizeof(tmp)) + return -EINVAL; + + if (copy_from_user(tmp, ubuf, len)) + return -EFAULT; + + tmp[len] = '\0'; + + /* Strip newline, if any */ + newline = strchr(tmp, '\n'); + if (newline) + *newline = '\0'; + + if (strcmp(tmp, "reset") == 0) + new_threshold = HPD_STORM_DEFAULT_THRESHOLD; + else if (kstrtouint(tmp, 10, &new_threshold) != 0) + return -EINVAL; + + if (new_threshold > 0) + drm_dbg_kms(&dev_priv->drm, + "Setting HPD storm detection threshold to %d\n", + new_threshold); + else + drm_dbg_kms(&dev_priv->drm, "Disabling HPD storm detection\n"); + + spin_lock_irq(&dev_priv->irq_lock); + hotplug->hpd_storm_threshold = new_threshold; + /* Reset the HPD storm stats so we don't accidentally trigger a storm */ + for_each_hpd_pin(i) + hotplug->stats[i].count = 0; + spin_unlock_irq(&dev_priv->irq_lock); + + /* Re-enable hpd immediately if we were in an irq storm */ + flush_delayed_work(&dev_priv->display.hotplug.reenable_work); + + return len; +} + +static int i915_hpd_storm_ctl_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_hpd_storm_ctl_show, inode->i_private); +} + +static const struct file_operations i915_hpd_storm_ctl_fops = { + .owner = THIS_MODULE, + .open = i915_hpd_storm_ctl_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_hpd_storm_ctl_write +}; + +static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data) +{ + struct drm_i915_private *dev_priv = m->private; + + seq_printf(m, "Enabled: %s\n", + str_yes_no(dev_priv->display.hotplug.hpd_short_storm_enabled)); + + return 0; +} + +static int +i915_hpd_short_storm_ctl_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_hpd_short_storm_ctl_show, + inode->i_private); +} + +static ssize_t i915_hpd_short_storm_ctl_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_i915_private *dev_priv = m->private; + struct intel_hotplug *hotplug = &dev_priv->display.hotplug; + char *newline; + char tmp[16]; + int i; + bool new_state; + + if (len >= sizeof(tmp)) + return -EINVAL; + + if (copy_from_user(tmp, ubuf, len)) + return -EFAULT; + + tmp[len] = '\0'; + + /* Strip newline, if any */ + newline = strchr(tmp, '\n'); + if (newline) + *newline = '\0'; + + /* Reset to the "default" state for this system */ + if (strcmp(tmp, "reset") == 0) + new_state = !HAS_DP_MST(dev_priv); + else if (kstrtobool(tmp, &new_state) != 0) + return -EINVAL; + + drm_dbg_kms(&dev_priv->drm, "%sabling HPD short storm detection\n", + new_state ? "En" : "Dis"); + + spin_lock_irq(&dev_priv->irq_lock); + hotplug->hpd_short_storm_enabled = new_state; + /* Reset the HPD storm stats so we don't accidentally trigger a storm */ + for_each_hpd_pin(i) + hotplug->stats[i].count = 0; + spin_unlock_irq(&dev_priv->irq_lock); + + /* Re-enable hpd immediately if we were in an irq storm */ + flush_delayed_work(&dev_priv->display.hotplug.reenable_work); + + return len; +} + +static const struct file_operations i915_hpd_short_storm_ctl_fops = { + .owner = THIS_MODULE, + .open = i915_hpd_short_storm_ctl_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_hpd_short_storm_ctl_write, +}; + +void intel_hpd_debugfs_register(struct drm_i915_private *i915) +{ + struct drm_minor *minor = i915->drm.primary; + + debugfs_create_file("i915_hpd_storm_ctl", 0644, minor->debugfs_root, + i915, &i915_hpd_storm_ctl_fops); + debugfs_create_file("i915_hpd_short_storm_ctl", 0644, minor->debugfs_root, + i915, &i915_hpd_short_storm_ctl_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h index b87e95d606e6..424ae5dbf5a0 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.h +++ b/drivers/gpu/drm/i915/display/intel_hotplug.h @@ -22,11 +22,12 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 pin_mask, u32 long_mask); void intel_hpd_trigger_irq(struct intel_digital_port *dig_port); void intel_hpd_init(struct drm_i915_private *dev_priv); -void intel_hpd_init_work(struct drm_i915_private *dev_priv); +void intel_hpd_init_early(struct drm_i915_private *i915); void intel_hpd_cancel_work(struct drm_i915_private *dev_priv); enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, enum port port); bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin); void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin); +void intel_hpd_debugfs_register(struct drm_i915_private *i915); #endif /* __INTEL_HOTPLUG_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index dca6003ccac8..6a7ac60e4f76 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -80,8 +80,7 @@ static struct platform_device * lpe_audio_platdev_create(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; - struct pci_dev *pdev = to_pci_dev(dev->dev); + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct platform_device_info pinfo = {}; struct resource *rsc; struct platform_device *platdev; @@ -108,7 +107,7 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) rsc[1].flags = IORESOURCE_MEM; rsc[1].name = "hdmi-lpe-audio-mmio"; - pinfo.parent = dev->dev; + pinfo.parent = dev_priv->drm.dev; pinfo.name = "hdmi-lpe-audio"; pinfo.id = -1; pinfo.res = rsc; diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 9aa38e8141b5..246787bbf5ef 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -78,9 +78,9 @@ struct intel_lvds_encoder { struct intel_connector *attached_connector; }; -static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder) +static struct intel_lvds_encoder *to_lvds_encoder(struct intel_encoder *encoder) { - return container_of(encoder, struct intel_lvds_encoder, base.base); + return container_of(encoder, struct intel_lvds_encoder, base); } bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv, @@ -103,7 +103,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); + struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder); intel_wakeref_t wakeref; bool ret; @@ -123,7 +123,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); + struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder); u32 tmp, flags = 0; pipe_config->output_types |= BIT(INTEL_OUTPUT_LVDS); @@ -229,7 +229,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); + struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; @@ -312,7 +312,7 @@ static void intel_enable_lvds(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; - struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); + struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder); struct drm_i915_private *dev_priv = to_i915(dev); intel_de_write(dev_priv, lvds_encoder->reg, @@ -334,7 +334,7 @@ static void intel_disable_lvds(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); + struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); intel_de_write(dev_priv, PP_CONTROL(0), @@ -413,7 +413,7 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder, { struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); struct intel_lvds_encoder *lvds_encoder = - to_lvds_encoder(&intel_encoder->base); + to_lvds_encoder(intel_encoder); struct intel_connector *intel_connector = lvds_encoder->attached_connector; struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; @@ -775,7 +775,7 @@ bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder = intel_get_lvds_encoder(dev_priv); - return encoder && to_lvds_encoder(&encoder->base)->is_dual_link; + return encoder && to_lvds_encoder(encoder)->is_dual_link; } static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) @@ -814,6 +814,11 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; } +static void intel_lvds_add_properties(struct drm_connector *connector) +{ + intel_attach_scaling_mode_property(connector); +} + /** * intel_lvds_init - setup LVDS connectors on this device * @dev_priv: i915 device @@ -823,7 +828,6 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) */ void intel_lvds_init(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_lvds_encoder *lvds_encoder; struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; @@ -833,11 +837,10 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) i915_reg_t lvds_reg; u32 lvds; u8 pin; - u32 allowed_scalers; /* Skip init on machines we know falsely report LVDS */ if (dmi_check_system(intel_no_lvds)) { - drm_WARN(dev, !dev_priv->display.vbt.int_lvds_support, + drm_WARN(&dev_priv->drm, !dev_priv->display.vbt.int_lvds_support, "Useless DMI match. Internal LVDS support disabled by VBT\n"); return; } @@ -886,10 +889,10 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) intel_encoder = &lvds_encoder->base; encoder = &intel_encoder->base; connector = &intel_connector->base; - drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, + drm_connector_init(&dev_priv->drm, &intel_connector->base, &intel_lvds_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs, + drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS, "LVDS"); intel_encoder->enable = intel_enable_lvds; @@ -920,17 +923,10 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; lvds_encoder->reg = lvds_reg; - /* create the scaling mode property */ - allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT); - allowed_scalers |= BIT(DRM_MODE_SCALE_FULLSCREEN); - allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER); - drm_connector_attach_scaling_mode_property(connector, allowed_scalers); - connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT; + intel_lvds_add_properties(connector); intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps); lvds_encoder->init_lvds_val = lvds; @@ -947,7 +943,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) * Attempt to get the fixed panel mode from DDC. Assume that the * preferred mode is the right one. */ - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) edid = drm_get_edid_switcheroo(connector, intel_gmbus_get_adapter(dev_priv, pin)); @@ -971,9 +967,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) IS_ERR(edid) ? NULL : edid); /* Try EDID first */ - intel_panel_add_edid_fixed_modes(intel_connector, - intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, - false); + intel_panel_add_edid_fixed_modes(intel_connector, true); /* Failed to get EDID, what about VBT? */ if (!intel_panel_preferred_fixed_mode(intel_connector)) @@ -987,7 +981,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) if (!intel_panel_preferred_fixed_mode(intel_connector)) intel_panel_add_encoder_fixed_mode(intel_connector, intel_encoder); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&dev_priv->drm.mode_config.mutex); /* If we still don't have a mode after all that, give up. */ if (!intel_panel_preferred_fixed_mode(intel_connector)) diff --git a/drivers/gpu/drm/i915/display/intel_tc_phy_regs.h b/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h index 5a545086f959..07978f8d5fb7 100644 --- a/drivers/gpu/drm/i915/display/intel_tc_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef __INTEL_TC_PHY_REGS__ -#define __INTEL_TC_PHY_REGS__ +#ifndef __INTEL_MG_PHY_REGS__ +#define __INTEL_MG_PHY_REGS__ #include "i915_reg_defs.h" @@ -277,4 +277,4 @@ _MG_PLL_TDC_COLDST_BIAS_PORT1, \ _MG_PLL_TDC_COLDST_BIAS_PORT2) -#endif /* __INTEL_TC_PHY_REGS__ */ +#endif /* __INTEL_MG_PHY_REGS__ */ diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index cbfabd58b75a..9d8ca230be39 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -155,6 +155,12 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; + /* assume 1:1 mapping */ + drm_property_replace_blob(&crtc_state->hw.degamma_lut, + crtc_state->pre_csc_lut); + drm_property_replace_blob(&crtc_state->hw.gamma_lut, + crtc_state->post_csc_lut); + drm_property_replace_blob(&crtc_state->uapi.degamma_lut, crtc_state->hw.degamma_lut); drm_property_replace_blob(&crtc_state->uapi.gamma_lut, @@ -205,13 +211,21 @@ static bool intel_crtc_has_encoders(struct intel_crtc *crtc) static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_connector_list_iter conn_iter; struct intel_connector *connector; + struct intel_connector *found_connector = NULL; - for_each_connector_on_encoder(dev, &encoder->base, connector) - return connector; + drm_connector_list_iter_begin(&i915->drm, &conn_iter); + for_each_intel_connector_iter(connector, &conn_iter) { + if (&encoder->base == connector->base.encoder) { + found_connector = connector; + break; + } + } + drm_connector_list_iter_end(&conn_iter); - return NULL; + return found_connector; } static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index 0fdcf2e6d57f..842d70f0dfd2 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -227,7 +227,8 @@ void intel_modeset_verify_crtc(struct intel_crtc *crtc, struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state) { - if (!intel_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe) + if (!intel_crtc_needs_modeset(new_crtc_state) && + !intel_crtc_needs_fastset(new_crtc_state)) return; intel_wm_state_verify(crtc, new_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index caa07ef34f21..e0184745632c 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -463,7 +463,6 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp) struct intel_connector *connector; struct drm_connector_list_iter conn_iter; struct opregion_asle *asle = dev_priv->display.opregion.asle; - struct drm_device *dev = &dev_priv->drm; drm_dbg(&dev_priv->drm, "bclp = 0x%08x\n", bclp); @@ -480,7 +479,7 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp) if (bclp > 255) return ASLC_BACKLIGHT_FAILED; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, NULL); /* * Update backlight on all connectors that support backlight (usually @@ -488,13 +487,13 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp) */ drm_dbg_kms(&dev_priv->drm, "updating opregion backlight %d/255\n", bclp); - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) intel_backlight_set_acpi(connector->base.state, bclp, 255); drm_connector_list_iter_end(&conn_iter); asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID; - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex); return 0; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index a3a3f9fe4342..69ce77711b7c 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -85,9 +85,10 @@ static bool is_alt_drrs_mode(const struct drm_display_mode *mode, static bool is_alt_fixed_mode(const struct drm_display_mode *mode, const struct drm_display_mode *preferred_mode) { - return drm_mode_match(mode, preferred_mode, - DRM_MODE_MATCH_FLAGS | - DRM_MODE_MATCH_3D_FLAGS) && + u32 sync_flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | + DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC; + + return (mode->flags & ~sync_flags) == (preferred_mode->flags & ~sync_flags) && mode->hdisplay == preferred_mode->hdisplay && mode->vdisplay == preferred_mode->vdisplay; } @@ -147,12 +148,24 @@ int intel_panel_get_modes(struct intel_connector *connector) return num_modes; } -enum drrs_type intel_panel_drrs_type(struct intel_connector *connector) +static bool has_drrs_modes(struct intel_connector *connector) { - if (list_empty(&connector->panel.fixed_modes) || - list_is_singular(&connector->panel.fixed_modes)) - return DRRS_TYPE_NONE; + const struct drm_display_mode *mode1; + + list_for_each_entry(mode1, &connector->panel.fixed_modes, head) { + const struct drm_display_mode *mode2 = mode1; + + list_for_each_entry_continue(mode2, &connector->panel.fixed_modes, head) { + if (is_alt_drrs_mode(mode1, mode2)) + return true; + } + } + + return false; +} +enum drrs_type intel_panel_drrs_type(struct intel_connector *connector) +{ return connector->panel.vbt.drrs_type; } @@ -254,10 +267,10 @@ static void intel_panel_destroy_probed_modes(struct intel_connector *connector) } void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, - bool has_drrs, bool has_vrr) + bool use_alt_fixed_modes) { intel_panel_add_edid_preferred_mode(connector); - if (intel_panel_preferred_fixed_mode(connector) && (has_drrs || has_vrr)) + if (intel_panel_preferred_fixed_mode(connector) && use_alt_fixed_modes) intel_panel_add_edid_alt_fixed_modes(connector); intel_panel_destroy_probed_modes(connector); } @@ -653,6 +666,9 @@ int intel_panel_init(struct intel_connector *connector) intel_backlight_init_funcs(panel); + if (!has_drrs_modes(connector)) + connector->panel.vbt.drrs_type = DRRS_TYPE_NONE; + drm_dbg_kms(connector->base.dev, "[CONNECTOR:%d:%s] DRRS type: %s\n", connector->base.base.id, connector->base.name, diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index eff3ffd3d082..5c5b5b7f95b6 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -44,7 +44,7 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state, int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode); void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, - bool has_drrs, bool has_vrr); + bool use_alt_fixed_modes); void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector); void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector); void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index 8ac263f471be..1c74388c60d7 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -75,7 +75,6 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, enum pipe pipe, enum intel_pipe_crc_source *source) { - struct drm_device *dev = &dev_priv->drm; struct intel_encoder *encoder; struct intel_crtc *crtc; struct intel_digital_port *dig_port; @@ -83,8 +82,8 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, *source = INTEL_PIPE_CRC_SOURCE_PIPE; - drm_modeset_lock_all(dev); - for_each_intel_encoder(dev, encoder) { + drm_modeset_lock_all(&dev_priv->drm); + for_each_intel_encoder(&dev_priv->drm, encoder) { if (!encoder->base.crtc) continue; @@ -111,7 +110,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, *source = INTEL_PIPE_CRC_SOURCE_DP_D; break; default: - drm_WARN(dev, 1, "nonexisting DP port %c\n", + drm_WARN(&dev_priv->drm, 1, "nonexisting DP port %c\n", port_name(dig_port->base.port)); break; } @@ -120,7 +119,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, break; } } - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d4cce627d7a8..904a1049eff3 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -533,7 +533,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT; - if (!IS_ALDERLAKE_P(dev_priv)) + if (DISPLAY_VER(dev_priv) <= 13 && !IS_ALDERLAKE_P(dev_priv)) val |= EDP_SU_TRACK_ENABLE; if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12) @@ -616,7 +616,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) static bool transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder trans) { - if (IS_ALDERLAKE_P(dev_priv)) + if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) return trans == TRANSCODER_A || trans == TRANSCODER_B; else if (DISPLAY_VER(dev_priv) >= 12) return trans == TRANSCODER_A; @@ -696,7 +696,7 @@ dc3co_is_pipe_port_compatible(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum port port = dig_port->base.port; - if (IS_ALDERLAKE_P(dev_priv)) + if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) return pipe <= PIPE_B && port <= PORT_B; else return pipe == PIPE_A && port == PORT_A; @@ -795,11 +795,11 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp, return intel_dp->psr.su_y_granularity == 4; /* - * adl_p has 1 line granularity. For other platforms with SW tracking we - * can adjust the y coordinates to match sink requirement if multiple of - * 4. + * adl_p and display 14+ platforms has 1 line granularity. + * For other platforms with SW tracking we can adjust the y coordinates + * to match sink requirement if multiple of 4. */ - if (IS_ALDERLAKE_P(dev_priv)) + if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) y_granularity = intel_dp->psr.su_y_granularity; else if (intel_dp->psr.su_y_granularity <= 2) y_granularity = 4; @@ -883,7 +883,8 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, * resolution requires DSC to be enabled, priority is given to DSC * over PSR2. */ - if (crtc_state->dsc.compression_enable) { + if (crtc_state->dsc.compression_enable && + (DISPLAY_VER(dev_priv) <= 13 && !IS_ALDERLAKE_P(dev_priv))) { drm_dbg_kms(&dev_priv->drm, "PSR2 cannot be enabled since DSC is enabled\n"); return false; @@ -1474,7 +1475,7 @@ static u32 man_trk_ctl_enable_bit_get(struct drm_i915_private *dev_priv) static u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv) { - return IS_ALDERLAKE_P(dev_priv) ? + return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ? ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME : PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME; } @@ -1627,7 +1628,7 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, if (clip->y1 == -1) goto exit; - if (IS_ALDERLAKE_P(dev_priv)) { + if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) { val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1); val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 - 1); } else { @@ -1664,7 +1665,15 @@ static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *c struct drm_rect *pipe_clip) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - const u16 y_alignment = crtc_state->su_y_granularity; + const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + u16 y_alignment; + + /* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */ + if (crtc_state->dsc.compression_enable && + (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)) + y_alignment = vdsc_cfg->slice_height; + else + y_alignment = crtc_state->su_y_granularity; pipe_clip->y1 -= pipe_clip->y1 % y_alignment; if (pipe_clip->y2 % y_alignment) @@ -2054,13 +2063,12 @@ static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp) static int intel_psr_fastset_force(struct drm_i915_private *dev_priv) { struct drm_connector_list_iter conn_iter; - struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx ctx; struct drm_atomic_state *state; struct drm_connector *conn; int err = 0; - state = drm_atomic_state_alloc(dev); + state = drm_atomic_state_alloc(&dev_priv->drm); if (!state) return -ENOMEM; @@ -2069,7 +2077,7 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv) retry: - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); drm_for_each_connector_iter(conn, &conn_iter) { struct drm_connector_state *conn_state; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index f5b744bef18f..48b7b1aa37b2 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -199,7 +199,7 @@ to_intel_sdvo_connector(struct drm_connector *connector) container_of((conn_state), struct intel_sdvo_connector_state, base.base) static bool -intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags); +intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo); static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, @@ -1297,13 +1297,28 @@ static bool intel_sdvo_limited_color_range(struct intel_encoder *encoder, return intel_hdmi_limited_color_range(crtc_state, conn_state); } +static bool intel_sdvo_has_audio(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_sdvo *intel_sdvo = to_sdvo(encoder); + const struct intel_digital_connector_state *intel_conn_state = + to_intel_digital_connector_state(conn_state); + + if (!crtc_state->has_hdmi_sink) + return false; + + if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) + return intel_sdvo->has_hdmi_audio; + else + return intel_conn_state->force_audio == HDMI_AUDIO_ON; +} + static int intel_sdvo_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { struct intel_sdvo *intel_sdvo = to_sdvo(encoder); - struct intel_sdvo_connector_state *intel_sdvo_state = - to_intel_sdvo_connector_state(conn_state); struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(conn_state->connector); struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; @@ -1362,13 +1377,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, conn_state); - if (pipe_config->has_hdmi_sink) { - if (intel_sdvo_state->base.force_audio == HDMI_AUDIO_AUTO) - pipe_config->has_audio = intel_sdvo->has_hdmi_audio; - else - pipe_config->has_audio = - intel_sdvo_state->base.force_audio == HDMI_AUDIO_ON; - } + pipe_config->has_audio = intel_sdvo_has_audio(encoder, pipe_config, conn_state); pipe_config->limited_color_range = intel_sdvo_limited_color_range(encoder, pipe_config, @@ -2290,17 +2299,12 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector) static int intel_sdvo_get_lvds_modes(struct drm_connector *connector) { - struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector)); struct drm_i915_private *dev_priv = to_i915(connector->dev); - int num_modes = 0; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - num_modes += intel_panel_get_modes(to_intel_connector(connector)); - num_modes += intel_ddc_get_modes(connector, &intel_sdvo->ddc); - - return num_modes; + return intel_panel_get_modes(to_intel_connector(connector)); } static int intel_sdvo_get_modes(struct drm_connector *connector) @@ -2627,7 +2631,7 @@ intel_sdvo_unselect_i2c_bus(struct intel_sdvo *sdvo) } static bool -intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device) +intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo) { return intel_sdvo_check_supp_encode(intel_sdvo); } @@ -2689,9 +2693,8 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector, drm_connector_helper_add(drm_connector, &intel_sdvo_connector_helper_funcs); - connector->base.base.interlace_allowed = 1; - connector->base.base.doublescan_allowed = 0; connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; + connector->base.base.interlace_allowed = true; connector->base.get_hw_state = intel_sdvo_connector_get_hw_state; intel_connector_attach_encoder(&connector->base, &encoder->base); @@ -2733,7 +2736,7 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) } static bool -intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) +intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, u16 type) { struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; @@ -2741,19 +2744,13 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising DVI device %d\n", device); + DRM_DEBUG_KMS("initialising DVI type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) return false; - if (device == 0) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0; - intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0; - } else if (device == 1) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1; - intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1; - } + intel_sdvo_connector->output_flag = type; intel_connector = &intel_sdvo_connector->base; connector = &intel_connector->base; @@ -2773,7 +2770,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) encoder->encoder_type = DRM_MODE_ENCODER_TMDS; connector->connector_type = DRM_MODE_CONNECTOR_DVID; - if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) { + if (intel_sdvo_is_hdmi_connector(intel_sdvo)) { connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; intel_sdvo_connector->is_hdmi = true; } @@ -2790,14 +2787,14 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) } static bool -intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) +intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, u16 type) { struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising TV type %d\n", type); + DRM_DEBUG_KMS("initialising TV type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2808,7 +2805,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; - intel_sdvo->controlled_output |= type; intel_sdvo_connector->output_flag = type; if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { @@ -2830,14 +2826,14 @@ err: } static bool -intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) +intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, u16 type) { struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising analog device %d\n", device); + DRM_DEBUG_KMS("initialising analog type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2849,13 +2845,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) encoder->encoder_type = DRM_MODE_ENCODER_DAC; connector->connector_type = DRM_MODE_CONNECTOR_VGA; - if (device == 0) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; - intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; - } else if (device == 1) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; - intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; - } + intel_sdvo_connector->output_flag = type; if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { kfree(intel_sdvo_connector); @@ -2866,7 +2856,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) } static bool -intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) +intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type) { struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_i915_private *i915 = to_i915(encoder->dev); @@ -2874,7 +2864,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising LVDS device %d\n", device); + DRM_DEBUG_KMS("initialising LVDS type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2885,13 +2875,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) encoder->encoder_type = DRM_MODE_ENCODER_LVDS; connector->connector_type = DRM_MODE_CONNECTOR_LVDS; - if (device == 0) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; - intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; - } else if (device == 1) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; - intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; - } + intel_sdvo_connector->output_flag = type; if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { kfree(intel_sdvo_connector); @@ -2910,8 +2894,12 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) intel_panel_add_vbt_sdvo_fixed_mode(intel_connector); if (!intel_panel_preferred_fixed_mode(intel_connector)) { + mutex_lock(&i915->drm.mode_config.mutex); + intel_ddc_get_modes(connector, &intel_sdvo->ddc); - intel_panel_add_edid_fixed_modes(intel_connector, false, false); + intel_panel_add_edid_fixed_modes(intel_connector, false); + + mutex_unlock(&i915->drm.mode_config.mutex); } intel_panel_init(intel_connector); @@ -2926,58 +2914,78 @@ err: return false; } -static bool -intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags) +static u16 intel_sdvo_filter_output_flags(u16 flags) { + flags &= SDVO_OUTPUT_MASK; + /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ + if (!(flags & SDVO_OUTPUT_TMDS0)) + flags &= ~SDVO_OUTPUT_TMDS1; - if (flags & SDVO_OUTPUT_TMDS0) - if (!intel_sdvo_dvi_init(intel_sdvo, 0)) - return false; + if (!(flags & SDVO_OUTPUT_RGB0)) + flags &= ~SDVO_OUTPUT_RGB1; - if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK) - if (!intel_sdvo_dvi_init(intel_sdvo, 1)) - return false; + if (!(flags & SDVO_OUTPUT_LVDS0)) + flags &= ~SDVO_OUTPUT_LVDS1; - /* TV has no XXX1 function block */ - if (flags & SDVO_OUTPUT_SVID0) - if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_SVID0)) - return false; + return flags; +} - if (flags & SDVO_OUTPUT_CVBS0) - if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_CVBS0)) - return false; +static bool intel_sdvo_output_init(struct intel_sdvo *sdvo, u16 type) +{ + if (type & SDVO_TMDS_MASK) + return intel_sdvo_dvi_init(sdvo, type); + else if (type & SDVO_TV_MASK) + return intel_sdvo_tv_init(sdvo, type); + else if (type & SDVO_RGB_MASK) + return intel_sdvo_analog_init(sdvo, type); + else if (type & SDVO_LVDS_MASK) + return intel_sdvo_lvds_init(sdvo, type); + else + return false; +} - if (flags & SDVO_OUTPUT_YPRPB0) - if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_YPRPB0)) - return false; +static bool +intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo) +{ + static const u16 probe_order[] = { + SDVO_OUTPUT_TMDS0, + SDVO_OUTPUT_TMDS1, + /* TV has no XXX1 function block */ + SDVO_OUTPUT_SVID0, + SDVO_OUTPUT_CVBS0, + SDVO_OUTPUT_YPRPB0, + SDVO_OUTPUT_RGB0, + SDVO_OUTPUT_RGB1, + SDVO_OUTPUT_LVDS0, + SDVO_OUTPUT_LVDS1, + }; + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); + u16 flags; + int i; - if (flags & SDVO_OUTPUT_RGB0) - if (!intel_sdvo_analog_init(intel_sdvo, 0)) - return false; + flags = intel_sdvo_filter_output_flags(intel_sdvo->caps.output_flags); - if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK) - if (!intel_sdvo_analog_init(intel_sdvo, 1)) - return false; + if (flags == 0) { + DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%04x)\n", + SDVO_NAME(intel_sdvo), intel_sdvo->caps.output_flags); + return false; + } - if (flags & SDVO_OUTPUT_LVDS0) - if (!intel_sdvo_lvds_init(intel_sdvo, 0)) - return false; + intel_sdvo->controlled_output = flags; - if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK) - if (!intel_sdvo_lvds_init(intel_sdvo, 1)) - return false; + intel_sdvo_select_ddc_bus(i915, intel_sdvo); - if ((flags & SDVO_OUTPUT_MASK) == 0) { - unsigned char bytes[2]; + for (i = 0; i < ARRAY_SIZE(probe_order); i++) { + u16 type = flags & probe_order[i]; - intel_sdvo->controlled_output = 0; - memcpy(bytes, &intel_sdvo->caps.output_flags, 2); - DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n", - SDVO_NAME(intel_sdvo), - bytes[0], bytes[1]); - return false; + if (!type) + continue; + + if (!intel_sdvo_output_init(intel_sdvo, type)) + return false; } + intel_sdvo->base.pipe_mask = ~0; return true; @@ -3353,8 +3361,7 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, intel_sdvo->colorimetry_cap = intel_sdvo_get_colorimetry_cap(intel_sdvo); - if (intel_sdvo_output_setup(intel_sdvo, - intel_sdvo->caps.output_flags) != true) { + if (!intel_sdvo_output_setup(intel_sdvo)) { drm_dbg_kms(&dev_priv->drm, "SDVO output failed to setup on %s\n", SDVO_NAME(intel_sdvo)); @@ -3383,8 +3390,6 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, */ intel_sdvo->base.cloneable = 0; - intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo); - /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) goto err_output; @@ -3407,9 +3412,12 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, (intel_sdvo->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', /* check currently supported outputs */ intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', + (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0 | + SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_SVID0 | + SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB0) ? 'Y' : 'N', intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); + (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1 | + SDVO_OUTPUT_LVDS1) ? 'Y' : 'N'); return true; err_output: diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index e5af955b5600..70624b4b2d38 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -8,9 +8,10 @@ #include "intel_display.h" #include "intel_display_power_map.h" #include "intel_display_types.h" +#include "intel_dkl_phy_regs.h" #include "intel_dp_mst.h" +#include "intel_mg_phy_regs.h" #include "intel_tc.h" -#include "intel_tc_phy_regs.h" static const char *tc_port_mode_name(enum tc_port_mode mode) { @@ -408,14 +409,9 @@ static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port, struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct intel_uncore *uncore = &i915->uncore; enum port port = dig_port->base.port; - u32 val; - val = intel_uncore_read(uncore, DDI_BUF_CTL(port)); - if (take) - val |= DDI_BUF_CTL_TC_PHY_OWNERSHIP; - else - val &= ~DDI_BUF_CTL_TC_PHY_OWNERSHIP; - intel_uncore_write(uncore, DDI_BUF_CTL(port), val); + intel_uncore_rmw(uncore, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, + take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); return true; } @@ -687,18 +683,58 @@ static void intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port, int refcount) { + dig_port->tc_link_refcount = refcount; +} + +/** + * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode + * @dig_port: digital port + * + * Read out the HW state and initialize the TypeC mode of @dig_port. The mode + * will be locked until intel_tc_port_sanitize_mode() is called. + */ +void intel_tc_port_init_mode(struct intel_digital_port *dig_port) +{ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + intel_wakeref_t tc_cold_wref; + enum intel_display_power_domain domain; + + mutex_lock(&dig_port->tc_lock); + drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED); + drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref); drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount); - dig_port->tc_link_refcount = refcount; + + tc_cold_wref = tc_cold_block(dig_port, &domain); + + dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); + /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ + intel_tc_port_link_init_refcount(dig_port, 1); + dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); + + tc_cold_unblock(dig_port, domain, tc_cold_wref); + + drm_dbg_kms(&i915->drm, "Port %s: init mode (%s)\n", + dig_port->tc_port_name, + tc_port_mode_name(dig_port->tc_mode)); + + mutex_unlock(&dig_port->tc_lock); } -void intel_tc_port_sanitize(struct intel_digital_port *dig_port) +/** + * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode + * @dig_port: digital port + * + * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver + * loading and system resume: + * If the encoder is enabled keep the TypeC mode/PHY connected state locked until + * the encoder is disabled. + * If the encoder is disabled make sure the PHY is disconnected. + */ +void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct intel_encoder *encoder = &dig_port->base; - intel_wakeref_t tc_cold_wref; - enum intel_display_power_domain domain; int active_links = 0; mutex_lock(&dig_port->tc_lock); @@ -708,21 +744,14 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port) else if (encoder->base.crtc) active_links = to_intel_crtc(encoder->base.crtc)->active; - drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED); - drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref); - - tc_cold_wref = tc_cold_block(dig_port, &domain); + drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount != 1); + intel_tc_port_link_init_refcount(dig_port, active_links); - dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); if (active_links) { if (!icl_tc_phy_is_connected(dig_port)) drm_dbg_kms(&i915->drm, "Port %s: PHY disconnected with %d active link(s)\n", dig_port->tc_port_name, active_links); - intel_tc_port_link_init_refcount(dig_port, active_links); - - dig_port->tc_lock_wakeref = tc_cold_block(dig_port, - &dig_port->tc_lock_power_domain); } else { /* * TBT-alt is the default mode in any case the PHY ownership is not @@ -736,9 +765,10 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port) dig_port->tc_port_name, tc_port_mode_name(dig_port->tc_mode)); icl_tc_phy_disconnect(dig_port); - } - tc_cold_unblock(dig_port, domain, tc_cold_wref); + tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, + fetch_and_zero(&dig_port->tc_lock_wakeref)); + } drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", dig_port->tc_port_name, @@ -923,4 +953,6 @@ void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) dig_port->tc_mode = TC_PORT_DISCONNECTED; dig_port->tc_link_refcount = 0; tc_port_load_fia_params(i915, dig_port); + + intel_tc_port_init_mode(dig_port); } diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h index 6b47b29f551c..d54082e2d5e8 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.h +++ b/drivers/gpu/drm/i915/display/intel_tc.h @@ -24,7 +24,8 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port); void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, int required_lanes); -void intel_tc_port_sanitize(struct intel_digital_port *dig_port); +void intel_tc_port_init_mode(struct intel_digital_port *dig_port); +void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port); void intel_tc_port_lock(struct intel_digital_port *dig_port); void intel_tc_port_unlock(struct intel_digital_port *dig_port); void intel_tc_port_flush_work(struct intel_digital_port *dig_port); diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index dcf89d701f0f..cf7d5c1ab406 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1880,18 +1880,56 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = { .destroy = intel_encoder_destroy, }; +static void intel_tv_add_properties(struct drm_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->dev); + struct drm_connector_state *conn_state = connector->state; + const char *tv_format_names[ARRAY_SIZE(tv_modes)]; + int i; + + /* BIOS margin values */ + conn_state->tv.margins.left = 54; + conn_state->tv.margins.top = 36; + conn_state->tv.margins.right = 46; + conn_state->tv.margins.bottom = 37; + + conn_state->tv.mode = 0; + + /* Create TV properties then attach current values */ + for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { + /* 1080p50/1080p60 not supported on gen3 */ + if (DISPLAY_VER(i915) == 3 && tv_modes[i].oversample == 1) + break; + + tv_format_names[i] = tv_modes[i].name; + } + drm_mode_create_tv_properties(&i915->drm, i, tv_format_names); + + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tv_mode_property, + conn_state->tv.mode); + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tv_left_margin_property, + conn_state->tv.margins.left); + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tv_top_margin_property, + conn_state->tv.margins.top); + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tv_right_margin_property, + conn_state->tv.margins.right); + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tv_bottom_margin_property, + conn_state->tv.margins.bottom); +} + void intel_tv_init(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct intel_tv *intel_tv; struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; u32 tv_dac_on, tv_dac_off, save_tv_dac; - const char *tv_format_names[ARRAY_SIZE(tv_modes)]; - int i, initial_mode = 0; - struct drm_connector_state *state; if ((intel_de_read(dev_priv, TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; @@ -1937,7 +1975,6 @@ intel_tv_init(struct drm_i915_private *dev_priv) intel_encoder = &intel_tv->base; connector = &intel_connector->base; - state = connector->state; /* * The documentation, for the older chipsets at least, recommend @@ -1951,10 +1988,10 @@ intel_tv_init(struct drm_i915_private *dev_priv) */ intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT; - drm_connector_init(dev, connector, &intel_tv_connector_funcs, + drm_connector_init(&dev_priv->drm, connector, &intel_tv_connector_funcs, DRM_MODE_CONNECTOR_SVIDEO); - drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs, + drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_tv_enc_funcs, DRM_MODE_ENCODER_TVDAC, "TV"); intel_encoder->compute_config = intel_tv_compute_config; @@ -1974,41 +2011,7 @@ intel_tv_init(struct drm_i915_private *dev_priv) intel_encoder->cloneable = 0; intel_tv->type = DRM_MODE_CONNECTOR_Unknown; - /* BIOS margin values */ - state->tv.margins.left = 54; - state->tv.margins.top = 36; - state->tv.margins.right = 46; - state->tv.margins.bottom = 37; - - state->tv.mode = initial_mode; - drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - /* Create TV properties then attach current values */ - for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { - /* 1080p50/1080p60 not supported on gen3 */ - if (DISPLAY_VER(dev_priv) == 3 && - tv_modes[i].oversample == 1) - break; - - tv_format_names[i] = tv_modes[i].name; - } - drm_mode_create_tv_properties(dev, i, tv_format_names); - - drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property, - state->tv.mode); - drm_object_attach_property(&connector->base, - dev->mode_config.tv_left_margin_property, - state->tv.margins.left); - drm_object_attach_property(&connector->base, - dev->mode_config.tv_top_margin_property, - state->tv.margins.top); - drm_object_attach_property(&connector->base, - dev->mode_config.tv_right_margin_property, - state->tv.margins.right); - drm_object_attach_property(&connector->base, - dev->mode_config.tv_bottom_margin_property, - state->tv.margins.bottom); + intel_tv_add_properties(connector); } diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 18178b01375e..d58e667016e4 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -1706,26 +1706,10 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, return -EINVAL; } - 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 || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || - modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS || - modifier == I915_FORMAT_MOD_4_TILED_DG2_MC_CCS || - modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC; wp->x_tiled = modifier == I915_FORMAT_MOD_X_TILED; - wp->rc_surface = modifier == I915_FORMAT_MOD_Y_TILED_CCS || - modifier == I915_FORMAT_MOD_Yf_TILED_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || - modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS || - modifier == I915_FORMAT_MOD_4_TILED_DG2_MC_CCS || - modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC; + wp->y_tiled = modifier != I915_FORMAT_MOD_X_TILED && + intel_fb_is_tiled_modifier(modifier); + wp->rc_surface = intel_fb_is_ccs_modifier(modifier); wp->is_planar = intel_format_info_is_yuv_semiplanar(format, modifier); wp->width = width; @@ -2498,7 +2482,7 @@ skl_compute_ddb(struct intel_atomic_state *state) if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { /* TODO: Implement vblank synchronized MBUS joining changes */ - ret = intel_modeset_all_pipes(state); + ret = intel_modeset_all_pipes(state, "MBUS joining change"); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index b3f5ca280ef2..5a741ea4505f 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1659,19 +1659,10 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = { static void vlv_dsi_add_properties(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *fixed_mode = intel_panel_preferred_fixed_mode(connector); - u32 allowed_scalers; - allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); - if (!HAS_GMCH(dev_priv)) - allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER); - - drm_connector_attach_scaling_mode_property(&connector->base, - allowed_scalers); - - connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; + intel_attach_scaling_mode_property(&connector->base); drm_connector_set_panel_orientation_with_quirk(&connector->base, intel_dsi_get_panel_orientation(connector), @@ -1854,7 +1845,6 @@ static void vlv_dphy_param_init(struct intel_dsi *intel_dsi) void vlv_dsi_init(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_dsi *intel_dsi; struct intel_encoder *intel_encoder; struct drm_encoder *encoder; @@ -1891,7 +1881,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) connector = &intel_connector->base; - drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI, + drm_encoder_init(&dev_priv->drm, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port)); intel_encoder->compute_config = intel_dsi_compute_config; @@ -1974,20 +1964,18 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_dsi_vbt_gpio_init(intel_dsi, intel_dsi_get_hw_state(intel_encoder, &pipe)); - drm_connector_init(dev, connector, &intel_dsi_connector_funcs, + drm_connector_init(&dev_priv->drm, connector, &intel_dsi_connector_funcs, DRM_MODE_CONNECTOR_DSI); drm_connector_helper_add(connector, &intel_dsi_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/ - connector->interlace_allowed = false; - connector->doublescan_allowed = false; intel_connector_attach_encoder(intel_connector, intel_encoder); - mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev_priv->drm.mode_config.mutex); intel_panel_add_vbt_lfp_fixed_mode(intel_connector); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&dev_priv->drm.mode_config.mutex); if (!intel_panel_preferred_fixed_mode(intel_connector)) { drm_dbg_kms(&dev_priv->drm, "no fixed mode\n"); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index 0512afdd20d8..b3b398fe689c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -113,7 +113,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, clflush = clflush_work_create(obj); if (clflush) { i915_sw_fence_await_reservation(&clflush->base.chain, - obj->base.resv, NULL, true, + obj->base.resv, true, i915_fence_timeout(i915), I915_FENCE_GFP); dma_resv_add_fence(obj->base.resv, &clflush->base.dma, diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 2275ee47da95..5a3a25838fff 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -39,6 +39,9 @@ #define FORCEWAKE_ACK_RENDER_GEN9 _MMIO(0xd84) #define FORCEWAKE_ACK_MEDIA_GEN9 _MMIO(0xd88) +#define GMD_ID_GRAPHICS _MMIO(0xd8c) +#define GMD_ID_MEDIA _MMIO(MTL_MEDIA_GSI_BASE + 0xd8c) + #define MCFG_MCR_SELECTOR _MMIO(0xfd0) #define SF_MCR_SELECTOR _MMIO(0xfd8) #define GEN8_MCR_SELECTOR _MMIO(0xfdc) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 6d2003d598e6..a821e3d405db 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2293,11 +2293,11 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) } if (IS_DG1_GRAPHICS_STEP(i915, STEP_A0, STEP_B0) || - IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) { + IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915) || IS_ALDERLAKE_P(i915)) { /* * Wa_1607030317:tgl * Wa_1607186500:tgl - * Wa_1607297627:tgl,rkl,dg1[a0] + * Wa_1607297627:tgl,rkl,dg1[a0],adlp * * On TGL and RKL there are multiple entries for this WA in the * BSpec; some indicate this is an A0-only WA, others indicate diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c459eb362c47..298ed36f078a 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -337,7 +337,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) if (i915_inject_probe_failure(dev_priv)) return -ENODEV; - intel_device_info_subplatform_init(dev_priv); + intel_device_info_runtime_init_early(dev_priv); + intel_step_init(dev_priv); intel_uncore_mmio_debug_init_early(dev_priv); @@ -353,6 +354,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->display.wm.wm_mutex); mutex_init(&dev_priv->display.pps.mutex); mutex_init(&dev_priv->display.hdcp.comp_mutex); + spin_lock_init(&dev_priv->display.dkl.phy_lock); i915_memcpy_init_early(dev_priv); intel_runtime_pm_init_early(&dev_priv->runtime_pm); @@ -738,7 +740,6 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) */ static void i915_driver_register(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_gt *gt; unsigned int i; @@ -748,7 +749,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) intel_vgpu_register(dev_priv); /* Reveal our presence to userspace */ - if (drm_dev_register(dev, 0)) { + if (drm_dev_register(&dev_priv->drm, 0)) { drm_err(&dev_priv->drm, "Failed to register driver for userspace access!\n"); return; @@ -893,10 +894,6 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (IS_ERR(i915)) return PTR_ERR(i915); - /* Disable nuclear pageflip by default on pre-ILK */ - if (!i915->params.nuclear_pageflip && DISPLAY_VER(i915) < 5) - i915->drm.driver_features &= ~DRIVER_ATOMIC; - ret = pci_enable_device(pdev); if (ret) goto out_fini; @@ -1092,32 +1089,30 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) static void intel_suspend_encoders(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_encoder *encoder; if (!HAS_DISPLAY(dev_priv)) return; - drm_modeset_lock_all(dev); - for_each_intel_encoder(dev, encoder) + drm_modeset_lock_all(&dev_priv->drm); + for_each_intel_encoder(&dev_priv->drm, encoder) if (encoder->suspend) encoder->suspend(encoder); - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); } static void intel_shutdown_encoders(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; struct intel_encoder *encoder; if (!HAS_DISPLAY(dev_priv)) return; - drm_modeset_lock_all(dev); - for_each_intel_encoder(dev, encoder) + drm_modeset_lock_all(&dev_priv->drm); + for_each_intel_encoder(&dev_priv->drm, encoder) if (encoder->shutdown) encoder->shutdown(encoder); - drm_modeset_unlock_all(dev); + drm_modeset_unlock_all(&dev_priv->drm); } void i915_driver_shutdown(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bdc81db76dbd..349ff7d65deb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -75,9 +75,6 @@ struct intel_limit; struct intel_overlay_error_state; struct vlv_s0ix_state; -/* Threshold == 5 for long IRQs, 50 for short */ -#define HPD_STORM_DEFAULT_THRESHOLD 50 - #define I915_GEM_GPU_DOMAINS \ (I915_GEM_DOMAIN_RENDER | \ I915_GEM_DOMAIN_SAMPLER | \ @@ -871,6 +868,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_DOUBLE_BUFFERED_M_N(dev_priv) (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) #define HAS_CDCLK_CRAWL(dev_priv) (INTEL_INFO(dev_priv)->display.has_cdclk_crawl) +#define HAS_CDCLK_SQUASH(dev_priv) (INTEL_INFO(dev_priv)->display.has_cdclk_squash) #define HAS_DDI(dev_priv) (INTEL_INFO(dev_priv)->display.has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev_priv) (INTEL_INFO(dev_priv)->display.has_fpga_dbg) #define HAS_PSR(dev_priv) (INTEL_INFO(dev_priv)->display.has_psr) @@ -938,6 +936,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_GMCH(dev_priv) (INTEL_INFO(dev_priv)->display.has_gmch) +#define HAS_GMD_ID(i915) (INTEL_INFO(i915)->has_gmd_id) + #define HAS_LSPCON(dev_priv) (IS_DISPLAY_VER(dev_priv, 9, 10)) #define HAS_L3_CCS_READ(i915) (INTEL_INFO(i915)->has_l3_ccs_read) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 86a42d9e8041..d68859866bf2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -325,15 +325,10 @@ i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, u32 mask, u32 bits) { - u32 val; - lockdep_assert_held(&dev_priv->irq_lock); drm_WARN_ON(&dev_priv->drm, bits & ~mask); - val = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_EN); - val &= ~mask; - val |= bits; - intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_EN, val); + intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits); } /** @@ -1057,8 +1052,8 @@ static void ivb_parity_work(struct work_struct *work) if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice)) goto out; - misccpctl = intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL); - intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, + GEN7_DOP_CLOCK_GATE_ENABLE, 0); intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL); while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { @@ -1689,8 +1684,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) * bits this time around. */ intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); - ier = intel_uncore_read(&dev_priv->uncore, VLV_IER); - intel_uncore_write(&dev_priv->uncore, VLV_IER, 0); + ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); if (gt_iir) intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir); @@ -1775,8 +1769,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) * bits this time around. */ intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); - ier = intel_uncore_read(&dev_priv->uncore, VLV_IER); - intel_uncore_write(&dev_priv->uncore, VLV_IER, 0); + ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); @@ -1981,8 +1974,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) if (ddi_hotplug_trigger) { u32 dig_hotplug_reg; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI); - intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, ddi_hotplug_trigger, dig_hotplug_reg, @@ -1993,8 +1985,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) if (tc_hotplug_trigger) { u32 dig_hotplug_reg; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC); - intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, tc_hotplug_trigger, dig_hotplug_reg, @@ -2019,8 +2010,7 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) if (hotplug_trigger) { u32 dig_hotplug_reg; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, @@ -2031,8 +2021,7 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) if (hotplug2_trigger) { u32 dig_hotplug_reg; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug2_trigger, dig_hotplug_reg, @@ -2052,8 +2041,7 @@ static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, { u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL); - intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, @@ -2232,8 +2220,7 @@ static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, { u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, @@ -2252,8 +2239,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) if (trigger_tc) { u32 dig_hotplug_reg; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL); - intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc, dig_hotplug_reg, @@ -2264,8 +2250,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) if (trigger_tbt) { u32 dig_hotplug_reg; - dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL); - intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, dig_hotplug_reg); + dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tbt, dig_hotplug_reg, @@ -2355,8 +2340,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) else iir_reg = EDP_PSR_IIR; - psr_iir = intel_uncore_read(&dev_priv->uncore, iir_reg); - intel_uncore_write(&dev_priv->uncore, iir_reg, psr_iir); + psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0); if (psr_iir) found = true; @@ -2426,8 +2410,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, /* clear TE in dsi IIR */ port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; - tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port)); - intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp); + tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); } static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) @@ -2884,7 +2867,6 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); enum port port; - u32 tmp; if (!(intel_crtc->mode_flags & (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) @@ -2896,16 +2878,10 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, else port = PORT_A; - tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_MASK_REG(port)); - if (enable) - tmp &= ~DSI_TE_EVENT; - else - tmp |= DSI_TE_EVENT; - - intel_uncore_write(&dev_priv->uncore, DSI_INTR_MASK_REG(port), tmp); + intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, + enable ? 0 : DSI_TE_EVENT); - tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port)); - intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp); + intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); return true; } @@ -3020,7 +2996,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); - intel_uncore_write(uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); + intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); i9xx_pipestat_irq_reset(dev_priv); @@ -3118,7 +3094,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; - gen8_master_intr_disable(dev_priv->uncore.regs); + gen8_master_intr_disable(uncore->regs); gen8_gt_irq_reset(to_gt(dev_priv)); gen8_display_irq_reset(dev_priv); @@ -3250,7 +3226,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; - intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); + intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0); intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); gen8_gt_irq_reset(to_gt(dev_priv)); @@ -3290,23 +3266,20 @@ static u32 ibx_hotplug_enables(struct drm_i915_private *i915, static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - /* * Enable digital hotplug on the PCH, and configure the DP short pulse * duration to 2ms (which is the minimum in the Display Port spec). * The pulse duration bits are reserved on LPT+. */ - hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); - hotplug &= ~(PORTA_HOTPLUG_ENABLE | - PORTB_HOTPLUG_ENABLE | - PORTC_HOTPLUG_ENABLE | - PORTD_HOTPLUG_ENABLE | - PORTB_PULSE_DURATION_MASK | - PORTC_PULSE_DURATION_MASK | - PORTD_PULSE_DURATION_MASK); - hotplug |= intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); + intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, + PORTA_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE | + PORTC_HOTPLUG_ENABLE | + PORTD_HOTPLUG_ENABLE | + PORTB_PULSE_DURATION_MASK | + PORTC_PULSE_DURATION_MASK | + PORTD_PULSE_DURATION_MASK, + intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables)); } static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) @@ -3353,30 +3326,24 @@ static u32 icp_tc_hotplug_enables(struct drm_i915_private *i915, static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - - hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI); - hotplug &= ~(SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | - SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | - SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | - SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D)); - hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, hotplug); + intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D), + intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables)); } static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - - hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC); - hotplug &= ~(ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | - ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | - ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | - ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | - ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | - ICP_TC_HPD_ENABLE(HPD_PORT_TC6)); - hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, hotplug); + intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, + ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC6), + intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables)); } static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) @@ -3411,62 +3378,54 @@ static u32 gen11_hotplug_enables(struct drm_i915_private *i915, } } -static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) +static void dg1_hpd_invert(struct drm_i915_private *i915) { - u32 val; - - val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1); - val |= (INVERT_DDIA_HPD | - INVERT_DDIB_HPD | - INVERT_DDIC_HPD | - INVERT_DDID_HPD); - intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val); + u32 val = (INVERT_DDIA_HPD | + INVERT_DDIB_HPD | + INVERT_DDIC_HPD | + INVERT_DDID_HPD); + intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val); +} +static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) +{ + dg1_hpd_invert(dev_priv); icp_hpd_irq_setup(dev_priv); } static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - - hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL); - hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); - hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, hotplug); + intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6), + intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables)); } static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - - hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL); - hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | - GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); - hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, hotplug); + intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6), + intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables)); } static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - u32 val; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); - val = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); - val &= ~hotplug_irqs; - val |= ~enabled_irqs & hotplug_irqs; - intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IMR, val); + intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs, + ~enabled_irqs & hotplug_irqs); intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); gen11_tc_hpd_detection_setup(dev_priv); @@ -3506,29 +3465,22 @@ static u32 spt_hotplug2_enables(struct drm_i915_private *i915, static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 val, hotplug; - /* Display WA #1179 WaHardHangonHotPlug: cnp */ if (HAS_PCH_CNP(dev_priv)) { - val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1); - val &= ~CHASSIS_CLK_REQ_DURATION_MASK; - val |= CHASSIS_CLK_REQ_DURATION(0xf); - intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val); + intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK, + CHASSIS_CLK_REQ_DURATION(0xf)); } /* Enable digital hotplug on the PCH */ - hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); - hotplug &= ~(PORTA_HOTPLUG_ENABLE | - PORTB_HOTPLUG_ENABLE | - PORTC_HOTPLUG_ENABLE | - PORTD_HOTPLUG_ENABLE); - hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); + intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, + PORTA_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE | + PORTC_HOTPLUG_ENABLE | + PORTD_HOTPLUG_ENABLE, + intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables)); - hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2); - hotplug &= ~PORTE_HOTPLUG_ENABLE; - hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, hotplug); + intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, PORTE_HOTPLUG_ENABLE, + intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables)); } static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) @@ -3560,18 +3512,14 @@ static u32 ilk_hotplug_enables(struct drm_i915_private *i915, static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - /* * Enable digital hotplug on the CPU, and configure the DP short pulse * duration to 2ms (which is the minimum in the Display Port spec) * The pulse duration bits are reserved on HSW+. */ - hotplug = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL); - hotplug &= ~(DIGITAL_PORTA_HOTPLUG_ENABLE | - DIGITAL_PORTA_PULSE_DURATION_MASK); - hotplug |= intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); + intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, + DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_MASK, + intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables)); } static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) @@ -3619,17 +3567,12 @@ static u32 bxt_hotplug_enables(struct drm_i915_private *i915, static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; - - hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); - hotplug &= ~(PORTA_HOTPLUG_ENABLE | - PORTB_HOTPLUG_ENABLE | - PORTC_HOTPLUG_ENABLE | - BXT_DDIA_HPD_INVERT | - BXT_DDIB_HPD_INVERT | - BXT_DDIC_HPD_INVERT); - hotplug |= intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables); - intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); + intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, + PORTA_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE | + PORTC_HOTPLUG_ENABLE | + BXT_DDI_HPD_INVERT_MASK, + intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables)); } static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) @@ -4009,9 +3952,7 @@ static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, { u32 emr; - *eir = intel_uncore_read(&dev_priv->uncore, EIR); - - intel_uncore_write(&dev_priv->uncore, EIR, *eir); + *eir = intel_uncore_rmw(&dev_priv->uncore, EIR, 0, 0); *eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR); if (*eir_stuck == 0) @@ -4027,8 +3968,7 @@ static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, * (or by a GPU reset) so we mask any bit that * remains set. */ - emr = intel_uncore_read(&dev_priv->uncore, EMR); - intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff); + emr = intel_uncore_rmw(&dev_priv->uncore, EMR, ~0, 0xffffffff); intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck); } @@ -4095,7 +4035,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv) if (I915_HAS_HOTPLUG(dev_priv)) { i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); + intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0); } i9xx_pipestat_irq_reset(dev_priv); @@ -4109,8 +4049,8 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv) struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; - intel_uncore_write(&dev_priv->uncore, EMR, ~(I915_ERROR_PAGE_TABLE | - I915_ERROR_MEMORY_REFRESH)); + intel_uncore_write(uncore, EMR, ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH)); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = @@ -4205,7 +4145,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv) struct intel_uncore *uncore = &dev_priv->uncore; i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); + intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); i9xx_pipestat_irq_reset(dev_priv); @@ -4232,7 +4172,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv) error_mask = ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH); } - intel_uncore_write(&dev_priv->uncore, EMR, error_mask); + intel_uncore_write(uncore, EMR, error_mask); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = @@ -4383,7 +4323,6 @@ void intel_hpd_irq_setup(struct drm_i915_private *i915) */ void intel_irq_init(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; int i; INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); @@ -4399,9 +4338,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv) intel_hpd_init_pins(dev_priv); - intel_hpd_init_work(dev_priv); + intel_hpd_init_early(dev_priv); - dev->vblank_disable_immediate = true; + dev_priv->drm.vblank_disable_immediate = true; /* Most platforms treat the display irq block as an always-on * power domain. vlv/chv can disable it at runtime and need @@ -4413,15 +4352,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) dev_priv->display_irqs_enabled = false; - dev_priv->display.hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; - /* If we have MST support, we want to avoid doing short HPD IRQ storm - * detection, as short HPD storms will occur as a natural part of - * sideband messaging with MST. - * On older platforms however, IRQ storms can occur with both long and - * short pulses, as seen on some G4x systems. - */ - dev_priv->display.hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); - if (HAS_GMCH(dev_priv)) { if (I915_HAS_HOTPLUG(dev_priv)) dev_priv->display.funcs.hotplug = &i915_hpd_funcs; diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index cd4487a1d3be..9486127a44f7 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1066,6 +1066,7 @@ static const struct intel_device_info xehpsdv_info = { .has_heci_pxp = 1, \ .needs_compact_pt = 1, \ .has_media_ratio_mode = 1, \ + .display.has_cdclk_squash = 1, \ .__runtime.platform_engine_mask = \ BIT(RCS0) | BIT(BCS0) | \ BIT(VECS0) | BIT(VECS1) | \ @@ -1144,6 +1145,7 @@ static const struct intel_device_info mtl_info = { .display.has_modular_fia = 1, .extra_gt_list = xelpmp_extra_gt, .has_flat_ccs = 0, + .has_gmd_id = 1, .has_snoop = 1, .__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0b287a59dc2f..2a887cdd7c1b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5847,6 +5847,11 @@ #define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29) #define ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz (2 << 29) +#define GMD_ID_DISPLAY _MMIO(0x510a0) +#define GMD_ID_ARCH_MASK REG_GENMASK(31, 22) +#define GMD_ID_RELEASE_MASK REG_GENMASK(21, 14) +#define GMD_ID_STEP REG_GENMASK(5, 0) + /*GEN11 chicken */ #define _PIPEA_CHICKEN 0x70038 #define _PIPEB_CHICKEN 0x71038 @@ -7413,182 +7418,6 @@ enum skl_power_gate { _ADLS_DPLL4_CFGCR1, \ _ADLS_DPLL3_CFGCR1) -#define _DKL_PHY1_BASE 0x168000 -#define _DKL_PHY2_BASE 0x169000 -#define _DKL_PHY3_BASE 0x16A000 -#define _DKL_PHY4_BASE 0x16B000 -#define _DKL_PHY5_BASE 0x16C000 -#define _DKL_PHY6_BASE 0x16D000 - -/* DEKEL PHY MMIO Address = Phy base + (internal address & ~index_mask) */ -#define _DKL_PCS_DW5 0x14 -#define DKL_PCS_DW5(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_PCS_DW5) -#define DKL_PCS_DW5_CORE_SOFTRESET REG_BIT(11) - -#define _DKL_PLL_DIV0 0x200 -#define DKL_PLL_DIV0_AFC_STARTUP_MASK REG_GENMASK(27, 25) -#define DKL_PLL_DIV0_AFC_STARTUP(val) REG_FIELD_PREP(DKL_PLL_DIV0_AFC_STARTUP_MASK, (val)) -#define DKL_PLL_DIV0_INTEG_COEFF(x) ((x) << 16) -#define DKL_PLL_DIV0_INTEG_COEFF_MASK (0x1F << 16) -#define DKL_PLL_DIV0_PROP_COEFF(x) ((x) << 12) -#define DKL_PLL_DIV0_PROP_COEFF_MASK (0xF << 12) -#define DKL_PLL_DIV0_FBPREDIV_SHIFT (8) -#define DKL_PLL_DIV0_FBPREDIV(x) ((x) << DKL_PLL_DIV0_FBPREDIV_SHIFT) -#define DKL_PLL_DIV0_FBPREDIV_MASK (0xF << DKL_PLL_DIV0_FBPREDIV_SHIFT) -#define DKL_PLL_DIV0_FBDIV_INT(x) ((x) << 0) -#define DKL_PLL_DIV0_FBDIV_INT_MASK (0xFF << 0) -#define DKL_PLL_DIV0_MASK (DKL_PLL_DIV0_INTEG_COEFF_MASK | \ - DKL_PLL_DIV0_PROP_COEFF_MASK | \ - DKL_PLL_DIV0_FBPREDIV_MASK | \ - DKL_PLL_DIV0_FBDIV_INT_MASK) -#define DKL_PLL_DIV0(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_PLL_DIV0) - -#define _DKL_PLL_DIV1 0x204 -#define DKL_PLL_DIV1_IREF_TRIM(x) ((x) << 16) -#define DKL_PLL_DIV1_IREF_TRIM_MASK (0x1F << 16) -#define DKL_PLL_DIV1_TDC_TARGET_CNT(x) ((x) << 0) -#define DKL_PLL_DIV1_TDC_TARGET_CNT_MASK (0xFF << 0) -#define DKL_PLL_DIV1(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_PLL_DIV1) - -#define _DKL_PLL_SSC 0x210 -#define DKL_PLL_SSC_IREF_NDIV_RATIO(x) ((x) << 29) -#define DKL_PLL_SSC_IREF_NDIV_RATIO_MASK (0x7 << 29) -#define DKL_PLL_SSC_STEP_LEN(x) ((x) << 16) -#define DKL_PLL_SSC_STEP_LEN_MASK (0xFF << 16) -#define DKL_PLL_SSC_STEP_NUM(x) ((x) << 11) -#define DKL_PLL_SSC_STEP_NUM_MASK (0x7 << 11) -#define DKL_PLL_SSC_EN (1 << 9) -#define DKL_PLL_SSC(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_PLL_SSC) - -#define _DKL_PLL_BIAS 0x214 -#define DKL_PLL_BIAS_FRAC_EN_H (1 << 30) -#define DKL_PLL_BIAS_FBDIV_SHIFT (8) -#define DKL_PLL_BIAS_FBDIV_FRAC(x) ((x) << DKL_PLL_BIAS_FBDIV_SHIFT) -#define DKL_PLL_BIAS_FBDIV_FRAC_MASK (0x3FFFFF << DKL_PLL_BIAS_FBDIV_SHIFT) -#define DKL_PLL_BIAS(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_PLL_BIAS) - -#define _DKL_PLL_TDC_COLDST_BIAS 0x218 -#define DKL_PLL_TDC_SSC_STEP_SIZE(x) ((x) << 8) -#define DKL_PLL_TDC_SSC_STEP_SIZE_MASK (0xFF << 8) -#define DKL_PLL_TDC_FEED_FWD_GAIN(x) ((x) << 0) -#define DKL_PLL_TDC_FEED_FWD_GAIN_MASK (0xFF << 0) -#define DKL_PLL_TDC_COLDST_BIAS(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_PLL_TDC_COLDST_BIAS) - -#define _DKL_REFCLKIN_CTL 0x12C -/* Bits are the same as MG_REFCLKIN_CTL */ -#define DKL_REFCLKIN_CTL(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_REFCLKIN_CTL) - -#define _DKL_CLKTOP2_HSCLKCTL 0xD4 -/* Bits are the same as MG_CLKTOP2_HSCLKCTL */ -#define DKL_CLKTOP2_HSCLKCTL(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_CLKTOP2_HSCLKCTL) - -#define _DKL_CLKTOP2_CORECLKCTL1 0xD8 -/* Bits are the same as MG_CLKTOP2_CORECLKCTL1 */ -#define DKL_CLKTOP2_CORECLKCTL1(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_CLKTOP2_CORECLKCTL1) - -#define _DKL_TX_DPCNTL0 0x2C0 -#define DKL_TX_PRESHOOT_COEFF(x) ((x) << 13) -#define DKL_TX_PRESHOOT_COEFF_MASK (0x1f << 13) -#define DKL_TX_DE_EMPHASIS_COEFF(x) ((x) << 8) -#define DKL_TX_DE_EMPAHSIS_COEFF_MASK (0x1f << 8) -#define DKL_TX_VSWING_CONTROL(x) ((x) << 0) -#define DKL_TX_VSWING_CONTROL_MASK (0x7 << 0) -#define DKL_TX_DPCNTL0(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_DPCNTL0) - -#define _DKL_TX_DPCNTL1 0x2C4 -/* Bits are the same as DKL_TX_DPCNTRL0 */ -#define DKL_TX_DPCNTL1(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_DPCNTL1) - -#define _DKL_TX_DPCNTL2 0x2C8 -#define DKL_TX_DP20BITMODE REG_BIT(2) -#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK REG_GENMASK(4, 3) -#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK, (val)) -#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK REG_GENMASK(6, 5) -#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, (val)) -#define DKL_TX_DPCNTL2(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_DPCNTL2) - -#define _DKL_TX_FW_CALIB 0x2F8 -#define DKL_TX_CFG_DISABLE_WAIT_INIT (1 << 7) -#define DKL_TX_FW_CALIB(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_FW_CALIB) - -#define _DKL_TX_PMD_LANE_SUS 0xD00 -#define DKL_TX_PMD_LANE_SUS(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_PMD_LANE_SUS) - -#define _DKL_TX_DW17 0xDC4 -#define DKL_TX_DW17(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_DW17) - -#define _DKL_TX_DW18 0xDC8 -#define DKL_TX_DW18(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_TX_DW18) - -#define _DKL_DP_MODE 0xA0 -#define DKL_DP_MODE(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_DP_MODE) - -#define _DKL_CMN_UC_DW27 0x36C -#define DKL_CMN_UC_DW27_UC_HEALTH (0x1 << 15) -#define DKL_CMN_UC_DW_27(tc_port) _MMIO(_PORT(tc_port, \ - _DKL_PHY1_BASE, \ - _DKL_PHY2_BASE) + \ - _DKL_CMN_UC_DW27) - -/* - * Each Dekel PHY is addressed through a 4KB aperture. Each PHY has more than - * 4KB of register space, so a separate index is programmed in HIP_INDEX_REG0 - * or HIP_INDEX_REG1, based on the port number, to set the upper 2 address - * bits that point the 4KB window into the full PHY register space. - */ -#define _HIP_INDEX_REG0 0x1010A0 -#define _HIP_INDEX_REG1 0x1010A4 -#define HIP_INDEX_REG(tc_port) _MMIO((tc_port) < 4 ? _HIP_INDEX_REG0 \ - : _HIP_INDEX_REG1) -#define _HIP_INDEX_SHIFT(tc_port) (8 * ((tc_port) % 4)) -#define HIP_INDEX_VAL(tc_port, val) ((val) << _HIP_INDEX_SHIFT(tc_port)) - /* BXT display engine PLL */ #define BXT_DE_PLL_CTL _MMIO(0x6d000) #define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */ @@ -8341,6 +8170,11 @@ enum skl_power_gate { #define GEN12_CULLBIT2 _MMIO(0x7030) #define GEN12_STATE_ACK_DEBUG _MMIO(0x20BC) +#define _MTL_CLKGATE_DIS_TRANS_A 0x604E8 +#define _MTL_CLKGATE_DIS_TRANS_B 0x614E8 +#define MTL_CLKGATE_DIS_TRANS(trans) _MMIO_TRANS2(trans, _MTL_CLKGATE_DIS_TRANS_A) +#define MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS REG_BIT(7) + #define MTL_LATENCY_LP0_LP1 _MMIO(0x45780) #define MTL_LATENCY_LP2_LP3 _MMIO(0x45784) #define MTL_LATENCY_LP4_LP5 _MMIO(0x45788) @@ -8364,4 +8198,6 @@ enum skl_power_gate { #define MTL_TRAS_MASK REG_GENMASK(16, 8) #define MTL_TRDPRE_MASK REG_GENMASK(7, 0) +#define MTL_MEDIA_GSI_BASE 0x380000 + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 6fc0d1b89690..cc2a8821d22a 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -571,7 +571,6 @@ int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, struct dma_resv *resv, - const struct dma_fence_ops *exclude, bool write, unsigned long timeout, gfp_t gfp) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 619fc5a22f0c..f752bfc7c6e1 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -91,7 +91,6 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, struct dma_resv *resv, - const struct dma_fence_ops *exclude, bool write, unsigned long timeout, gfp_t gfp); diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 20575eb77ea7..1dc1fb29a776 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -29,6 +29,7 @@ #include "display/intel_cdclk.h" #include "display/intel_de.h" +#include "gt/intel_gt_regs.h" #include "intel_device_info.h" #include "i915_drv.h" #include "i915_utils.h" @@ -231,7 +232,7 @@ static bool find_devid(u16 id, const u16 *p, unsigned int num) return false; } -void intel_device_info_subplatform_init(struct drm_i915_private *i915) +static void intel_device_info_subplatform_init(struct drm_i915_private *i915) { const struct intel_device_info *info = INTEL_INFO(i915); const struct intel_runtime_info *rinfo = RUNTIME_INFO(i915); @@ -288,6 +289,78 @@ void intel_device_info_subplatform_init(struct drm_i915_private *i915) RUNTIME_INFO(i915)->platform_mask[pi] |= mask; } +static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_ip_version *ip) +{ + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + void __iomem *addr; + u32 val; + u8 expected_ver = ip->ver; + u8 expected_rel = ip->rel; + + addr = pci_iomap_range(pdev, 0, offset, sizeof(u32)); + if (drm_WARN_ON(&i915->drm, !addr)) + return; + + val = ioread32(addr); + pci_iounmap(pdev, addr); + + ip->ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val); + ip->rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); + ip->step = REG_FIELD_GET(GMD_ID_STEP, val); + + /* Sanity check against expected versions from device info */ + if (IP_VER(ip->ver, ip->rel) < IP_VER(expected_ver, expected_rel)) + drm_dbg(&i915->drm, + "Hardware reports GMD IP version %u.%u (REG[0x%x] = 0x%08x) but minimum expected is %u.%u\n", + ip->ver, ip->rel, offset, val, expected_ver, expected_rel); +} + +/* + * Setup the graphics version for the current device. This must be done before + * any code that performs checks on GRAPHICS_VER or DISPLAY_VER, so this + * function should be called very early in the driver initialization sequence. + * + * Regular MMIO access is not yet setup at the point this function is called so + * we peek at the appropriate MMIO offset directly. The GMD_ID register is + * part of an 'always on' power well by design, so we don't need to worry about + * forcewake while reading it. + */ +static void intel_ipver_early_init(struct drm_i915_private *i915) +{ + struct intel_runtime_info *runtime = RUNTIME_INFO(i915); + + if (!HAS_GMD_ID(i915)) { + drm_WARN_ON(&i915->drm, RUNTIME_INFO(i915)->graphics.ip.ver > 12); + /* + * On older platforms, graphics and media share the same ip + * version and release. + */ + RUNTIME_INFO(i915)->media.ip = + RUNTIME_INFO(i915)->graphics.ip; + return; + } + + ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_GRAPHICS), + &runtime->graphics.ip); + ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_DISPLAY), + &runtime->display.ip); + ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_MEDIA), + &runtime->media.ip); +} + +/** + * intel_device_info_runtime_init_early - initialize early runtime info + * @i915: the i915 device + * + * Determine early intel_device_info fields at runtime. This function needs + * to be called before the MMIO has been setup. + */ +void intel_device_info_runtime_init_early(struct drm_i915_private *i915) +{ + intel_ipver_early_init(i915); + intel_device_info_subplatform_init(i915); +} + /** * intel_device_info_runtime_init - initialize runtime info * @dev_priv: the i915 device @@ -442,6 +515,11 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) runtime->has_dmc = false; runtime->has_dsc = false; } + + /* Disable nuclear pageflip by default on pre-g4x */ + if (!dev_priv->params.nuclear_pageflip && + DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) + dev_priv->drm.driver_features &= ~DRIVER_ATOMIC; } void intel_driver_caps_print(const struct intel_driver_caps *caps, diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index d638235e1d26..7b5dd8e21d7a 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -153,6 +153,7 @@ enum intel_ppgtt_type { func(has_4tile); \ func(has_flat_ccs); \ func(has_global_mocs); \ + func(has_gmd_id); \ func(has_gt_uc); \ func(has_heci_pxp); \ func(has_heci_gscfi); \ @@ -180,6 +181,7 @@ enum intel_ppgtt_type { /* Keep in alphabetical order */ \ func(cursor_needs_physical); \ func(has_cdclk_crawl); \ + func(has_cdclk_squash); \ func(has_ddi); \ func(has_dp_mst); \ func(has_dsb); \ @@ -195,20 +197,25 @@ enum intel_ppgtt_type { func(overlay_needs_physical); \ func(supports_tv); -struct ip_version { +struct intel_ip_version { u8 ver; u8 rel; + u8 step; }; struct intel_runtime_info { + /* + * Single "graphics" IP version that represents + * render, compute and copy behavior. + */ struct { - struct ip_version ip; + struct intel_ip_version ip; } graphics; struct { - struct ip_version ip; + struct intel_ip_version ip; } media; struct { - struct ip_version ip; + struct intel_ip_version ip; } display; /* @@ -308,7 +315,7 @@ struct intel_driver_caps { const char *intel_platform_name(enum intel_platform platform); -void intel_device_info_subplatform_init(struct drm_i915_private *dev_priv); +void intel_device_info_runtime_init_early(struct drm_i915_private *dev_priv); void intel_device_info_runtime_init(struct drm_i915_private *dev_priv); void intel_device_info_print(const struct intel_device_info *info, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8f86f56e7ca4..19d4a88184d7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -895,19 +895,14 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) wm = intel_calculate_wm(pixel_rate, &pnv_cursor_wm, pnv_display_wm.fifo_size, 4, latency->cursor_sr); - reg = intel_uncore_read(&dev_priv->uncore, DSPFW3); - reg &= ~DSPFW_CURSOR_SR_MASK; - reg |= FW_WM(wm, CURSOR_SR); - intel_uncore_write(&dev_priv->uncore, DSPFW3, reg); + intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_CURSOR_SR_MASK, + FW_WM(wm, CURSOR_SR)); /* Display HPLL off SR */ wm = intel_calculate_wm(pixel_rate, &pnv_display_hplloff_wm, pnv_display_hplloff_wm.fifo_size, cpp, latency->display_hpll_disable); - reg = intel_uncore_read(&dev_priv->uncore, DSPFW3); - reg &= ~DSPFW_HPLL_SR_MASK; - reg |= FW_WM(wm, HPLL_SR); - intel_uncore_write(&dev_priv->uncore, DSPFW3, reg); + intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_HPLL_SR_MASK, FW_WM(wm, HPLL_SR)); /* cursor HPLL off SR */ wm = intel_calculate_wm(pixel_rate, &pnv_cursor_hplloff_wm, @@ -1337,34 +1332,14 @@ static bool g4x_compute_fbc_en(const struct g4x_wm_state *wm_state, return true; } -static int g4x_compute_pipe_wm(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int _g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state) { - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct g4x_wm_state *wm_state = &crtc_state->wm.g4x.optimal; u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); const struct g4x_pipe_wm *raw; - const struct intel_plane_state *old_plane_state; - const struct intel_plane_state *new_plane_state; - struct intel_plane *plane; enum plane_id plane_id; - int i, level; - unsigned int dirty = 0; - - for_each_oldnew_intel_plane_in_state(state, plane, - old_plane_state, - new_plane_state, i) { - if (new_plane_state->hw.crtc != &crtc->base && - old_plane_state->hw.crtc != &crtc->base) - continue; - - if (g4x_raw_plane_wm_compute(crtc_state, new_plane_state)) - dirty |= BIT(plane->id); - } - - if (!dirty) - return 0; + int level; level = G4X_WM_LEVEL_NORMAL; if (!g4x_raw_crtc_wm_is_valid(crtc_state, level)) @@ -1417,6 +1392,34 @@ static int g4x_compute_pipe_wm(struct intel_atomic_state *state, return 0; } +static int g4x_compute_pipe_wm(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct intel_plane_state *old_plane_state; + const struct intel_plane_state *new_plane_state; + struct intel_plane *plane; + unsigned int dirty = 0; + int i; + + for_each_oldnew_intel_plane_in_state(state, plane, + old_plane_state, + new_plane_state, i) { + if (new_plane_state->hw.crtc != &crtc->base && + old_plane_state->hw.crtc != &crtc->base) + continue; + + if (g4x_raw_plane_wm_compute(crtc_state, new_plane_state)) + dirty |= BIT(plane->id); + } + + if (!dirty) + return 0; + + return _g4x_compute_pipe_wm(crtc_state); +} + static int g4x_compute_intermediate_wm(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1857,64 +1860,17 @@ static bool vlv_raw_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, vlv_raw_plane_wm_is_valid(crtc_state, PLANE_CURSOR, level); } -static int vlv_compute_pipe_wm(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int _vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal; const struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state; u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); int num_active_planes = hweight8(active_planes); - bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->uapi); - const struct intel_plane_state *old_plane_state; - const struct intel_plane_state *new_plane_state; - struct intel_plane *plane; enum plane_id plane_id; - int level, ret, i; - unsigned int dirty = 0; - - for_each_oldnew_intel_plane_in_state(state, plane, - old_plane_state, - new_plane_state, i) { - if (new_plane_state->hw.crtc != &crtc->base && - old_plane_state->hw.crtc != &crtc->base) - continue; - - if (vlv_raw_plane_wm_compute(crtc_state, new_plane_state)) - dirty |= BIT(plane->id); - } - - /* - * DSPARB registers may have been reset due to the - * power well being turned off. Make sure we restore - * them to a consistent state even if no primary/sprite - * planes are initially active. - */ - if (needs_modeset) - crtc_state->fifo_changed = true; - - if (!dirty) - return 0; - - /* cursor changes don't warrant a FIFO recompute */ - if (dirty & ~BIT(PLANE_CURSOR)) { - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - const struct vlv_fifo_state *old_fifo_state = - &old_crtc_state->wm.vlv.fifo_state; - - ret = vlv_compute_fifo(crtc_state); - if (ret) - return ret; - - if (needs_modeset || - memcmp(old_fifo_state, fifo_state, - sizeof(*fifo_state)) != 0) - crtc_state->fifo_changed = true; - } + int level; /* initially allow all levels */ wm_state->num_levels = intel_wm_num_levels(dev_priv); @@ -1961,6 +1917,67 @@ static int vlv_compute_pipe_wm(struct intel_atomic_state *state, return 0; } +static int vlv_compute_pipe_wm(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->uapi); + const struct intel_plane_state *old_plane_state; + const struct intel_plane_state *new_plane_state; + struct intel_plane *plane; + unsigned int dirty = 0; + int i; + + for_each_oldnew_intel_plane_in_state(state, plane, + old_plane_state, + new_plane_state, i) { + if (new_plane_state->hw.crtc != &crtc->base && + old_plane_state->hw.crtc != &crtc->base) + continue; + + if (vlv_raw_plane_wm_compute(crtc_state, new_plane_state)) + dirty |= BIT(plane->id); + } + + /* + * DSPARB registers may have been reset due to the + * power well being turned off. Make sure we restore + * them to a consistent state even if no primary/sprite + * planes are initially active. We also force a FIFO + * recomputation so that we are sure to sanitize the + * FIFO setting we took over from the BIOS even if there + * are no active planes on the crtc. + */ + if (needs_modeset) + dirty = ~0; + + if (!dirty) + return 0; + + /* cursor changes don't warrant a FIFO recompute */ + if (dirty & ~BIT(PLANE_CURSOR)) { + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct vlv_fifo_state *old_fifo_state = + &old_crtc_state->wm.vlv.fifo_state; + const struct vlv_fifo_state *new_fifo_state = + &crtc_state->wm.vlv.fifo_state; + int ret; + + ret = vlv_compute_fifo(crtc_state); + if (ret) + return ret; + + if (needs_modeset || + memcmp(old_fifo_state, new_fifo_state, + sizeof(*new_fifo_state)) != 0) + crtc_state->fifo_changed = true; + } + + return _vlv_compute_pipe_wm(crtc_state); +} + #define VLV_FIFO(plane, value) \ (((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV) @@ -3458,7 +3475,6 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, { struct ilk_wm_values *previous = &dev_priv->display.wm.hw; unsigned int dirty; - u32 val; dirty = ilk_compute_wm_dirty(dev_priv, previous, results); if (!dirty) @@ -3474,32 +3490,20 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, intel_uncore_write(&dev_priv->uncore, WM0_PIPE_ILK(PIPE_C), results->wm_pipe[2]); if (dirty & WM_DIRTY_DDB) { - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - val = intel_uncore_read(&dev_priv->uncore, WM_MISC); - if (results->partitioning == INTEL_DDB_PART_1_2) - val &= ~WM_MISC_DATA_PARTITION_5_6; - else - val |= WM_MISC_DATA_PARTITION_5_6; - intel_uncore_write(&dev_priv->uncore, WM_MISC, val); - } else { - val = intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL2); - if (results->partitioning == INTEL_DDB_PART_1_2) - val &= ~DISP_DATA_PARTITION_5_6; - else - val |= DISP_DATA_PARTITION_5_6; - intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL2, val); - } - } - - if (dirty & WM_DIRTY_FBC) { - val = intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL); - if (results->enable_fbc_wm) - val &= ~DISP_FBC_WM_DIS; + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + intel_uncore_rmw(&dev_priv->uncore, WM_MISC, WM_MISC_DATA_PARTITION_5_6, + results->partitioning == INTEL_DDB_PART_1_2 ? 0 : + WM_MISC_DATA_PARTITION_5_6); else - val |= DISP_FBC_WM_DIS; - intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, val); + intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL2, DISP_DATA_PARTITION_5_6, + results->partitioning == INTEL_DDB_PART_1_2 ? 0 : + DISP_DATA_PARTITION_5_6); } + if (dirty & WM_DIRTY_FBC) + intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, DISP_FBC_WM_DIS, + results->enable_fbc_wm ? 0 : DISP_FBC_WM_DIS); + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) intel_uncore_write(&dev_priv->uncore, WM1S_LP_ILK, results->wm_lp_spr[0]); @@ -3824,6 +3828,8 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv) plane_id, USHRT_MAX); g4x_raw_fbc_wm_set(crtc_state, level, USHRT_MAX); + g4x_invalidate_wms(crtc, active, level); + crtc_state->wm.g4x.optimal = *active; crtc_state->wm.g4x.intermediate = *active; @@ -3860,37 +3866,30 @@ void g4x_wm_sanitize(struct drm_i915_private *dev_priv) to_intel_crtc_state(crtc->base.state); struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - struct g4x_wm_state *wm_state = &crtc_state->wm.g4x.optimal; enum plane_id plane_id = plane->id; - int level; + int level, num_levels = intel_wm_num_levels(dev_priv); if (plane_state->uapi.visible) continue; - for (level = 0; level < 3; level++) { + for (level = 0; level < num_levels; level++) { struct g4x_pipe_wm *raw = &crtc_state->wm.g4x.raw[level]; raw->plane[plane_id] = 0; - wm_state->wm.plane[plane_id] = 0; - } - if (plane_id == PLANE_PRIMARY) { - for (level = 0; level < 3; level++) { - struct g4x_pipe_wm *raw = - &crtc_state->wm.g4x.raw[level]; + if (plane_id == PLANE_PRIMARY) raw->fbc = 0; - } - - wm_state->sr.fbc = 0; - wm_state->hpll.fbc = 0; - wm_state->fbc_en = false; } } for_each_intel_crtc(&dev_priv->drm, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + int ret; + + ret = _g4x_compute_pipe_wm(crtc_state); + drm_WARN_ON(&dev_priv->drm, ret); crtc_state->wm.g4x.intermediate = crtc_state->wm.g4x.optimal; @@ -4016,30 +4015,27 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv) to_intel_crtc_state(crtc->base.state); struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal; - const struct vlv_fifo_state *fifo_state = - &crtc_state->wm.vlv.fifo_state; enum plane_id plane_id = plane->id; - int level; + int level, num_levels = intel_wm_num_levels(dev_priv); if (plane_state->uapi.visible) continue; - for (level = 0; level < wm_state->num_levels; level++) { + for (level = 0; level < num_levels; level++) { struct g4x_pipe_wm *raw = &crtc_state->wm.vlv.raw[level]; raw->plane[plane_id] = 0; - - wm_state->wm[level].plane[plane_id] = - vlv_invert_wm_value(raw->plane[plane_id], - fifo_state->plane[plane_id]); } } for_each_intel_crtc(&dev_priv->drm, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + int ret; + + ret = _vlv_compute_pipe_wm(crtc_state); + drm_WARN_ON(&dev_priv->drm, ret); crtc_state->wm.vlv.intermediate = crtc_state->wm.vlv.optimal; @@ -4117,7 +4113,7 @@ static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) intel_uncore_read(&dev_priv->uncore, DSPCNTR(pipe)) | DISP_TRICKLE_FEED_DISABLE); - intel_uncore_write(&dev_priv->uncore, DSPSURF(pipe), intel_uncore_read(&dev_priv->uncore, DSPSURF(pipe))); + intel_uncore_rmw(&dev_priv->uncore, DSPSURF(pipe), 0, 0); intel_uncore_posting_read(&dev_priv->uncore, DSPSURF(pipe)); } } @@ -4325,8 +4321,8 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv, u32 val; /* WaTempDisableDOPClkGating:bdw */ - misccpctl = intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL); - intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, + GEN7_DOP_CLOCK_GATE_ENABLE, 0); val = intel_uncore_read(&dev_priv->uncore, GEN8_L3SQCREG1); val &= ~L3_PRIO_CREDITS_MASK; @@ -4605,8 +4601,6 @@ static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) static void ivb_init_clock_gating(struct drm_i915_private *dev_priv) { - u32 snpcr; - intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); /* WaFbcAsynchFlipDisableFbcQueue:ivb */ @@ -4644,10 +4638,8 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv) g4x_disable_trickle_feed(dev_priv); - snpcr = intel_uncore_read(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR); - snpcr &= ~GEN6_MBC_SNPCR_MASK; - snpcr |= GEN6_MBC_SNPCR_MED; - intel_uncore_write(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR, snpcr); + intel_uncore_rmw(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR, GEN6_MBC_SNPCR_MASK, + GEN6_MBC_SNPCR_MED); if (!HAS_PCH_NOP(dev_priv)) cpt_init_clock_gating(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 6ed5786bcd29..744cca507946 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -591,8 +591,15 @@ void intel_runtime_pm_enable(struct intel_runtime_pm *rpm) pm_runtime_use_autosuspend(kdev); } - /* Enable by default */ - pm_runtime_allow(kdev); + /* + * FIXME: Temp hammer to keep autosupend disable on lmem supported platforms. + * As per PCIe specs 5.3.1.4.1, all iomem read write request over a PCIe + * function will be unsupported in case PCIe endpoint function is in D3. + * Let's keep i915 autosuspend control 'on' till we fix all known issue + * with lmem access in D3. + */ + if (!IS_DGFX(i915)) + pm_runtime_allow(kdev); /* * The core calls the driver load handler with an RPM reference held. diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c index 42b3133d8387..75d7a86c60c0 100644 --- a/drivers/gpu/drm/i915/intel_step.c +++ b/drivers/gpu/drm/i915/intel_step.c @@ -135,6 +135,19 @@ static const struct intel_step_info adlp_n_revids[] = { [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display_step = STEP_D0 }, }; +static u8 gmd_to_intel_step(struct drm_i915_private *i915, + struct intel_ip_version *gmd) +{ + u8 step = gmd->step + STEP_A0; + + if (step >= STEP_FUTURE) { + drm_dbg(&i915->drm, "Using future steppings\n"); + return STEP_FUTURE; + } + + return step; +} + static void pvc_step_init(struct drm_i915_private *i915, int pci_revid); void intel_step_init(struct drm_i915_private *i915) @@ -144,6 +157,18 @@ void intel_step_init(struct drm_i915_private *i915) int revid = INTEL_REVID(i915); struct intel_step_info step = {}; + if (HAS_GMD_ID(i915)) { + step.graphics_step = gmd_to_intel_step(i915, + &RUNTIME_INFO(i915)->graphics.ip); + step.media_step = gmd_to_intel_step(i915, + &RUNTIME_INFO(i915)->media.ip); + step.display_step = gmd_to_intel_step(i915, + &RUNTIME_INFO(i915)->display.ip); + RUNTIME_INFO(i915)->step = step; + + return; + } + if (IS_PONTEVECCHIO(i915)) { pvc_step_init(i915, revid); return; diff --git a/drivers/gpu/drm/i915/intel_step.h b/drivers/gpu/drm/i915/intel_step.h index a6b12bfa9744..96dfca4cba73 100644 --- a/drivers/gpu/drm/i915/intel_step.h +++ b/drivers/gpu/drm/i915/intel_step.h @@ -11,6 +11,10 @@ struct drm_i915_private; struct intel_step_info { + /* + * It is expected to have 4 number steps per letter. Deviation from + * the expectation breaks gmd_to_intel_step(). + */ u8 graphics_step; /* Represents the compute tile on Xe_HPC */ u8 display_step; u8 media_step; @@ -23,21 +27,43 @@ struct intel_step_info { func(A0) \ func(A1) \ func(A2) \ + func(A3) \ func(B0) \ func(B1) \ func(B2) \ func(B3) \ func(C0) \ func(C1) \ + func(C2) \ + func(C3) \ func(D0) \ func(D1) \ + func(D2) \ + func(D3) \ func(E0) \ + func(E1) \ + func(E2) \ + func(E3) \ func(F0) \ + func(F1) \ + func(F2) \ + func(F3) \ func(G0) \ + func(G1) \ + func(G2) \ + func(G3) \ func(H0) \ + func(H1) \ + func(H2) \ + func(H3) \ func(I0) \ func(I1) \ - func(J0) + func(I2) \ + func(I3) \ + func(J0) \ + func(J1) \ + func(J2) \ + func(J3) /* * Symbolic steppings that do not match the hardware. These are valid both as gt diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 5022bac80b67..ddafa4a7ed71 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -431,15 +431,15 @@ intel_uncore_read64_2x32(struct intel_uncore *uncore, #define intel_uncore_write64_fw(...) __raw_uncore_write64(__VA_ARGS__) #define intel_uncore_posting_read_fw(...) ((void)intel_uncore_read_fw(__VA_ARGS__)) -static inline void intel_uncore_rmw(struct intel_uncore *uncore, - i915_reg_t reg, u32 clear, u32 set) +static inline u32 intel_uncore_rmw(struct intel_uncore *uncore, + i915_reg_t reg, u32 clear, u32 set) { u32 old, val; old = intel_uncore_read(uncore, reg); val = (old & ~clear) | set; - if (val != old) - intel_uncore_write(uncore, reg, val); + intel_uncore_write(uncore, reg, val); + return old; } static inline void intel_uncore_rmw_fw(struct intel_uncore *uncore, diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c index 1bb5b5249157..c4f5c994ca51 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c @@ -77,6 +77,7 @@ static int pxp_create_arb_session(struct intel_pxp *pxp) drm_err(>->i915->drm, "arb session failed to go in play\n"); return ret; } + drm_dbg(>->i915->drm, "PXP ARB session is alive\n"); if (!++pxp->key_instance) ++pxp->key_instance; diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index 4b6f5655fab5..a90905039216 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -174,6 +174,9 @@ int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp, if (ret) drm_err(&i915->drm, "Failed to send tee msg ret=[%d]\n", ret); + else if (msg_out.header.status != 0x0) + drm_warn(&i915->drm, "PXP firmware failed arb session init request ret=[0x%08x]\n", + msg_out.header.status); return ret; } diff --git a/drivers/gpu/drm/i915/vlv_suspend.c b/drivers/gpu/drm/i915/vlv_suspend.c index 664fde244f59..02e63ed77f60 100644 --- a/drivers/gpu/drm/i915/vlv_suspend.c +++ b/drivers/gpu/drm/i915/vlv_suspend.c @@ -194,7 +194,6 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *i915) { struct vlv_s0ix_state *s = i915->vlv_s0ix_state; struct intel_uncore *uncore = &i915->uncore; - u32 val; int i; if (!s) @@ -262,15 +261,11 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *i915) * be restored, as they are used to control the s0ix suspend/resume * sequence by the caller. */ - val = intel_uncore_read(uncore, VLV_GTLC_WAKE_CTRL); - val &= VLV_GTLC_ALLOWWAKEREQ; - val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ; - intel_uncore_write(uncore, VLV_GTLC_WAKE_CTRL, val); + intel_uncore_rmw(uncore, VLV_GTLC_WAKE_CTRL, ~VLV_GTLC_ALLOWWAKEREQ, + s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ); - val = intel_uncore_read(uncore, VLV_GTLC_SURVIVABILITY_REG); - val &= VLV_GFX_CLK_FORCE_ON_BIT; - val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT; - intel_uncore_write(uncore, VLV_GTLC_SURVIVABILITY_REG, val); + intel_uncore_rmw(uncore, VLV_GTLC_SURVIVABILITY_REG, ~VLV_GFX_CLK_FORCE_ON_BIT, + s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT); intel_uncore_write(uncore, VLV_PMWGICZ, s->pmwgicz); @@ -308,14 +303,10 @@ static int vlv_wait_for_pw_status(struct drm_i915_private *i915, static int vlv_force_gfx_clock(struct drm_i915_private *i915, bool force_on) { struct intel_uncore *uncore = &i915->uncore; - u32 val; int err; - val = intel_uncore_read(uncore, VLV_GTLC_SURVIVABILITY_REG); - val &= ~VLV_GFX_CLK_FORCE_ON_BIT; - if (force_on) - val |= VLV_GFX_CLK_FORCE_ON_BIT; - intel_uncore_write(uncore, VLV_GTLC_SURVIVABILITY_REG, val); + intel_uncore_rmw(uncore, VLV_GTLC_SURVIVABILITY_REG, VLV_GFX_CLK_FORCE_ON_BIT, + force_on ? VLV_GFX_CLK_FORCE_ON_BIT : 0); if (!force_on) return 0; @@ -340,11 +331,8 @@ static int vlv_allow_gt_wake(struct drm_i915_private *i915, bool allow) u32 val; int err; - val = intel_uncore_read(uncore, VLV_GTLC_WAKE_CTRL); - val &= ~VLV_GTLC_ALLOWWAKEREQ; - if (allow) - val |= VLV_GTLC_ALLOWWAKEREQ; - intel_uncore_write(uncore, VLV_GTLC_WAKE_CTRL, val); + intel_uncore_rmw(uncore, VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ, + allow ? VLV_GTLC_ALLOWWAKEREQ : 0); intel_uncore_posting_read(uncore, VLV_GTLC_WAKE_CTRL); mask = VLV_GTLC_ALLOWWAKEACK; |