diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2020-08-12 19:17:18 +0200 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2020-08-12 20:42:08 +0200 |
commit | 534b1f9071d95325044c21d47d9f63a45cdf425e (patch) | |
tree | 5c2aa3cd65bfb6b9e73d9ad22c021d800380f0f6 /drivers/gpu/drm/i915/display | |
parent | 82dd18096c718962379e61cd8a7a0dc219db174f (diff) | |
parent | 62975d27d647a40c58d3b96c29b911fc4f33c310 (diff) |
Merge drm/drm-next into drm-misc-next
Backmerging drm-next into drm-misc-next for nouveau and panel updates.
Resolves a conflict between ttm and nouveau, where struct ttm_mem_res got
renamed to struct ttm_resource.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Diffstat (limited to 'drivers/gpu/drm/i915/display')
50 files changed, 2532 insertions, 1573 deletions
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 4fec5bd64920..8c55f5bee9ab 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1469,8 +1469,7 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc); if (gen11_dsi_is_periodic_cmd_mode(intel_dsi)) - pipe_config->hw.adjusted_mode.private_flags |= - I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE; + pipe_config->mode_flags |= I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE; } static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder, @@ -1558,10 +1557,6 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, pipe_config->port_clock = afe_clk(encoder, pipe_config) / 5; - /* We would not operate in periodic command mode */ - pipe_config->hw.adjusted_mode.private_flags &= - ~I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE; - /* * In case of TE GATE cmd mode, we * receive TE from the slave if @@ -1569,14 +1564,14 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, */ if (is_cmd_mode(intel_dsi)) { if (intel_dsi->ports == (BIT(PORT_B) | BIT(PORT_A))) - pipe_config->hw.adjusted_mode.private_flags |= + pipe_config->mode_flags |= I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0; else if (intel_dsi->ports == BIT(PORT_B)) - pipe_config->hw.adjusted_mode.private_flags |= + pipe_config->mode_flags |= I915_MODE_FLAG_DSI_USE_TE1; else - pipe_config->hw.adjusted_mode.private_flags |= + pipe_config->mode_flags |= I915_MODE_FLAG_DSI_USE_TE0; } @@ -1954,6 +1949,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) return; err: + drm_connector_cleanup(connector); drm_encoder_cleanup(&encoder->base); kfree(intel_dsi); kfree(intel_connector); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index d043057d2fa0..630f49b7aa01 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -249,9 +249,11 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->update_wm_post = false; crtc_state->fifo_changed = false; crtc_state->preload_luts = false; + crtc_state->inherited = false; crtc_state->wm.need_postvbl_update = false; crtc_state->fb_bits = 0; crtc_state->update_planes = 0; + crtc_state->dsb = NULL; return &crtc_state->uapi; } @@ -292,6 +294,8 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, { struct intel_crtc_state *crtc_state = to_intel_crtc_state(state); + drm_WARN_ON(crtc->dev, crtc_state->dsb); + __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); intel_crtc_free_hw_state(crtc_state); kfree(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 839124647202..c53c85d38fa5 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -479,7 +479,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, struct drm_display_mode *panel_fixed_mode; int index; - index = i915_modparams.vbt_sdvo_panel_type; + index = dev_priv->params.vbt_sdvo_panel_type; if (index == -2) { drm_dbg_kms(&dev_priv->drm, "Ignore SDVO panel mode from BIOS VBT tables.\n"); @@ -722,6 +722,9 @@ parse_power_conservation_features(struct drm_i915_private *dev_priv, */ if (!(power->drrs & BIT(panel_type))) dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; + + if (bdb->version >= 232) + dev_priv->vbt.edp.hobl = power->hobl & BIT(panel_type); } static void @@ -829,9 +832,9 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) u8 vswing; /* Don't read from VBT if module parameter has valid value*/ - if (i915_modparams.edp_vswing) { + if (dev_priv->params.edp_vswing) { dev_priv->vbt.edp.low_vswing = - i915_modparams.edp_vswing == 1; + dev_priv->params.edp_vswing == 1; } else { vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF; dev_priv->vbt.edp.low_vswing = vswing == 0; @@ -1619,30 +1622,18 @@ static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin) return 0; } -static enum port dvo_port_to_port(u8 dvo_port) +static enum port __dvo_port_to_port(int n_ports, int n_dvo, + const int port_mapping[][3], u8 dvo_port) { - /* - * Each DDI port can have more than one value on the "DVO Port" field, - * so look for all the possible values for each port. - */ - static const int dvo_ports[][3] = { - [PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1}, - [PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1}, - [PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1}, - [PORT_D] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1}, - [PORT_E] = { DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE}, - [PORT_F] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1}, - [PORT_G] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1}, - }; enum port port; int i; - for (port = PORT_A; port < ARRAY_SIZE(dvo_ports); port++) { - for (i = 0; i < ARRAY_SIZE(dvo_ports[port]); i++) { - if (dvo_ports[port][i] == -1) + for (port = PORT_A; port < n_ports; port++) { + for (i = 0; i < n_dvo; i++) { + if (port_mapping[port][i] == -1) break; - if (dvo_port == dvo_ports[port][i]) + if (dvo_port == port_mapping[port][i]) return port; } } @@ -1650,6 +1641,48 @@ static enum port dvo_port_to_port(u8 dvo_port) return PORT_NONE; } +static enum port dvo_port_to_port(struct drm_i915_private *dev_priv, + u8 dvo_port) +{ + /* + * Each DDI port can have more than one value on the "DVO Port" field, + * so look for all the possible values for each port. + */ + static const int port_mapping[][3] = { + [PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 }, + [PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 }, + [PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 }, + [PORT_D] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 }, + [PORT_E] = { DVO_PORT_HDMIE, DVO_PORT_DPE, DVO_PORT_CRT }, + [PORT_F] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1 }, + [PORT_G] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1 }, + }; + /* + * Bspec lists the ports as A, B, C, D - however internally in our + * driver we keep them as PORT_A, PORT_B, PORT_D and PORT_E so the + * registers in Display Engine match the right offsets. Apply the + * mapping here to translate from VBT to internal convention. + */ + static const int rkl_port_mapping[][3] = { + [PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 }, + [PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 }, + [PORT_C] = { -1 }, + [PORT_D] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 }, + [PORT_E] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 }, + }; + + if (IS_ROCKETLAKE(dev_priv)) + return __dvo_port_to_port(ARRAY_SIZE(rkl_port_mapping), + ARRAY_SIZE(rkl_port_mapping[0]), + rkl_port_mapping, + dvo_port); + else + return __dvo_port_to_port(ARRAY_SIZE(port_mapping), + ARRAY_SIZE(port_mapping[0]), + port_mapping, + dvo_port); +} + static void parse_ddi_port(struct drm_i915_private *dev_priv, struct display_device_data *devdata, u8 bdb_version) @@ -1659,7 +1692,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; enum port port; - port = dvo_port_to_port(child->dvo_port); + port = dvo_port_to_port(dev_priv, child->dvo_port); if (port == PORT_NONE) return; @@ -2603,10 +2636,10 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, aux_ch = AUX_CH_B; break; case DP_AUX_C: - aux_ch = AUX_CH_C; + aux_ch = IS_ROCKETLAKE(dev_priv) ? AUX_CH_D : AUX_CH_C; break; case DP_AUX_D: - aux_ch = AUX_CH_D; + aux_ch = IS_ROCKETLAKE(dev_priv) ? AUX_CH_E : AUX_CH_D; break; case DP_AUX_E: aux_ch = AUX_CH_E; diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index fef04e2d954e..bd060404d249 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -5,12 +5,12 @@ #include <drm/drm_atomic_state_helper.h> +#include "intel_atomic.h" #include "intel_bw.h" +#include "intel_cdclk.h" #include "intel_display_types.h" -#include "intel_sideband.h" -#include "intel_atomic.h" #include "intel_pm.h" - +#include "intel_sideband.h" /* Parameters for Qclk Geyserville (QGV) */ struct intel_qgv_point { @@ -199,6 +199,12 @@ static const struct intel_sa_info tgl_sa_info = { .displayrtids = 256, }; +static const struct intel_sa_info rkl_sa_info = { + .deburst = 16, + .deprogbwlimit = 20, /* GB/s */ + .displayrtids = 128, +}; + static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa) { struct intel_qgv_info qi = {}; @@ -309,7 +315,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - if (IS_GEN(dev_priv, 12)) + if (IS_ROCKETLAKE(dev_priv)) + icl_get_bw_info(dev_priv, &rkl_sa_info); + else if (IS_GEN(dev_priv, 12)) icl_get_bw_info(dev_priv, &tgl_sa_info); else if (IS_GEN(dev_priv, 11)) icl_get_bw_info(dev_priv, &icl_sa_info); @@ -420,6 +428,141 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state) return to_intel_bw_state(bw_state); } +int skl_bw_calc_min_cdclk(struct intel_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_bw_state *new_bw_state = NULL; + struct intel_bw_state *old_bw_state = NULL; + const struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int max_bw = 0; + int slice_id; + enum pipe pipe; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + enum plane_id plane_id; + struct intel_dbuf_bw *crtc_bw; + + new_bw_state = intel_atomic_get_bw_state(state); + if (IS_ERR(new_bw_state)) + return PTR_ERR(new_bw_state); + + old_bw_state = intel_atomic_get_old_bw_state(state); + + crtc_bw = &new_bw_state->dbuf_bw[crtc->pipe]; + + memset(&crtc_bw->used_bw, 0, sizeof(crtc_bw->used_bw)); + + if (!crtc_state->hw.active) + continue; + + for_each_plane_id_on_crtc(crtc, plane_id) { + const struct skl_ddb_entry *plane_alloc = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; + const struct skl_ddb_entry *uv_plane_alloc = + &crtc_state->wm.skl.plane_ddb_uv[plane_id]; + unsigned int data_rate = crtc_state->data_rate[plane_id]; + unsigned int dbuf_mask = 0; + + dbuf_mask |= skl_ddb_dbuf_slice_mask(dev_priv, plane_alloc); + dbuf_mask |= skl_ddb_dbuf_slice_mask(dev_priv, uv_plane_alloc); + + /* + * FIXME: To calculate that more properly we probably + * need to to split per plane data_rate into data_rate_y + * and data_rate_uv for multiplanar formats in order not + * to get accounted those twice if they happen to reside + * on different slices. + * However for pre-icl this would work anyway because + * we have only single slice and for icl+ uv plane has + * non-zero data rate. + * So in worst case those calculation are a bit + * pessimistic, which shouldn't pose any significant + * problem anyway. + */ + for_each_dbuf_slice_in_mask(slice_id, dbuf_mask) + crtc_bw->used_bw[slice_id] += data_rate; + } + } + + if (!old_bw_state) + return 0; + + for_each_pipe(dev_priv, pipe) { + struct intel_dbuf_bw *crtc_bw; + + crtc_bw = &new_bw_state->dbuf_bw[pipe]; + + for_each_dbuf_slice(slice_id) { + /* + * Current experimental observations show that contrary + * to BSpec we get underruns once we exceed 64 * CDCLK + * for slices in total. + * As a temporary measure in order not to keep CDCLK + * bumped up all the time we calculate CDCLK according + * to this formula for overall bw consumed by slices. + */ + max_bw += crtc_bw->used_bw[slice_id]; + } + } + + new_bw_state->min_cdclk = max_bw / 64; + + if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) { + int ret = intel_atomic_lock_global_state(&new_bw_state->base); + + if (ret) + return ret; + } + + return 0; +} + +int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_bw_state *new_bw_state = NULL; + struct intel_bw_state *old_bw_state = NULL; + const struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int min_cdclk = 0; + enum pipe pipe; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + new_bw_state = intel_atomic_get_bw_state(state); + if (IS_ERR(new_bw_state)) + return PTR_ERR(new_bw_state); + + old_bw_state = intel_atomic_get_old_bw_state(state); + } + + if (!old_bw_state) + return 0; + + for_each_pipe(dev_priv, pipe) { + struct intel_cdclk_state *cdclk_state; + + cdclk_state = intel_atomic_get_new_cdclk_state(state); + if (!cdclk_state) + return 0; + + min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk); + } + + new_bw_state->min_cdclk = min_cdclk; + + if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) { + int ret = intel_atomic_lock_global_state(&new_bw_state->base); + + if (ret) + return ret; + } + + return 0; +} + int intel_bw_atomic_check(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h index bbcaaa73ec1b..46c6eecbd917 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.h +++ b/drivers/gpu/drm/i915/display/intel_bw.h @@ -9,14 +9,20 @@ #include <drm/drm_atomic.h> #include "intel_display.h" +#include "intel_display_power.h" #include "intel_global_state.h" struct drm_i915_private; struct intel_atomic_state; struct intel_crtc_state; +struct intel_dbuf_bw { + int used_bw[I915_MAX_DBUF_SLICES]; +}; + struct intel_bw_state { struct intel_global_state base; + struct intel_dbuf_bw dbuf_bw[I915_MAX_PIPES]; /* * Contains a bit mask, used to determine, whether correspondent @@ -36,6 +42,8 @@ struct intel_bw_state { /* bitmask of active pipes */ u8 active_pipes; + + int min_cdclk; }; #define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base) @@ -56,5 +64,7 @@ void intel_bw_crtc_update(struct intel_bw_state *bw_state, const struct intel_crtc_state *crtc_state); int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv, u32 points_mask); +int intel_bw_calc_min_cdclk(struct intel_atomic_state *state); +int skl_bw_calc_min_cdclk(struct intel_atomic_state *state); #endif /* __INTEL_BW_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 979a0241fdcb..bb91dace304a 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -21,7 +21,10 @@ * DEALINGS IN THE SOFTWARE. */ +#include <linux/time.h> + #include "intel_atomic.h" +#include "intel_bw.h" #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_sideband.h" @@ -2077,8 +2080,15 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) * Explicitly stating here that this seems to be currently * rather a Hack, than final solution. */ - if (IS_TIGERLAKE(dev_priv)) - min_cdclk = max(min_cdclk, (int)crtc_state->pixel_rate); + if (IS_TIGERLAKE(dev_priv)) { + /* + * Clamp to max_cdclk_freq in case pixel rate is higher, + * in order not to break an 8K, but still leave W/A at place. + */ + min_cdclk = max_t(int, min_cdclk, + min_t(int, crtc_state->pixel_rate, + dev_priv->max_cdclk_freq)); + } if (min_cdclk > dev_priv->max_cdclk_freq) { drm_dbg_kms(&dev_priv->drm, @@ -2094,6 +2104,7 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) { struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_bw_state *bw_state = NULL; struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; int min_cdclk, i; @@ -2106,6 +2117,10 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) if (min_cdclk < 0) return min_cdclk; + bw_state = intel_atomic_get_bw_state(state); + if (IS_ERR(bw_state)) + return PTR_ERR(bw_state); + if (cdclk_state->min_cdclk[i] == min_cdclk) continue; @@ -2117,9 +2132,15 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) } min_cdclk = cdclk_state->force_min_cdclk; - for_each_pipe(dev_priv, pipe) + for_each_pipe(dev_priv, pipe) { min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk); + if (!bw_state) + continue; + + min_cdclk = max(bw_state->min_cdclk, min_cdclk); + } + return min_cdclk; } @@ -2700,29 +2721,59 @@ static int vlv_hrawclk(struct drm_i915_private *dev_priv) CCK_DISPLAY_REF_CLOCK_CONTROL); } -static int g4x_hrawclk(struct drm_i915_private *dev_priv) +static int i9xx_hrawclk(struct drm_i915_private *dev_priv) { u32 clkcfg; - /* hrawclock is 1/4 the FSB frequency */ - clkcfg = intel_de_read(dev_priv, CLKCFG); - switch (clkcfg & CLKCFG_FSB_MASK) { - case CLKCFG_FSB_400: - return 100000; - case CLKCFG_FSB_533: - return 133333; - case CLKCFG_FSB_667: - return 166667; - case CLKCFG_FSB_800: - return 200000; - case CLKCFG_FSB_1067: - case CLKCFG_FSB_1067_ALT: - return 266667; - case CLKCFG_FSB_1333: - case CLKCFG_FSB_1333_ALT: - return 333333; - default: - return 133333; + /* + * hrawclock is 1/4 the FSB frequency + * + * Note that this only reads the state of the FSB + * straps, not the actual FSB frequency. Some BIOSen + * let you configure each independently. Ideally we'd + * read out the actual FSB frequency but sadly we + * don't know which registers have that information, + * and all the relevant docs have gone to bit heaven :( + */ + clkcfg = intel_de_read(dev_priv, CLKCFG) & CLKCFG_FSB_MASK; + + if (IS_MOBILE(dev_priv)) { + switch (clkcfg) { + case CLKCFG_FSB_400: + return 100000; + case CLKCFG_FSB_533: + return 133333; + case CLKCFG_FSB_667: + return 166667; + case CLKCFG_FSB_800: + return 200000; + case CLKCFG_FSB_1067: + return 266667; + case CLKCFG_FSB_1333: + return 333333; + default: + MISSING_CASE(clkcfg); + return 133333; + } + } else { + switch (clkcfg) { + case CLKCFG_FSB_400_ALT: + return 100000; + case CLKCFG_FSB_533: + return 133333; + case CLKCFG_FSB_667: + return 166667; + case CLKCFG_FSB_800: + return 200000; + case CLKCFG_FSB_1067_ALT: + return 266667; + case CLKCFG_FSB_1333_ALT: + return 333333; + case CLKCFG_FSB_1600_ALT: + return 400000; + default: + return 133333; + } } } @@ -2743,8 +2794,8 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) freq = pch_rawclk(dev_priv); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) freq = vlv_hrawclk(dev_priv); - else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv)) - freq = g4x_hrawclk(dev_priv); + else if (INTEL_GEN(dev_priv) >= 3) + freq = i9xx_hrawclk(dev_priv); else /* no rawclk on other platforms, or no need to know it */ return 0; @@ -2760,25 +2811,30 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) { if (INTEL_GEN(dev_priv) >= 12) { dev_priv->display.set_cdclk = bxt_set_cdclk; + dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk; dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk; dev_priv->display.calc_voltage_level = tgl_calc_voltage_level; dev_priv->cdclk.table = icl_cdclk_table; } else if (IS_ELKHARTLAKE(dev_priv)) { dev_priv->display.set_cdclk = bxt_set_cdclk; + dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk; dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk; dev_priv->display.calc_voltage_level = ehl_calc_voltage_level; dev_priv->cdclk.table = icl_cdclk_table; } else if (INTEL_GEN(dev_priv) >= 11) { dev_priv->display.set_cdclk = bxt_set_cdclk; + dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk; dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk; dev_priv->display.calc_voltage_level = icl_calc_voltage_level; dev_priv->cdclk.table = icl_cdclk_table; } else if (IS_CANNONLAKE(dev_priv)) { + dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk; dev_priv->display.set_cdclk = bxt_set_cdclk; dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk; dev_priv->display.calc_voltage_level = cnl_calc_voltage_level; dev_priv->cdclk.table = cnl_cdclk_table; } else if (IS_GEN9_LP(dev_priv)) { + dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk; dev_priv->display.set_cdclk = bxt_set_cdclk; dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk; dev_priv->display.calc_voltage_level = bxt_calc_voltage_level; @@ -2787,18 +2843,23 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) else dev_priv->cdclk.table = bxt_cdclk_table; } else if (IS_GEN9_BC(dev_priv)) { + dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk; dev_priv->display.set_cdclk = skl_set_cdclk; dev_priv->display.modeset_calc_cdclk = skl_modeset_calc_cdclk; } else if (IS_BROADWELL(dev_priv)) { + dev_priv->display.bw_calc_min_cdclk = intel_bw_calc_min_cdclk; dev_priv->display.set_cdclk = bdw_set_cdclk; dev_priv->display.modeset_calc_cdclk = bdw_modeset_calc_cdclk; } else if (IS_CHERRYVIEW(dev_priv)) { + dev_priv->display.bw_calc_min_cdclk = intel_bw_calc_min_cdclk; dev_priv->display.set_cdclk = chv_set_cdclk; dev_priv->display.modeset_calc_cdclk = vlv_modeset_calc_cdclk; } else if (IS_VALLEYVIEW(dev_priv)) { + dev_priv->display.bw_calc_min_cdclk = intel_bw_calc_min_cdclk; dev_priv->display.set_cdclk = vlv_set_cdclk; dev_priv->display.modeset_calc_cdclk = vlv_modeset_calc_cdclk; } else { + dev_priv->display.bw_calc_min_cdclk = intel_bw_calc_min_cdclk; dev_priv->display.modeset_calc_cdclk = fixed_modeset_calc_cdclk; } diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 98ece9cd7cdd..945bb03bdd4d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -714,16 +714,16 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0); } -static void ivb_load_lut_ext_max(struct intel_crtc *crtc) +static void ivb_load_lut_ext_max(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); - struct intel_dsb *dsb = intel_dsb_get(crtc); enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ - intel_dsb_reg_write(dsb, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); - intel_dsb_reg_write(dsb, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); - intel_dsb_reg_write(dsb, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); /* * Program the gc max 2 register to clamp values > 1.0. @@ -731,15 +731,13 @@ static void ivb_load_lut_ext_max(struct intel_crtc *crtc) * from 3.0 to 7.0 */ if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { - intel_dsb_reg_write(dsb, PREC_PAL_EXT2_GC_MAX(pipe, 0), + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); - intel_dsb_reg_write(dsb, PREC_PAL_EXT2_GC_MAX(pipe, 1), + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16); - intel_dsb_reg_write(dsb, PREC_PAL_EXT2_GC_MAX(pipe, 2), + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16); } - - intel_dsb_put(dsb); } static void ivb_load_luts(const struct intel_crtc_state *crtc_state) @@ -753,7 +751,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) } else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) { ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); - ivb_load_lut_ext_max(crtc); + ivb_load_lut_ext_max(crtc_state); ivb_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); } else { @@ -761,7 +759,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) ivb_load_lut_10(crtc, blob, PAL_PREC_INDEX_VALUE(0)); - ivb_load_lut_ext_max(crtc); + ivb_load_lut_ext_max(crtc_state); } } @@ -776,7 +774,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state) } else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) { bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); - ivb_load_lut_ext_max(crtc); + ivb_load_lut_ext_max(crtc_state); bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); } else { @@ -784,7 +782,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state) bdw_load_lut_10(crtc, blob, PAL_PREC_INDEX_VALUE(0)); - ivb_load_lut_ext_max(crtc); + ivb_load_lut_ext_max(crtc_state); } } @@ -877,7 +875,7 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state) ilk_load_lut_8(crtc, gamma_lut); } else { bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0)); - ivb_load_lut_ext_max(crtc); + ivb_load_lut_ext_max(crtc_state); } } @@ -900,14 +898,12 @@ icl_load_gcmax(const struct intel_crtc_state *crtc_state, const struct drm_color_lut *color) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_dsb *dsb = intel_dsb_get(crtc); enum pipe pipe = crtc->pipe; /* FIXME LUT entries are 16 bit only, so we can prog 0xFFFF max */ - intel_dsb_reg_write(dsb, PREC_PAL_GC_MAX(pipe, 0), color->red); - intel_dsb_reg_write(dsb, PREC_PAL_GC_MAX(pipe, 1), color->green); - intel_dsb_reg_write(dsb, PREC_PAL_GC_MAX(pipe, 2), color->blue); - intel_dsb_put(dsb); + intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 0), color->red); + intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 1), color->green); + intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 2), color->blue); } static void @@ -916,7 +912,6 @@ 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_color_lut *lut = blob->data; - struct intel_dsb *dsb = intel_dsb_get(crtc); enum pipe pipe = crtc->pipe; int i; @@ -927,19 +922,17 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) * 9 entries, corresponding to values 0, 1/(8 * 128 * 256), * 2/(8 * 128 * 256) ... 8/(8 * 128 * 256). */ - intel_dsb_reg_write(dsb, PREC_PAL_MULTI_SEG_INDEX(pipe), + intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), PAL_PREC_AUTO_INCREMENT); for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; - intel_dsb_indexed_reg_write(dsb, PREC_PAL_MULTI_SEG_DATA(pipe), + intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(dsb, PREC_PAL_MULTI_SEG_DATA(pipe), + intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), ilk_lut_12p4_udw(entry)); } - - intel_dsb_put(dsb); } static void @@ -949,7 +942,6 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; const struct drm_color_lut *lut = blob->data; const struct drm_color_lut *entry; - struct intel_dsb *dsb = intel_dsb_get(crtc); enum pipe pipe = crtc->pipe; int i; @@ -963,12 +955,13 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) * PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1], * seg2[0] being unused by the hardware. */ - intel_dsb_reg_write(dsb, PREC_PAL_INDEX(pipe), PAL_PREC_AUTO_INCREMENT); + intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT); for (i = 1; i < 257; i++) { entry = &lut[i * 8]; - intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe), + intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe), + intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), ilk_lut_12p4_udw(entry)); } @@ -986,24 +979,22 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) */ for (i = 0; i < 256; i++) { entry = &lut[i * 8 * 128]; - intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe), + intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe), + intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), ilk_lut_12p4_udw(entry)); } /* The last entry in the LUT is to be programmed in GCMAX */ entry = &lut[256 * 8 * 128]; icl_load_gcmax(crtc_state, entry); - ivb_load_lut_ext_max(crtc); - intel_dsb_put(dsb); + ivb_load_lut_ext_max(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; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_dsb *dsb = intel_dsb_get(crtc); if (crtc_state->hw.degamma_lut) glk_load_degamma_lut(crtc_state); @@ -1018,11 +1009,10 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) break; default: bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0)); - ivb_load_lut_ext_max(crtc); + ivb_load_lut_ext_max(crtc_state); } - intel_dsb_commit(dsb); - intel_dsb_put(dsb); + intel_dsb_commit(crtc_state); } static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 9ff05ec12115..eccaa79cb4a9 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -181,11 +181,25 @@ static void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv) intel_de_write(dev_priv, CHICKEN_MISC_2, val); } +static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy) +{ + /* + * Some platforms only expect PHY_MISC to be programmed for PHY-A and + * PHY-B and may not even have instances of the register for the + * other combo PHY's. + */ + if (IS_ELKHARTLAKE(i915) || + IS_ROCKETLAKE(i915)) + return phy < PHY_C; + + return true; +} + static bool icl_combo_phy_enabled(struct drm_i915_private *dev_priv, enum phy phy) { /* The PHY C added by EHL has no PHY_MISC register */ - if (IS_ELKHARTLAKE(dev_priv) && phy == PHY_C) + if (!has_phy_misc(dev_priv, phy)) return intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)) & COMP_INIT; else return !(intel_de_read(dev_priv, ICL_PHY_MISC(phy)) & @@ -220,6 +234,27 @@ static bool ehl_vbt_ddi_d_present(struct drm_i915_private *i915) return false; } +static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) +{ + /* + * Certain PHYs are connected to compensation resistors and act + * as masters to other PHYs. + * + * ICL,TGL: + * A(master) -> B(slave), C(slave) + * RKL: + * A(master) -> B(slave) + * C(master) -> D(slave) + * + * We must set the IREFGEN bit for any PHY acting as a master + * to another PHY. + */ + if (IS_ROCKETLAKE(dev_priv) && phy == PHY_C) + return true; + + return phy == PHY_A; +} + static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { @@ -229,9 +264,21 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, if (!icl_combo_phy_enabled(dev_priv, phy)) return false; + if (INTEL_GEN(dev_priv) >= 12) { + ret &= check_phy_reg(dev_priv, phy, ICL_PORT_TX_DW8_LN0(phy), + ICL_PORT_TX_DW8_ODCC_CLK_SEL | + ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_MASK, + ICL_PORT_TX_DW8_ODCC_CLK_SEL | + ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_DIV2); + + ret &= check_phy_reg(dev_priv, phy, ICL_PORT_PCS_DW1_LN0(phy), + DCC_MODE_SELECT_MASK, + DCC_MODE_SELECT_CONTINUOSLY); + } + ret = cnl_verify_procmon_ref_values(dev_priv, phy); - if (phy == PHY_A) { + if (phy_is_master(dev_priv, phy)) { ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy), IREFGEN, IREFGEN); @@ -317,12 +364,7 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv) continue; } - /* - * Although EHL adds a combo PHY C, there's no PHY_MISC - * register for it and no need to program the - * DE_IO_COMP_PWR_DOWN setting on PHY C. - */ - if (IS_ELKHARTLAKE(dev_priv) && phy == PHY_C) + if (!has_phy_misc(dev_priv, phy)) goto skip_phy_misc; /* @@ -345,9 +387,22 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv) intel_de_write(dev_priv, ICL_PHY_MISC(phy), val); skip_phy_misc: + if (INTEL_GEN(dev_priv) >= 12) { + val = intel_de_read(dev_priv, ICL_PORT_TX_DW8_LN0(phy)); + val &= ~ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_MASK; + val |= ICL_PORT_TX_DW8_ODCC_CLK_SEL; + val |= ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_DIV2; + intel_de_write(dev_priv, ICL_PORT_TX_DW8_GRP(phy), val); + + val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN0(phy)); + val &= ~DCC_MODE_SELECT_MASK; + val |= DCC_MODE_SELECT_CONTINUOSLY; + intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val); + } + cnl_set_procmon_ref_values(dev_priv, phy); - if (phy == PHY_A) { + if (phy_is_master(dev_priv, phy)) { val = intel_de_read(dev_priv, ICL_PORT_COMP_DW8(phy)); val |= IREFGEN; intel_de_write(dev_priv, ICL_PORT_COMP_DW8(phy), val); @@ -376,12 +431,7 @@ static void icl_combo_phys_uninit(struct drm_i915_private *dev_priv) "Combo PHY %c HW state changed unexpectedly\n", phy_name(phy)); - /* - * Although EHL adds a combo PHY C, there's no PHY_MISC - * register for it and no need to program the - * DE_IO_COMP_PWR_DOWN setting on PHY C. - */ - if (IS_ELKHARTLAKE(dev_priv) && phy == PHY_C) + if (!has_phy_misc(dev_priv, phy)) goto skip_phy_misc; val = intel_de_read(dev_priv, ICL_PHY_MISC(phy)); diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 2f5b9a4baafd..5b4510ce5693 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -833,7 +833,7 @@ intel_crt_detect(struct drm_connector *connector, connector->base.id, connector->name, force); - if (i915_modparams.load_detect_test) { + if (dev_priv->params.load_detect_test) { wakeref = intel_display_power_get(dev_priv, intel_encoder->power_domain); goto load_detect; @@ -889,7 +889,7 @@ load_detect: else if (INTEL_GEN(dev_priv) < 4) status = intel_crt_load_detect(crt, to_intel_crtc(connector->state->crtc)->pipe); - else if (i915_modparams.load_detect_test) + else if (dev_priv->params.load_detect_test) status = connector_status_disconnected; else status = connector_status_unknown; diff --git a/drivers/gpu/drm/i915/display/intel_csr.c b/drivers/gpu/drm/i915/display/intel_csr.c index 3112572cfb7d..f22a7645c249 100644 --- a/drivers/gpu/drm/i915/display/intel_csr.c +++ b/drivers/gpu/drm/i915/display/intel_csr.c @@ -40,6 +40,10 @@ #define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE +#define RKL_CSR_PATH "i915/rkl_dmc_ver2_01.bin" +#define RKL_CSR_VERSION_REQUIRED CSR_VERSION(2, 1) +MODULE_FIRMWARE(RKL_CSR_PATH); + #define TGL_CSR_PATH "i915/tgl_dmc_ver2_06.bin" #define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 6) #define TGL_CSR_MAX_FW_SIZE 0x6000 @@ -682,7 +686,11 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) */ intel_csr_runtime_pm_get(dev_priv); - if (INTEL_GEN(dev_priv) >= 12) { + if (IS_ROCKETLAKE(dev_priv)) { + csr->fw_path = RKL_CSR_PATH; + csr->required_version = RKL_CSR_VERSION_REQUIRED; + csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE; + } else if (INTEL_GEN(dev_priv) >= 12) { csr->fw_path = TGL_CSR_PATH; csr->required_version = TGL_CSR_VERSION_REQUIRED; /* Allow to load fw via parameter using the last known size */ @@ -699,7 +707,9 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) csr->fw_path = GLK_CSR_PATH; csr->required_version = GLK_CSR_VERSION_REQUIRED; csr->max_fw_size = GLK_CSR_MAX_FW_SIZE; - } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { + } else if (IS_KABYLAKE(dev_priv) || + IS_COFFEELAKE(dev_priv) || + IS_COMETLAKE(dev_priv)) { csr->fw_path = KBL_CSR_PATH; csr->required_version = KBL_CSR_VERSION_REQUIRED; csr->max_fw_size = KBL_CSR_MAX_FW_SIZE; @@ -713,15 +723,15 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) csr->max_fw_size = BXT_CSR_MAX_FW_SIZE; } - if (i915_modparams.dmc_firmware_path) { - if (strlen(i915_modparams.dmc_firmware_path) == 0) { + if (dev_priv->params.dmc_firmware_path) { + if (strlen(dev_priv->params.dmc_firmware_path) == 0) { csr->fw_path = NULL; drm_info(&dev_priv->drm, "Disabling CSR firmware and runtime PM\n"); return; } - csr->fw_path = i915_modparams.dmc_firmware_path; + csr->fw_path = dev_priv->params.dmc_firmware_path; /* Bypass version check for firmware override. */ csr->required_version = 0; } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0575a1eea2a1..2c484b55bcdf 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -639,11 +639,25 @@ struct tgl_dkl_phy_ddi_buf_trans { static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_dp_ddi_trans[] = { /* VS pre-emp Non-trans mV Pre-emph dB */ { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */ - { 0x5, 0x0, 0x03 }, /* 0 1 400mV 3.5 dB */ - { 0x2, 0x0, 0x0b }, /* 0 2 400mV 6 dB */ + { 0x5, 0x0, 0x05 }, /* 0 1 400mV 3.5 dB */ + { 0x2, 0x0, 0x0B }, /* 0 2 400mV 6 dB */ + { 0x0, 0x0, 0x18 }, /* 0 3 400mV 9.5 dB */ + { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */ + { 0x2, 0x0, 0x08 }, /* 1 1 600mV 3.5 dB */ + { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */ + { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */ + { 0x0, 0x0, 0x0B }, /* 2 1 800mV 3.5 dB */ + { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB HDMI default */ +}; + +static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_dp_ddi_trans_hbr2[] = { + /* VS pre-emp Non-trans mV Pre-emph dB */ + { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */ + { 0x5, 0x0, 0x05 }, /* 0 1 400mV 3.5 dB */ + { 0x2, 0x0, 0x0B }, /* 0 2 400mV 6 dB */ { 0x0, 0x0, 0x19 }, /* 0 3 400mV 9.5 dB */ { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */ - { 0x2, 0x0, 0x03 }, /* 1 1 600mV 3.5 dB */ + { 0x2, 0x0, 0x08 }, /* 1 1 600mV 3.5 dB */ { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */ { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */ { 0x0, 0x0, 0x0B }, /* 2 1 800mV 3.5 dB */ @@ -693,8 +707,10 @@ static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2[] = }; static const struct ddi_buf_trans * -bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) +bdw_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (dev_priv->vbt.edp.low_vswing) { *n_entries = ARRAY_SIZE(bdw_ddi_translations_edp); return bdw_ddi_translations_edp; @@ -705,8 +721,10 @@ bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) } static const struct ddi_buf_trans * -skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +skl_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (IS_SKL_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); return skl_y_ddi_translations_dp; @@ -720,12 +738,18 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) } static const struct ddi_buf_trans * -kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +kbl_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries) { - if (IS_KBL_ULX(dev_priv) || IS_CFL_ULX(dev_priv)) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (IS_KBL_ULX(dev_priv) || + IS_CFL_ULX(dev_priv) || + IS_CML_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp); return kbl_y_ddi_translations_dp; - } else if (IS_KBL_ULT(dev_priv) || IS_CFL_ULT(dev_priv)) { + } else if (IS_KBL_ULT(dev_priv) || + IS_CFL_ULT(dev_priv) || + IS_CML_ULT(dev_priv)) { *n_entries = ARRAY_SIZE(kbl_u_ddi_translations_dp); return kbl_u_ddi_translations_dp; } else { @@ -735,15 +759,21 @@ kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) } static const struct ddi_buf_trans * -skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) +skl_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (dev_priv->vbt.edp.low_vswing) { - if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv) || - IS_CFL_ULX(dev_priv)) { + if (IS_SKL_ULX(dev_priv) || + IS_KBL_ULX(dev_priv) || + IS_CFL_ULX(dev_priv) || + IS_CML_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); return skl_y_ddi_translations_edp; - } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv) || - IS_CFL_ULT(dev_priv)) { + } else if (IS_SKL_ULT(dev_priv) || + IS_KBL_ULT(dev_priv) || + IS_CFL_ULT(dev_priv) || + IS_CML_ULT(dev_priv)) { *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); return skl_u_ddi_translations_edp; } else { @@ -752,17 +782,21 @@ skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) } } - if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) - return kbl_get_buf_trans_dp(dev_priv, n_entries); + if (IS_KABYLAKE(dev_priv) || + IS_COFFEELAKE(dev_priv) || + IS_COMETLAKE(dev_priv)) + return kbl_get_buf_trans_dp(encoder, n_entries); else - return skl_get_buf_trans_dp(dev_priv, n_entries); + return skl_get_buf_trans_dp(encoder, n_entries); } static const struct ddi_buf_trans * skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) { - if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv) || - IS_CFL_ULX(dev_priv)) { + if (IS_SKL_ULX(dev_priv) || + IS_KBL_ULX(dev_priv) || + IS_CFL_ULX(dev_priv) || + IS_CML_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi); return skl_y_ddi_translations_hdmi; } else { @@ -781,18 +815,21 @@ static int skl_buf_trans_num_entries(enum port port, int n_entries) } static const struct ddi_buf_trans * -intel_ddi_get_buf_trans_dp(struct drm_i915_private *dev_priv, - enum port port, int *n_entries) +intel_ddi_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries) { - if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (IS_KABYLAKE(dev_priv) || + IS_COFFEELAKE(dev_priv) || + IS_COMETLAKE(dev_priv)) { const struct ddi_buf_trans *ddi_translations = - kbl_get_buf_trans_dp(dev_priv, n_entries); - *n_entries = skl_buf_trans_num_entries(port, *n_entries); + kbl_get_buf_trans_dp(encoder, n_entries); + *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries); return ddi_translations; } else if (IS_SKYLAKE(dev_priv)) { const struct ddi_buf_trans *ddi_translations = - skl_get_buf_trans_dp(dev_priv, n_entries); - *n_entries = skl_buf_trans_num_entries(port, *n_entries); + skl_get_buf_trans_dp(encoder, n_entries); + *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries); return ddi_translations; } else if (IS_BROADWELL(dev_priv)) { *n_entries = ARRAY_SIZE(bdw_ddi_translations_dp); @@ -807,16 +844,17 @@ intel_ddi_get_buf_trans_dp(struct drm_i915_private *dev_priv, } static const struct ddi_buf_trans * -intel_ddi_get_buf_trans_edp(struct drm_i915_private *dev_priv, - enum port port, int *n_entries) +intel_ddi_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (IS_GEN9_BC(dev_priv)) { const struct ddi_buf_trans *ddi_translations = - skl_get_buf_trans_edp(dev_priv, n_entries); - *n_entries = skl_buf_trans_num_entries(port, *n_entries); + skl_get_buf_trans_edp(encoder, n_entries); + *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries); return ddi_translations; } else if (IS_BROADWELL(dev_priv)) { - return bdw_get_buf_trans_edp(dev_priv, n_entries); + return bdw_get_buf_trans_edp(encoder, n_entries); } else if (IS_HASWELL(dev_priv)) { *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp); return hsw_ddi_translations_dp; @@ -843,9 +881,11 @@ intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv, } static const struct ddi_buf_trans * -intel_ddi_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, +intel_ddi_get_buf_trans_hdmi(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (IS_GEN9_BC(dev_priv)) { return skl_get_buf_trans_hdmi(dev_priv, n_entries); } else if (IS_BROADWELL(dev_priv)) { @@ -861,33 +901,36 @@ intel_ddi_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, } static const struct bxt_ddi_buf_trans * -bxt_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +bxt_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries) { *n_entries = ARRAY_SIZE(bxt_ddi_translations_dp); return bxt_ddi_translations_dp; } static const struct bxt_ddi_buf_trans * -bxt_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) +bxt_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (dev_priv->vbt.edp.low_vswing) { *n_entries = ARRAY_SIZE(bxt_ddi_translations_edp); return bxt_ddi_translations_edp; } - return bxt_get_buf_trans_dp(dev_priv, n_entries); + return bxt_get_buf_trans_dp(encoder, n_entries); } static const struct bxt_ddi_buf_trans * -bxt_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) +bxt_get_buf_trans_hdmi(struct intel_encoder *encoder, int *n_entries) { *n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi); return bxt_ddi_translations_hdmi; } static const struct cnl_ddi_buf_trans * -cnl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) +cnl_get_buf_trans_hdmi(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; if (voltage == VOLTAGE_INFO_0_85V) { @@ -907,8 +950,9 @@ cnl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) } static const struct cnl_ddi_buf_trans * -cnl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +cnl_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; if (voltage == VOLTAGE_INFO_0_85V) { @@ -928,8 +972,9 @@ cnl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) } static const struct cnl_ddi_buf_trans * -cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) +cnl_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; if (dev_priv->vbt.edp.low_vswing) { @@ -948,14 +993,16 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) } return NULL; } else { - return cnl_get_buf_trans_dp(dev_priv, n_entries); + return cnl_get_buf_trans_dp(encoder, n_entries); } } static const struct cnl_ddi_buf_trans * -icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, +icl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + if (type == INTEL_OUTPUT_HDMI) { *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); return icl_combo_phy_ddi_translations_hdmi; @@ -972,7 +1019,7 @@ icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, } static const struct icl_mg_phy_ddi_buf_trans * -icl_get_mg_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, +icl_get_mg_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { if (type == INTEL_OUTPUT_HDMI) { @@ -988,7 +1035,7 @@ icl_get_mg_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, } static const struct cnl_ddi_buf_trans * -ehl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, +ehl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { if (type != INTEL_OUTPUT_HDMI && type != INTEL_OUTPUT_EDP) { @@ -996,15 +1043,15 @@ ehl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, return ehl_combo_phy_ddi_translations_dp; } - return icl_get_combo_buf_trans(dev_priv, type, rate, n_entries); + return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } static const struct cnl_ddi_buf_trans * -tgl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, +tgl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { if (type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_EDP) { - return icl_get_combo_buf_trans(dev_priv, type, rate, n_entries); + return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } else if (rate > 270000) { *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr2); return tgl_combo_phy_ddi_translations_dp_hbr2; @@ -1014,6 +1061,22 @@ tgl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, return tgl_combo_phy_ddi_translations_dp_hbr; } +static const struct tgl_dkl_phy_ddi_buf_trans * +tgl_get_dkl_buf_trans(struct intel_encoder *encoder, int type, int rate, + int *n_entries) +{ + if (type == INTEL_OUTPUT_HDMI) { + *n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans); + return tgl_dkl_phy_hdmi_ddi_trans; + } else if (rate > 270000) { + *n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans_hbr2); + return tgl_dkl_phy_dp_ddi_trans_hbr2; + } + + *n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans); + return tgl_dkl_phy_dp_ddi_trans; +} + static int intel_ddi_hdmi_level(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -1022,33 +1085,34 @@ static int intel_ddi_hdmi_level(struct intel_encoder *encoder) if (INTEL_GEN(dev_priv) >= 12) { if (intel_phy_is_combo(dev_priv, phy)) - tgl_get_combo_buf_trans(dev_priv, INTEL_OUTPUT_HDMI, + tgl_get_combo_buf_trans(encoder, INTEL_OUTPUT_HDMI, 0, &n_entries); else - n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans); + tgl_get_dkl_buf_trans(encoder, INTEL_OUTPUT_HDMI, 0, + &n_entries); default_entry = n_entries - 1; } else if (INTEL_GEN(dev_priv) == 11) { if (intel_phy_is_combo(dev_priv, phy)) - icl_get_combo_buf_trans(dev_priv, INTEL_OUTPUT_HDMI, + icl_get_combo_buf_trans(encoder, INTEL_OUTPUT_HDMI, 0, &n_entries); else - icl_get_mg_buf_trans(dev_priv, INTEL_OUTPUT_HDMI, 0, + icl_get_mg_buf_trans(encoder, INTEL_OUTPUT_HDMI, 0, &n_entries); default_entry = n_entries - 1; } else if (IS_CANNONLAKE(dev_priv)) { - cnl_get_buf_trans_hdmi(dev_priv, &n_entries); + cnl_get_buf_trans_hdmi(encoder, &n_entries); default_entry = n_entries - 1; } else if (IS_GEN9_LP(dev_priv)) { - bxt_get_buf_trans_hdmi(dev_priv, &n_entries); + bxt_get_buf_trans_hdmi(encoder, &n_entries); default_entry = n_entries - 1; } else if (IS_GEN9_BC(dev_priv)) { - intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + intel_ddi_get_buf_trans_hdmi(encoder, &n_entries); default_entry = 8; } else if (IS_BROADWELL(dev_priv)) { - intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + intel_ddi_get_buf_trans_hdmi(encoder, &n_entries); default_entry = 7; } else if (IS_HASWELL(dev_priv)) { - intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + intel_ddi_get_buf_trans_hdmi(encoder, &n_entries); default_entry = 6; } else { drm_WARN(&dev_priv->drm, 1, "ddi translation table missing\n"); @@ -1086,10 +1150,10 @@ static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder, ddi_translations = intel_ddi_get_buf_trans_fdi(dev_priv, &n_entries); else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) - ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, port, + ddi_translations = intel_ddi_get_buf_trans_edp(encoder, &n_entries); else - ddi_translations = intel_ddi_get_buf_trans_dp(dev_priv, port, + ddi_translations = intel_ddi_get_buf_trans_dp(encoder, &n_entries); /* If we're boosting the current, set bit 31 of trans1 */ @@ -1118,7 +1182,7 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder, enum port port = encoder->port; const struct ddi_buf_trans *ddi_translations; - ddi_translations = intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + ddi_translations = intel_ddi_get_buf_trans_hdmi(encoder, &n_entries); if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations)) return; @@ -1139,16 +1203,30 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder, static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, enum port port) { - i915_reg_t reg = DDI_BUF_CTL(port); - int i; + if (IS_BROXTON(dev_priv)) { + udelay(16); + return; + } - for (i = 0; i < 16; i++) { - udelay(1); - if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE) - return; + if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) & + DDI_BUF_IS_IDLE), 8)) + drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get idle\n", + port_name(port)); +} + +static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, + enum port port) +{ + /* Wait > 518 usecs for DDI_BUF_CTL to be non idle */ + if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) { + usleep_range(518, 1000); + return; } - drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n", - port_name(port)); + + if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & + DDI_BUF_IS_IDLE), 500)) + drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n", + port_name(port)); } static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) @@ -1349,10 +1427,9 @@ void hsw_fdi_link_train(struct intel_encoder *encoder, static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_digital_port *intel_dig_port = - enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - intel_dp->DP = intel_dig_port->saved_port_bits | + intel_dp->DP = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0); intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); } @@ -1608,7 +1685,6 @@ void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 ctl; if (INTEL_GEN(dev_priv) >= 11) { enum transcoder master_transcoder = crtc_state->master_transcoder; @@ -1626,10 +1702,9 @@ void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder, TRANS_DDI_FUNC_CTL2(cpu_transcoder), ctl2); } - ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state); - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) - ctl |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl); + intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), + intel_ddi_transcoder_func_reg_val_get(encoder, + crtc_state)); } /* @@ -2027,9 +2102,8 @@ static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv, static void skl_ddi_set_iboost(struct intel_encoder *encoder, int level, enum intel_output_type type) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum port port = encoder->port; u8 iboost; if (type == INTEL_OUTPUT_HDMI) @@ -2042,11 +2116,13 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, int n_entries; if (type == INTEL_OUTPUT_HDMI) - ddi_translations = intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + ddi_translations = intel_ddi_get_buf_trans_hdmi(encoder, &n_entries); else if (type == INTEL_OUTPUT_EDP) - ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, port, &n_entries); + ddi_translations = intel_ddi_get_buf_trans_edp(encoder, + &n_entries); else - ddi_translations = intel_ddi_get_buf_trans_dp(dev_priv, port, &n_entries); + ddi_translations = intel_ddi_get_buf_trans_dp(encoder, + &n_entries); if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations)) return; @@ -2062,9 +2138,9 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, return; } - _skl_ddi_set_iboost(dev_priv, port, iboost); + _skl_ddi_set_iboost(dev_priv, encoder->port, iboost); - if (port == PORT_A && intel_dig_port->max_lanes == 4) + if (encoder->port == PORT_A && dig_port->max_lanes == 4) _skl_ddi_set_iboost(dev_priv, PORT_E, iboost); } @@ -2077,11 +2153,11 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder, int n_entries; if (type == INTEL_OUTPUT_HDMI) - ddi_translations = bxt_get_buf_trans_hdmi(dev_priv, &n_entries); + ddi_translations = bxt_get_buf_trans_hdmi(encoder, &n_entries); else if (type == INTEL_OUTPUT_EDP) - ddi_translations = bxt_get_buf_trans_edp(dev_priv, &n_entries); + ddi_translations = bxt_get_buf_trans_edp(encoder, &n_entries); else - ddi_translations = bxt_get_buf_trans_dp(dev_priv, &n_entries); + ddi_translations = bxt_get_buf_trans_dp(encoder, &n_entries); if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations)) return; @@ -2095,45 +2171,46 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder, ddi_translations[level].deemphasis); } -u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) +static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp) { + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); enum port port = encoder->port; enum phy phy = intel_port_to_phy(dev_priv, port); int n_entries; if (INTEL_GEN(dev_priv) >= 12) { if (intel_phy_is_combo(dev_priv, phy)) - tgl_get_combo_buf_trans(dev_priv, encoder->type, + tgl_get_combo_buf_trans(encoder, encoder->type, intel_dp->link_rate, &n_entries); else - n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans); + tgl_get_dkl_buf_trans(encoder, encoder->type, + intel_dp->link_rate, &n_entries); } else if (INTEL_GEN(dev_priv) == 11) { if (IS_ELKHARTLAKE(dev_priv)) - ehl_get_combo_buf_trans(dev_priv, encoder->type, + ehl_get_combo_buf_trans(encoder, encoder->type, intel_dp->link_rate, &n_entries); else if (intel_phy_is_combo(dev_priv, phy)) - icl_get_combo_buf_trans(dev_priv, encoder->type, + icl_get_combo_buf_trans(encoder, encoder->type, intel_dp->link_rate, &n_entries); else - icl_get_mg_buf_trans(dev_priv, encoder->type, + icl_get_mg_buf_trans(encoder, encoder->type, intel_dp->link_rate, &n_entries); } else if (IS_CANNONLAKE(dev_priv)) { if (encoder->type == INTEL_OUTPUT_EDP) - cnl_get_buf_trans_edp(dev_priv, &n_entries); + cnl_get_buf_trans_edp(encoder, &n_entries); else - cnl_get_buf_trans_dp(dev_priv, &n_entries); + cnl_get_buf_trans_dp(encoder, &n_entries); } else if (IS_GEN9_LP(dev_priv)) { if (encoder->type == INTEL_OUTPUT_EDP) - bxt_get_buf_trans_edp(dev_priv, &n_entries); + bxt_get_buf_trans_edp(encoder, &n_entries); else - bxt_get_buf_trans_dp(dev_priv, &n_entries); + bxt_get_buf_trans_dp(encoder, &n_entries); } else { if (encoder->type == INTEL_OUTPUT_EDP) - intel_ddi_get_buf_trans_edp(dev_priv, port, &n_entries); + intel_ddi_get_buf_trans_edp(encoder, &n_entries); else - intel_ddi_get_buf_trans_dp(dev_priv, port, &n_entries); + intel_ddi_get_buf_trans_dp(encoder, &n_entries); } if (drm_WARN_ON(&dev_priv->drm, n_entries < 1)) @@ -2151,19 +2228,9 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) * used on all DDI platforms. Should that change we need to * rethink this code. */ -u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder, u8 voltage_swing) -{ - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - return DP_TRAIN_PRE_EMPH_LEVEL_3; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - return DP_TRAIN_PRE_EMPH_LEVEL_2; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - return DP_TRAIN_PRE_EMPH_LEVEL_1; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: - default: - return DP_TRAIN_PRE_EMPH_LEVEL_0; - } +static u8 intel_ddi_dp_preemph_max(struct intel_dp *intel_dp) +{ + return DP_TRAIN_PRE_EMPH_LEVEL_3; } static void cnl_ddi_vswing_program(struct intel_encoder *encoder, @@ -2176,11 +2243,11 @@ static void cnl_ddi_vswing_program(struct intel_encoder *encoder, u32 val; if (type == INTEL_OUTPUT_HDMI) - ddi_translations = cnl_get_buf_trans_hdmi(dev_priv, &n_entries); + ddi_translations = cnl_get_buf_trans_hdmi(encoder, &n_entries); else if (type == INTEL_OUTPUT_EDP) - ddi_translations = cnl_get_buf_trans_edp(dev_priv, &n_entries); + ddi_translations = cnl_get_buf_trans_edp(encoder, &n_entries); else - ddi_translations = cnl_get_buf_trans_dp(dev_priv, &n_entries); + ddi_translations = cnl_get_buf_trans_dp(encoder, &n_entries); if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations)) return; @@ -2297,22 +2364,23 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, intel_de_write(dev_priv, CNL_PORT_TX_DW5_GRP(port), val); } -static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, - u32 level, enum phy phy, int type, - int rate) +static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, + u32 level, int type, int rate) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); const struct cnl_ddi_buf_trans *ddi_translations = NULL; u32 n_entries, val; int ln; if (INTEL_GEN(dev_priv) >= 12) - ddi_translations = tgl_get_combo_buf_trans(dev_priv, type, rate, + ddi_translations = tgl_get_combo_buf_trans(encoder, type, rate, &n_entries); else if (IS_ELKHARTLAKE(dev_priv)) - ddi_translations = ehl_get_combo_buf_trans(dev_priv, type, rate, + ddi_translations = ehl_get_combo_buf_trans(encoder, type, rate, &n_entries); else - ddi_translations = icl_get_combo_buf_trans(dev_priv, type, rate, + ddi_translations = icl_get_combo_buf_trans(encoder, type, rate, &n_entries); if (!ddi_translations) return; @@ -2424,7 +2492,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder, intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val); /* 5. Program swing and de-emphasis */ - icl_ddi_combo_vswing_program(dev_priv, level, phy, type, rate); + icl_ddi_combo_vswing_program(encoder, level, type, rate); /* 6. Set training enable to trigger update */ val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN0(phy)); @@ -2448,7 +2516,7 @@ static void icl_mg_phy_ddi_vswing_sequence(struct intel_encoder *encoder, rate = intel_dp->link_rate; } - ddi_translations = icl_get_mg_buf_trans(dev_priv, type, rate, + ddi_translations = icl_get_mg_buf_trans(encoder, type, rate, &n_entries); /* The table does not have values for level 3 and level 9. */ if (level >= n_entries || level == 3 || level == 9) { @@ -2585,15 +2653,17 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, int link_clock, enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); const struct tgl_dkl_phy_ddi_buf_trans *ddi_translations; u32 n_entries, val, ln, dpcnt_mask, dpcnt_val; + int rate = 0; if (type == INTEL_OUTPUT_HDMI) { - n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans); - ddi_translations = tgl_dkl_phy_hdmi_ddi_trans; - } else { - n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans); - ddi_translations = tgl_dkl_phy_dp_ddi_trans; + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + rate = intel_dp->link_rate; } + ddi_translations = tgl_get_dkl_buf_trans(encoder, encoder->type, rate, + &n_entries); + if (level >= n_entries) level = n_entries - 1; @@ -2964,15 +3034,15 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder) } static void -icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port, +icl_program_mg_dp_mode(struct intel_digital_port *dig_port, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); - enum tc_port tc_port = intel_port_to_tc(dev_priv, intel_dig_port->base.port); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port); u32 ln0, ln1, pin_assignment; u8 width; - if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT) + if (dig_port->tc_mode == TC_PORT_TBT_ALT) return; if (INTEL_GEN(dev_priv) >= 12) { @@ -2991,13 +3061,13 @@ icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port, ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE); /* DPPATC */ - pin_assignment = intel_tc_port_get_pin_assignment_mask(intel_dig_port); + pin_assignment = intel_tc_port_get_pin_assignment_mask(dig_port); width = crtc_state->lane_count; switch (pin_assignment) { case 0x0: drm_WARN_ON(&dev_priv->drm, - intel_dig_port->tc_mode != TC_PORT_LEGACY); + dig_port->tc_mode != TC_PORT_LEGACY); if (width == 1) { ln1 |= MG_DP_MODE_CFG_DP_X1_MODE; } else { @@ -3344,11 +3414,10 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + struct intel_hdmi *intel_hdmi = &dig_port->hdmi; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int level = intel_ddi_hdmi_level(encoder); - struct intel_digital_port *dig_port = enc_to_dig_port(encoder); intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); intel_ddi_clk_select(encoder, crtc_state); @@ -3375,9 +3444,9 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state, intel_ddi_enable_pipe_clock(encoder, crtc_state); - intel_dig_port->set_infoframes(encoder, - crtc_state->has_infoframe, - crtc_state, conn_state); + dig_port->set_infoframes(encoder, + crtc_state->has_infoframe, + crtc_state, conn_state); } static void intel_ddi_pre_enable(struct intel_atomic_state *state, @@ -3943,10 +4012,9 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = - to_i915(intel_dig_port->base.base.dev); - enum port port = intel_dig_port->base.port; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + enum port port = dig_port->base.port; u32 dp_tp_ctl, ddi_buf_ctl; bool wait = false; @@ -3985,7 +4053,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); - udelay(600); + intel_wait_ddi_buf_active(dev_priv, port); } static void intel_ddi_set_link_train(struct intel_dp *intel_dp, @@ -4155,11 +4223,6 @@ void intel_ddi_get_config(struct intel_encoder *encoder, if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder))) return; - if (INTEL_GEN(dev_priv) >= 12) { - intel_dp->regs.dp_tp_ctl = TGL_DP_TP_CTL(cpu_transcoder); - intel_dp->regs.dp_tp_status = TGL_DP_TP_STATUS(cpu_transcoder); - } - intel_dsc_get_config(encoder, pipe_config); temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); @@ -4261,6 +4324,16 @@ void intel_ddi_get_config(struct intel_encoder *encoder, break; } + if (INTEL_GEN(dev_priv) >= 12) { + enum transcoder transcoder = + intel_dp_mst_is_slave_trans(pipe_config) ? + pipe_config->mst_master_transcoder : + pipe_config->cpu_transcoder; + + intel_dp->regs.dp_tp_ctl = TGL_DP_TP_CTL(transcoder); + intel_dp->regs.dp_tp_status = TGL_DP_TP_STATUS(transcoder); + } + pipe_config->has_audio = intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); @@ -4496,39 +4569,41 @@ static const struct drm_encoder_funcs intel_ddi_funcs = { }; static struct intel_connector * -intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) +intel_ddi_init_dp_connector(struct intel_digital_port *dig_port) { - struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); struct intel_connector *connector; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; connector = intel_connector_alloc(); if (!connector) return NULL; - intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); - intel_dig_port->dp.prepare_link_retrain = - intel_ddi_prepare_link_retrain; - intel_dig_port->dp.set_link_train = intel_ddi_set_link_train; - intel_dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train; + dig_port->dp.output_reg = DDI_BUF_CTL(port); + dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain; + dig_port->dp.set_link_train = intel_ddi_set_link_train; + dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train; if (INTEL_GEN(dev_priv) >= 12) - intel_dig_port->dp.set_signal_levels = tgl_set_signal_levels; + dig_port->dp.set_signal_levels = tgl_set_signal_levels; else if (INTEL_GEN(dev_priv) >= 11) - intel_dig_port->dp.set_signal_levels = icl_set_signal_levels; + dig_port->dp.set_signal_levels = icl_set_signal_levels; else if (IS_CANNONLAKE(dev_priv)) - intel_dig_port->dp.set_signal_levels = cnl_set_signal_levels; + dig_port->dp.set_signal_levels = cnl_set_signal_levels; else if (IS_GEN9_LP(dev_priv)) - intel_dig_port->dp.set_signal_levels = bxt_set_signal_levels; + dig_port->dp.set_signal_levels = bxt_set_signal_levels; else - intel_dig_port->dp.set_signal_levels = hsw_set_signal_levels; + dig_port->dp.set_signal_levels = hsw_set_signal_levels; + + dig_port->dp.voltage_max = intel_ddi_dp_voltage_max; + dig_port->dp.preemph_max = intel_ddi_dp_preemph_max; if (INTEL_GEN(dev_priv) < 12) { - intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port); - intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port); + dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port); + dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port); } - if (!intel_dp_init_connector(intel_dig_port, connector)) { + if (!intel_dp_init_connector(dig_port, connector)) { kfree(connector); return NULL; } @@ -4727,29 +4802,29 @@ static bool bdw_digital_port_connected(struct intel_encoder *encoder) } static struct intel_connector * -intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) +intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port) { struct intel_connector *connector; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; connector = intel_connector_alloc(); if (!connector) return NULL; - intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); - intel_hdmi_init_connector(intel_dig_port, connector); + dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); + intel_hdmi_init_connector(dig_port, connector); return connector; } -static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dport) +static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port) { - struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - if (dport->base.port != PORT_A) + if (dig_port->base.port != PORT_A) return false; - if (dport->saved_port_bits & DDI_A_4_LANES) + if (dig_port->saved_port_bits & DDI_A_4_LANES) return false; /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only @@ -4771,10 +4846,10 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dport) } static int -intel_ddi_max_lanes(struct intel_digital_port *intel_dport) +intel_ddi_max_lanes(struct intel_digital_port *dig_port) { - struct drm_i915_private *dev_priv = to_i915(intel_dport->base.base.dev); - enum port port = intel_dport->base.port; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + enum port port = dig_port->base.port; int max_lanes = 4; if (INTEL_GEN(dev_priv) >= 11) @@ -4793,10 +4868,10 @@ intel_ddi_max_lanes(struct intel_digital_port *intel_dport) * wasn't lit up at boot. Force this bit set when needed * so we use the proper lane count for our calculations. */ - if (intel_ddi_a_force_4_lanes(intel_dport)) { + if (intel_ddi_a_force_4_lanes(dig_port)) { drm_dbg_kms(&dev_priv->drm, "Forcing DDI_A_4_LANES for port A\n"); - intel_dport->saved_port_bits |= DDI_A_4_LANES; + dig_port->saved_port_bits |= DDI_A_4_LANES; max_lanes = 4; } @@ -4805,7 +4880,7 @@ intel_ddi_max_lanes(struct intel_digital_port *intel_dport) void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { - struct intel_digital_port *intel_dig_port; + struct intel_digital_port *dig_port; struct intel_encoder *encoder; bool init_hdmi, init_dp, init_lspcon = false; enum phy phy = intel_port_to_phy(dev_priv, port); @@ -4834,11 +4909,11 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) return; } - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); - if (!intel_dig_port) + dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); + if (!dig_port) return; - encoder = &intel_dig_port->base; + encoder = &dig_port->base; drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port)); @@ -4865,49 +4940,49 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->pipe_mask = ~0; if (INTEL_GEN(dev_priv) >= 11) - intel_dig_port->saved_port_bits = intel_de_read(dev_priv, - DDI_BUF_CTL(port)) & - DDI_BUF_PORT_REVERSAL; + dig_port->saved_port_bits = + intel_de_read(dev_priv, DDI_BUF_CTL(port)) + & DDI_BUF_PORT_REVERSAL; else - intel_dig_port->saved_port_bits = intel_de_read(dev_priv, - DDI_BUF_CTL(port)) & - (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); + dig_port->saved_port_bits = + intel_de_read(dev_priv, DDI_BUF_CTL(port)) + & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); - intel_dig_port->dp.output_reg = INVALID_MMIO_REG; - intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port); - intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); + dig_port->dp.output_reg = INVALID_MMIO_REG; + dig_port->max_lanes = intel_ddi_max_lanes(dig_port); + dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); if (intel_phy_is_tc(dev_priv, phy)) { bool is_legacy = !intel_bios_port_supports_typec_usb(dev_priv, port) && !intel_bios_port_supports_tbt(dev_priv, port); - intel_tc_port_init(intel_dig_port, is_legacy); + intel_tc_port_init(dig_port, is_legacy); encoder->update_prepare = intel_ddi_update_prepare; encoder->update_complete = intel_ddi_update_complete; } drm_WARN_ON(&dev_priv->drm, port > PORT_I); - intel_dig_port->ddi_io_power_domain = POWER_DOMAIN_PORT_DDI_A_IO + + dig_port->ddi_io_power_domain = POWER_DOMAIN_PORT_DDI_A_IO + port - PORT_A; if (init_dp) { - if (!intel_ddi_init_dp_connector(intel_dig_port)) + if (!intel_ddi_init_dp_connector(dig_port)) goto err; - intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; + dig_port->hpd_pulse = intel_dp_hpd_pulse; } /* In theory we don't need the encoder->type check, but leave it just in * case we have some really bad VBTs... */ if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { - if (!intel_ddi_init_hdmi_connector(intel_dig_port)) + if (!intel_ddi_init_hdmi_connector(dig_port)) goto err; } if (init_lspcon) { - if (lspcon_init(intel_dig_port)) + if (lspcon_init(dig_port)) /* TODO: handle hdmi info frame part */ drm_dbg_kms(&dev_priv->drm, "LSPCON init success on port %c\n", @@ -4924,26 +4999,26 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) if (INTEL_GEN(dev_priv) >= 11) { if (intel_phy_is_tc(dev_priv, phy)) - intel_dig_port->connected = intel_tc_port_connected; + dig_port->connected = intel_tc_port_connected; else - intel_dig_port->connected = lpt_digital_port_connected; + dig_port->connected = lpt_digital_port_connected; } else if (INTEL_GEN(dev_priv) >= 8) { if (port == PORT_A || IS_GEN9_LP(dev_priv)) - intel_dig_port->connected = bdw_digital_port_connected; + dig_port->connected = bdw_digital_port_connected; else - intel_dig_port->connected = lpt_digital_port_connected; + dig_port->connected = lpt_digital_port_connected; } else { if (port == PORT_A) - intel_dig_port->connected = hsw_digital_port_connected; + dig_port->connected = hsw_digital_port_connected; else - intel_dig_port->connected = lpt_digital_port_connected; + dig_port->connected = lpt_digital_port_connected; } - intel_infoframe_init(intel_dig_port); + intel_infoframe_init(dig_port); return; err: drm_encoder_cleanup(&encoder->base); - kfree(intel_dig_port); + kfree(dig_port); } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index fbdf8ddde486..077e9dbbe367 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -42,9 +42,6 @@ void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, struct intel_crtc_state *crtc_state); u32 bxt_signal_levels(struct intel_dp *intel_dp); u32 ddi_signal_levels(struct intel_dp *intel_dp); -u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); -u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder, - u8 voltage_swing); int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, bool enable); void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c1836095ea38..729ec6e0d43a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -35,6 +35,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_dp_helper.h> #include <drm/drm_edid.h> #include <drm/drm_fourcc.h> @@ -1611,13 +1612,13 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) } void vlv_wait_port_ready(struct drm_i915_private *dev_priv, - struct intel_digital_port *dport, + struct intel_digital_port *dig_port, unsigned int expected_mask) { u32 port_mask; i915_reg_t dpll_reg; - switch (dport->base.port) { + switch (dig_port->base.port) { case PORT_B: port_mask = DPLL_PORTB_READY_MASK; dpll_reg = DPLL(0); @@ -1639,7 +1640,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, port_mask, expected_mask, 1000)) drm_WARN(&dev_priv->drm, 1, "timed out waiting for [ENCODER:%d:%s] port ready: got 0x%x, expected 0x%x\n", - dport->base.base.base.id, dport->base.base.name, + dig_port->base.base.base.id, dig_port->base.base.name, intel_de_read(dev_priv, dpll_reg) & port_mask, expected_mask); } @@ -3822,6 +3823,17 @@ skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, return true; } +unsigned int +intel_plane_fence_y_offset(const struct intel_plane_state *plane_state) +{ + int x = 0, y = 0; + + intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, + plane_state->color_plane[0].offset, 0); + + return y; +} + static int skl_check_main_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); @@ -4812,11 +4824,18 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { - if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) + switch (plane_state->hw.color_encoding) { + case DRM_COLOR_YCBCR_BT709: plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; - else - plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709; - + break; + case DRM_COLOR_YCBCR_BT2020: + plane_color_ctl |= + PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; + break; + default: + plane_color_ctl |= + PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; + } if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; } else if (fb->format->is_yuv) { @@ -4879,7 +4898,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) int ret; /* reset doesn't touch the display */ - if (!i915_modparams.force_reset_modeset_test && + if (!dev_priv->params.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) return; @@ -6424,8 +6443,7 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s * 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->hw.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED) + if (new_crtc_state->update_pipe && old_crtc_state->inherited) return true; return !old_crtc_state->ips_enabled; @@ -7212,30 +7230,33 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) { if (phy == PHY_NONE) return false; - - if (IS_ELKHARTLAKE(dev_priv)) + else if (IS_ROCKETLAKE(dev_priv)) + return phy <= PHY_D; + else if (IS_ELKHARTLAKE(dev_priv)) return phy <= PHY_C; - - if (INTEL_GEN(dev_priv) >= 11) + else if (INTEL_GEN(dev_priv) >= 11) return phy <= PHY_B; - - return false; + else + return false; } bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) { - if (INTEL_GEN(dev_priv) >= 12) + if (IS_ROCKETLAKE(dev_priv)) + return false; + else if (INTEL_GEN(dev_priv) >= 12) return phy >= PHY_D && phy <= PHY_I; - - if (INTEL_GEN(dev_priv) >= 11 && !IS_ELKHARTLAKE(dev_priv)) + else if (INTEL_GEN(dev_priv) >= 11 && !IS_ELKHARTLAKE(dev_priv)) return phy >= PHY_C && phy <= PHY_F; - - return false; + else + return false; } enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port) { - if (IS_ELKHARTLAKE(i915) && port == PORT_D) + if (IS_ROCKETLAKE(i915) && port >= PORT_D) + return (enum phy)port - 1; + else if (IS_ELKHARTLAKE(i915) && port == PORT_D) return PHY_A; return (enum phy)port; @@ -7506,6 +7527,10 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state, intel_crtc_vblank_on(new_crtc_state); intel_encoders_enable(state, crtc); + + /* prevents spurious underruns */ + if (IS_GEN(dev_priv, 2)) + intel_wait_for_vblank(dev_priv, pipe); } static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) @@ -7579,6 +7604,8 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, to_intel_bw_state(dev_priv->bw_obj.state); struct intel_cdclk_state *cdclk_state = to_intel_cdclk_state(dev_priv->cdclk.obj.state); + struct intel_dbuf_state *dbuf_state = + to_intel_dbuf_state(dev_priv->dbuf.obj.state); struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); enum intel_display_power_domain domain; @@ -7652,6 +7679,8 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, cdclk_state->min_voltage_level[pipe] = 0; cdclk_state->active_pipes &= ~BIT(pipe); + dbuf_state->active_pipes &= ~BIT(pipe); + bw_state->data_rate[pipe] = 0; bw_state->num_active_planes[pipe] = 0; } @@ -7869,7 +7898,7 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) if (!hsw_crtc_supports_ips(crtc)) return false; - if (!i915_modparams.enable_ips) + if (!dev_priv->params.enable_ips) return false; if (crtc_state->pipe_bpp > 24) @@ -8140,8 +8169,8 @@ static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv) static bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) { - if (i915_modparams.panel_use_ssc >= 0) - return i915_modparams.panel_use_ssc != 0; + if (dev_priv->params.panel_use_ssc >= 0) + return dev_priv->params.panel_use_ssc != 0; return dev_priv->vbt.lvds_use_ssc && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } @@ -10044,7 +10073,8 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) drm_WARN_ON(&dev_priv->drm, crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB); - if (crtc_state->limited_color_range) + if (crtc_state->limited_color_range && + !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO)) val |= PIPECONF_COLOR_RANGE_SELECT; if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) @@ -10882,7 +10912,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum intel_display_power_domain power_domain; - unsigned long panel_transcoder_mask = 0; + unsigned long panel_transcoder_mask = BIT(TRANSCODER_EDP); unsigned long enabled_panel_transcoders = 0; enum transcoder panel_transcoder; intel_wakeref_t wf; @@ -10892,9 +10922,6 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, panel_transcoder_mask |= BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1); - if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP)) - panel_transcoder_mask |= BIT(TRANSCODER_EDP); - /* * The pipe->transcoder mapping is fixed with the exception of the eDP * and DSI transcoders handled below. @@ -10905,9 +10932,8 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, * XXX: Do intel_display_power_get_if_enabled before reading this (for * consistency and less surprising code; it's in always on power). */ - for_each_set_bit(panel_transcoder, - &panel_transcoder_mask, - ARRAY_SIZE(INTEL_INFO(dev_priv)->trans_offsets)) { + for_each_cpu_transcoder_masked(dev_priv, panel_transcoder, + panel_transcoder_mask) { bool force_thru = false; enum pipe trans_pipe; @@ -12499,7 +12525,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) continue; for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, linked) { - if (!icl_is_nv12_y_plane(linked->id)) + if (!icl_is_nv12_y_plane(dev_priv, linked->id)) continue; if (crtc_state->active_planes & BIT(linked->id)) @@ -12545,6 +12571,10 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) plane_state->cus_ctl |= PLANE_CUS_PLANE_7; else if (linked->id == PLANE_SPRITE4) plane_state->cus_ctl |= PLANE_CUS_PLANE_6; + else if (linked->id == PLANE_SPRITE3) + plane_state->cus_ctl |= PLANE_CUS_PLANE_5_RKL; + else if (linked->id == PLANE_SPRITE2) + plane_state->cus_ctl |= PLANE_CUS_PLANE_4_RKL; else MISSING_CASE(linked->id); } @@ -12568,12 +12598,15 @@ static u16 hsw_linetime_wm(const struct intel_crtc_state *crtc_state) { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int linetime_wm; if (!crtc_state->hw.enable) return 0; - return DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8, - adjusted_mode->crtc_clock); + linetime_wm = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8, + adjusted_mode->crtc_clock); + + return min(linetime_wm, 0x1ff); } static u16 hsw_ips_linetime_wm(const struct intel_crtc_state *crtc_state, @@ -12581,12 +12614,15 @@ static u16 hsw_ips_linetime_wm(const struct intel_crtc_state *crtc_state, { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int linetime_wm; if (!crtc_state->hw.enable) return 0; - return DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8, - cdclk_state->logical.cdclk); + linetime_wm = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8, + cdclk_state->logical.cdclk); + + return min(linetime_wm, 0x1ff); } static u16 skl_linetime_wm(const struct intel_crtc_state *crtc_state) @@ -12595,7 +12631,7 @@ static u16 skl_linetime_wm(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - u16 linetime_wm; + int linetime_wm; if (!crtc_state->hw.enable) return 0; @@ -12607,7 +12643,7 @@ static u16 skl_linetime_wm(const struct intel_crtc_state *crtc_state) if (IS_GEN9_LP(dev_priv) && dev_priv->ipc_enabled) linetime_wm /= 2; - return linetime_wm; + return min(linetime_wm, 0x1ff); } static int hsw_compute_linetime_wm(struct intel_atomic_state *state, @@ -13570,8 +13606,8 @@ pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, static bool fastboot_enabled(struct drm_i915_private *dev_priv) { - if (i915_modparams.fastboot != -1) - return i915_modparams.fastboot; + if (dev_priv->params.fastboot != -1) + return dev_priv->params.fastboot; /* Enable fastboot by default on Skylake and newer */ if (INTEL_GEN(dev_priv) >= 9) @@ -13595,8 +13631,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, bool ret = true; u32 bp_gamma = 0; bool fixup_inherited = fastset && - (current_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) && - !(pipe_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED); + current_config->inherited && !pipe_config->inherited; if (fixup_inherited && !fastboot_enabled(dev_priv)) { drm_dbg_kms(&dev_priv->drm, @@ -14007,10 +14042,10 @@ static void verify_wm_state(struct intel_crtc *crtc, hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv); if (INTEL_GEN(dev_priv) >= 11 && - hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask) + hw_enabled_slices != dev_priv->dbuf.enabled_slices) drm_err(&dev_priv->drm, "mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n", - dev_priv->enabled_dbuf_slices_mask, + dev_priv->dbuf.enabled_slices, hw_enabled_slices); /* planes */ @@ -14404,6 +14439,8 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) drm_calc_timestamping_constants(&crtc->base, adjusted_mode); + crtc->mode_flags = crtc_state->mode_flags; + /* * The scanline counter increments at the leading edge of hsync. * @@ -14551,20 +14588,12 @@ static int intel_modeset_checks(struct intel_atomic_state *state) state->modeset = true; state->active_pipes = intel_calc_active_pipes(state, dev_priv->active_pipes); - state->active_pipe_changes = state->active_pipes ^ dev_priv->active_pipes; - - if (state->active_pipe_changes) { + if (state->active_pipes != dev_priv->active_pipes) { ret = _intel_atomic_lock_global_state(state); if (ret) return ret; } - ret = intel_modeset_calc_cdclk(state); - if (ret) - return ret; - - intel_modeset_clear_plls(state); - if (IS_HASWELL(dev_priv)) return hsw_mode_set_planes_workaround(state); @@ -14641,11 +14670,10 @@ static bool active_planes_affects_min_cdclk(struct drm_i915_private *dev_priv) /* See {hsw,vlv,ivb}_plane_ratio() */ return IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv) || IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv) || - IS_IVYBRIDGE(dev_priv); + IS_IVYBRIDGE(dev_priv) || (INTEL_GEN(dev_priv) >= 11); } -static int intel_atomic_check_planes(struct intel_atomic_state *state, - bool *need_cdclk_calc) +static int intel_atomic_check_planes(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *old_crtc_state, *new_crtc_state; @@ -14687,7 +14715,13 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state, old_active_planes = old_crtc_state->active_planes & ~BIT(PLANE_CURSOR); new_active_planes = new_crtc_state->active_planes & ~BIT(PLANE_CURSOR); - if (hweight8(old_active_planes) == hweight8(new_active_planes)) + /* + * Not only the number of planes, but if the plane configuration had + * changed might already mean we need to recompute min CDCLK, + * because different planes might consume different amount of Dbuf bandwidth + * according to formula: Bw per plane = Pixel rate * bpp * pipe/plane scale factor + */ + if (old_active_planes == new_active_planes) continue; ret = intel_crtc_add_planes_to_state(state, crtc, new_active_planes); @@ -14695,6 +14729,21 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state, return ret; } + return 0; +} + +static int intel_atomic_check_cdclk(struct intel_atomic_state *state, + bool *need_cdclk_calc) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_cdclk_state *new_cdclk_state; + struct intel_plane_state *plane_state; + struct intel_bw_state *new_bw_state; + struct intel_plane *plane; + int min_cdclk = 0; + enum pipe pipe; + int ret; + int i; /* * active_planes bitmask has been updated, and potentially * affected planes are part of the state. We can now @@ -14706,6 +14755,30 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state, return ret; } + new_cdclk_state = intel_atomic_get_new_cdclk_state(state); + + if (new_cdclk_state && new_cdclk_state->force_min_cdclk_changed) + *need_cdclk_calc = true; + + ret = dev_priv->display.bw_calc_min_cdclk(state); + if (ret) + return ret; + + new_bw_state = intel_atomic_get_new_bw_state(state); + + if (!new_cdclk_state || !new_bw_state) + return 0; + + for_each_pipe(dev_priv, pipe) { + min_cdclk = max(new_cdclk_state->min_cdclk[pipe], min_cdclk); + + /* + * Currently do this change only if we need to increase + */ + if (new_bw_state->min_cdclk > min_cdclk) + *need_cdclk_calc = true; + } + return 0; } @@ -14757,16 +14830,13 @@ static int intel_atomic_check(struct drm_device *dev, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_atomic_state *state = to_intel_atomic_state(_state); struct intel_crtc_state *old_crtc_state, *new_crtc_state; - struct intel_cdclk_state *new_cdclk_state; struct intel_crtc *crtc; int ret, i; bool any_ms = false; - /* Catch I915_MODE_FLAG_INHERITED */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (new_crtc_state->uapi.mode.private_flags != - old_crtc_state->uapi.mode.private_flags) + if (new_crtc_state->inherited != old_crtc_state->inherited) new_crtc_state->uapi.mode_changed = true; } @@ -14868,14 +14938,10 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; - ret = intel_atomic_check_planes(state, &any_ms); + ret = intel_atomic_check_planes(state); if (ret) goto fail; - new_cdclk_state = intel_atomic_get_new_cdclk_state(state); - if (new_cdclk_state && new_cdclk_state->force_min_cdclk_changed) - any_ms = true; - /* * distrust_bios_wm will force a full dbuf recomputation * but the hardware state will only get updated accordingly @@ -14896,10 +14962,6 @@ static int intel_atomic_check(struct drm_device *dev, goto fail; } - ret = intel_atomic_check_crtcs(state); - if (ret) - goto fail; - intel_fbc_choose_crtc(dev_priv, state); ret = calc_watermark_data(state); if (ret) @@ -14909,6 +14971,22 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; + ret = intel_atomic_check_cdclk(state, &any_ms); + if (ret) + goto fail; + + if (any_ms) { + ret = intel_modeset_calc_cdclk(state); + if (ret) + return ret; + + intel_modeset_clear_plls(state); + } + + ret = intel_atomic_check_crtcs(state); + if (ret) + goto fail; + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!needs_modeset(new_crtc_state) && @@ -14939,8 +15017,24 @@ static int intel_atomic_check(struct drm_device *dev, static int intel_atomic_prepare_commit(struct intel_atomic_state *state) { - return drm_atomic_helper_prepare_planes(state->base.dev, - &state->base); + struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int i, ret; + + ret = drm_atomic_helper_prepare_planes(state->base.dev, &state->base); + if (ret < 0) + return ret; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + bool mode_changed = needs_modeset(crtc_state); + + if (mode_changed || crtc_state->update_pipe || + crtc_state->uapi.color_mgmt_changed) { + intel_dsb_prepare(crtc_state); + } + } + + return 0; } u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) @@ -15112,7 +15206,7 @@ static void intel_update_crtc(struct intel_atomic_state *state, * of enabling them on the CRTC's first fastset. */ if (new_crtc_state->update_pipe && !modeset && - old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) + old_crtc_state->inherited) intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } @@ -15204,29 +15298,6 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) } } -static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask; - u8 required_slices = state->enabled_dbuf_slices_mask; - u8 slices_union = hw_enabled_slices | required_slices; - - /* If 2nd DBuf slice required, enable it here */ - if (INTEL_GEN(dev_priv) >= 11 && slices_union != hw_enabled_slices) - icl_dbuf_slices_update(dev_priv, slices_union); -} - -static void icl_dbuf_slice_post_update(struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask; - u8 required_slices = state->enabled_dbuf_slices_mask; - - /* If 2nd DBuf slice is no more required disable it */ - if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices) - icl_dbuf_slices_update(dev_priv, required_slices); -} - static void skl_commit_modeset_enables(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); @@ -15393,15 +15464,27 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat &wait_reset); } +static void intel_cleanup_dsbs(struct intel_atomic_state *state) +{ + struct intel_crtc_state *old_crtc_state, *new_crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) + intel_dsb_cleanup(old_crtc_state); +} + static void intel_atomic_cleanup_work(struct work_struct *work) { - struct drm_atomic_state *state = - container_of(work, struct drm_atomic_state, commit_work); - struct drm_i915_private *i915 = to_i915(state->dev); + struct intel_atomic_state *state = + container_of(work, struct intel_atomic_state, base.commit_work); + struct drm_i915_private *i915 = to_i915(state->base.dev); - drm_atomic_helper_cleanup_planes(&i915->drm, state); - drm_atomic_helper_commit_cleanup_done(state); - drm_atomic_state_put(state); + intel_cleanup_dsbs(state); + drm_atomic_helper_cleanup_planes(&i915->drm, &state->base); + drm_atomic_helper_commit_cleanup_done(&state->base); + drm_atomic_state_put(&state->base); intel_atomic_helper_free_state(i915); } @@ -15467,9 +15550,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) if (state->modeset) intel_encoders_update_prepare(state); - /* Enable all new slices, we might need */ - if (state->modeset) - icl_dbuf_slice_pre_update(state); + intel_dbuf_pre_plane_update(state); /* Now enable the clocks, plane, pipe, and connectors that we set up. */ dev_priv->display.commit_modeset_enables(state); @@ -15524,9 +15605,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) dev_priv->display.optimize_watermarks(state, crtc); } - /* Disable all slices, we don't need */ - if (state->modeset) - icl_dbuf_slice_post_update(state); + intel_dbuf_post_plane_update(state); for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { intel_post_plane_update(state, crtc); @@ -15535,6 +15614,13 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) modeset_put_power_domains(dev_priv, put_domains[i]); intel_modeset_verify_crtc(crtc, state, old_crtc_state, 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. + */ + old_crtc_state->dsb = fetch_and_zero(&new_crtc_state->dsb); } /* Underruns don't always raise interrupts, so check manually */ @@ -15684,8 +15770,15 @@ static int intel_atomic_commit(struct drm_device *dev, intel_atomic_swap_global_state(state); if (ret) { + struct intel_crtc_state *new_crtc_state; + struct intel_crtc *crtc; + int i; + i915_sw_fence_commit(&state->commit_ready); + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + intel_dsb_cleanup(new_crtc_state); + drm_atomic_helper_cleanup_planes(dev, &state->base); intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref); return ret; @@ -16240,7 +16333,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS * port is hooked to pipe B. Hence we want plane A feeding pipe B. */ - if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4) + if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 && + INTEL_NUM_PIPES(dev_priv) == 2) plane->i9xx_plane = (enum i9xx_plane_id) !pipe; else plane->i9xx_plane = (enum i9xx_plane_id) pipe; @@ -16405,6 +16499,9 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1; drm_plane_create_zpos_immutable_property(&cursor->base, zpos); + if (INTEL_GEN(dev_priv) >= 12) + drm_plane_enable_fb_damage_clips(&cursor->base); + drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs); return cursor; @@ -16745,7 +16842,12 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) return; - if (INTEL_GEN(dev_priv) >= 12) { + if (IS_ROCKETLAKE(dev_priv)) { + intel_ddi_init(dev_priv, PORT_A); + intel_ddi_init(dev_priv, PORT_B); + intel_ddi_init(dev_priv, PORT_D); /* DDI TC1 */ + intel_ddi_init(dev_priv, PORT_E); /* DDI TC2 */ + } else if (INTEL_GEN(dev_priv) >= 12) { intel_ddi_init(dev_priv, PORT_A); intel_ddi_init(dev_priv, PORT_B); intel_ddi_init(dev_priv, PORT_D); @@ -17420,23 +17522,35 @@ void intel_modeset_init_hw(struct drm_i915_private *i915) { struct intel_cdclk_state *cdclk_state = to_intel_cdclk_state(i915->cdclk.obj.state); + struct intel_dbuf_state *dbuf_state = + to_intel_dbuf_state(i915->dbuf.obj.state); intel_update_cdclk(i915); intel_dump_cdclk_config(&i915->cdclk.hw, "Current CDCLK"); cdclk_state->logical = cdclk_state->actual = i915->cdclk.hw; + + dbuf_state->enabled_slices = i915->dbuf.enabled_slices; } static int sanitize_watermarks_add_affected(struct drm_atomic_state *state) { struct drm_plane *plane; - struct drm_crtc *crtc; + struct intel_crtc *crtc; - drm_for_each_crtc(crtc, state->dev) { - struct drm_crtc_state *crtc_state; + for_each_intel_crtc(state->dev, crtc) { + struct intel_crtc_state *crtc_state; - crtc_state = drm_atomic_get_crtc_state(state, crtc); + crtc_state = intel_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); + + if (crtc_state->hw.active) { + /* + * Preserve the inherited flag to avoid + * taking the full modeset path. + */ + crtc_state->inherited = true; + } } drm_for_each_plane(plane, state->dev) { @@ -17578,6 +17692,15 @@ retry: } if (crtc_state->hw.active) { + /* + * We've not yet detected sink capabilities + * (audio,infoframes,etc.) and thus we don't want to + * force a full state recomputation yet. We want that to + * happen only for the first real commit from userspace. + * So preserve the inherited flag for the time being. + */ + crtc_state->inherited = true; + ret = drm_atomic_add_affected_planes(state, &crtc->base); if (ret) goto out; @@ -17665,7 +17788,8 @@ static void intel_mode_config_init(struct drm_i915_private *i915) if (IS_I845G(i915) || IS_I865G(i915)) { mode_config->cursor_width = IS_I845G(i915) ? 64 : 512; mode_config->cursor_height = 1023; - } else if (IS_GEN(i915, 2)) { + } else if (IS_I830(i915) || IS_I85X(i915) || + IS_I915G(i915) || IS_I915GM(i915)) { mode_config->cursor_width = 64; mode_config->cursor_height = 64; } else { @@ -17711,6 +17835,10 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) if (ret) return ret; + ret = intel_dbuf_init(i915); + if (ret) + return ret; + ret = intel_bw_init(i915); if (ret) return ret; @@ -18227,6 +18355,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_cdclk_state *cdclk_state = to_intel_cdclk_state(dev_priv->cdclk.obj.state); + struct intel_dbuf_state *dbuf_state = + to_intel_dbuf_state(dev_priv->dbuf.obj.state); enum pipe pipe; struct intel_crtc *crtc; struct intel_encoder *encoder; @@ -18257,7 +18387,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) enableddisabled(crtc_state->hw.active)); } - dev_priv->active_pipes = cdclk_state->active_pipes = active_pipes; + dev_priv->active_pipes = cdclk_state->active_pipes = + dbuf_state->active_pipes = active_pipes; readout_plane_state(dev_priv); @@ -18348,7 +18479,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * set a flag to indicate that a full recalculation is * needed on the next commit. */ - mode->private_flags = I915_MODE_FLAG_INHERITED; + crtc_state->inherited = true; intel_crtc_compute_pixel_rate(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index efb4da205ea2..e890c8fb779b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -187,6 +187,13 @@ enum plane_id { for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \ for_each_if((__crtc)->plane_ids_mask & BIT(__p)) +#define for_each_dbuf_slice_in_mask(__slice, __mask) \ + for ((__slice) = DBUF_S1; (__slice) < I915_MAX_DBUF_SLICES; (__slice)++) \ + for_each_if((BIT(__slice)) & (__mask)) + +#define for_each_dbuf_slice(__slice) \ + for_each_dbuf_slice_in_mask(__slice, BIT(I915_MAX_DBUF_SLICES) - 1) + enum port { PORT_NONE = -1, @@ -535,7 +542,7 @@ void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state); int ilk_get_lanes_required(int target_clock, int link_bw, int bpp); void vlv_wait_port_ready(struct drm_i915_private *dev_priv, - struct intel_digital_port *dport, + struct intel_digital_port *dig_port, unsigned int expected_mask); int intel_get_load_detect_pipe(struct drm_connector *connector, struct intel_load_detect_pipe *old, @@ -608,6 +615,7 @@ unsigned int i9xx_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); int bdw_get_pipemisc_bpp(struct intel_crtc *crtc); +unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state); struct intel_display_error_state * intel_display_capture_error_state(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 2b640d8ab9d2..3644752cc5ec 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -125,7 +125,7 @@ static int i915_ips_status(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); seq_printf(m, "Enabled by kernel parameter: %s\n", - yesno(i915_modparams.enable_ips)); + yesno(dev_priv->params.enable_ips)); if (INTEL_GEN(dev_priv) >= 8) { seq_puts(m, "Currently: unknown\n"); @@ -1194,7 +1194,7 @@ 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 *intel_dig_port; + struct intel_digital_port *dig_port; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; @@ -1207,14 +1207,14 @@ static int i915_dp_mst_info(struct seq_file *m, void *unused) if (!intel_encoder || intel_encoder->type == INTEL_OUTPUT_DP_MST) continue; - intel_dig_port = enc_to_dig_port(intel_encoder); - if (!intel_dig_port->dp.can_mst) + dig_port = enc_to_dig_port(intel_encoder); + if (!dig_port->dp.can_mst) continue; seq_printf(m, "MST Source Port [ENCODER:%d:%s]\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); - drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr); + dig_port->base.base.base.id, + dig_port->base.base.name); + drm_dp_mst_dump_topology(m, &dig_port->dp.mst_mgr); } drm_connector_list_iter_end(&conn_iter); @@ -2218,7 +2218,8 @@ int intel_connector_debugfs_add(struct drm_connector *connector) } if (INTEL_GEN(dev_priv) >= 10 && - (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort && + !to_intel_connector(connector)->mst_port) || connector->connector_type == DRM_MODE_CONNECTOR_eDP)) debugfs_create_file("i915_dsc_fec_support", S_IRUGO, root, connector, &i915_dsc_fec_support_fops); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 49998906cc61..0c713e83274d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1161,7 +1161,7 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv, static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv) { u8 hw_enabled_dbuf_slices = intel_enabled_dbuf_slices_mask(dev_priv); - u8 enabled_dbuf_slices = dev_priv->enabled_dbuf_slices_mask; + u8 enabled_dbuf_slices = dev_priv->dbuf.enabled_slices; drm_WARN(&dev_priv->drm, hw_enabled_dbuf_slices != enabled_dbuf_slices, @@ -1817,8 +1817,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct i915_power_domains *power_domains = &dev_priv->power_domains; - enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(encoder)); - enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(encoder)); + enum dpio_phy phy = vlv_dig_port_to_phy(enc_to_dig_port(encoder)); + enum dpio_channel ch = vlv_dig_port_to_channel(enc_to_dig_port(encoder)); mutex_lock(&power_domains->lock); @@ -1943,22 +1943,29 @@ static u64 __async_put_domains_mask(struct i915_power_domains *power_domains) static bool assert_async_put_domain_masks_disjoint(struct i915_power_domains *power_domains) { - return !WARN_ON(power_domains->async_put_domains[0] & - power_domains->async_put_domains[1]); + struct drm_i915_private *i915 = container_of(power_domains, + struct drm_i915_private, + power_domains); + return !drm_WARN_ON(&i915->drm, power_domains->async_put_domains[0] & + power_domains->async_put_domains[1]); } static bool __async_put_domains_state_ok(struct i915_power_domains *power_domains) { + struct drm_i915_private *i915 = container_of(power_domains, + struct drm_i915_private, + power_domains); enum intel_display_power_domain domain; bool err = false; err |= !assert_async_put_domain_masks_disjoint(power_domains); - err |= WARN_ON(!!power_domains->async_put_wakeref != - !!__async_put_domains_mask(power_domains)); + err |= drm_WARN_ON(&i915->drm, !!power_domains->async_put_wakeref != + !!__async_put_domains_mask(power_domains)); for_each_power_domain(domain, __async_put_domains_mask(power_domains)) - err |= WARN_ON(power_domains->domain_use_count[domain] != 1); + err |= drm_WARN_ON(&i915->drm, + power_domains->domain_use_count[domain] != 1); return !err; } @@ -2200,11 +2207,14 @@ static void queue_async_put_domains_work(struct i915_power_domains *power_domains, intel_wakeref_t wakeref) { - WARN_ON(power_domains->async_put_wakeref); + struct drm_i915_private *i915 = container_of(power_domains, + struct drm_i915_private, + power_domains); + drm_WARN_ON(&i915->drm, power_domains->async_put_wakeref); power_domains->async_put_wakeref = wakeref; - WARN_ON(!queue_delayed_work(system_unbound_wq, - &power_domains->async_put_work, - msecs_to_jiffies(100))); + drm_WARN_ON(&i915->drm, !queue_delayed_work(system_unbound_wq, + &power_domains->async_put_work, + msecs_to_jiffies(100))); } static void @@ -2913,6 +2923,53 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, BIT_ULL(POWER_DOMAIN_AUX_I_TBT) | \ BIT_ULL(POWER_DOMAIN_TC_COLD_OFF)) +#define RKL_PW_4_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +#define RKL_PW_3_POWER_DOMAINS ( \ + RKL_PW_4_POWER_DOMAINS | \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_D) | \ + BIT_ULL(POWER_DOMAIN_AUX_E) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +/* + * There is no PW_2/PG_2 on RKL. + * + * RKL PW_1/PG_1 domains (under HW/DMC control): + * - DBUF function (note: registers are in PW0) + * - PIPE_A and its planes and VDSC/joining, except VGA + * - transcoder A + * - DDI_A and DDI_B + * - FBC + * + * RKL PW_0/PG_0 domains (under HW/DMC control): + * - PCI + * - clocks except port PLL + * - shared functions: + * * interrupts except pipe interrupts + * * MBus except PIPE_MBUS_DBOX_CTL + * * DBUF registers + * - central power except FBC + * - top-level GTC (DDI-level GTC is in the well associated with the DDI) + */ + +#define RKL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + RKL_PW_3_POWER_DOMAINS | \ + BIT_ULL(POWER_DOMAIN_MODESET) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { .sync_hw = i9xx_power_well_sync_hw_noop, .enable = i9xx_always_on_power_well_noop, @@ -4283,6 +4340,140 @@ static const struct i915_power_well_desc tgl_power_wells[] = { }, }; +static const struct i915_power_well_desc rkl_power_wells[] = { + { + .name = "always-on", + .always_on = true, + .domains = POWER_DOMAIN_MASK, + .ops = &i9xx_always_on_power_well_ops, + .id = DISP_PW_ID_NONE, + }, + { + .name = "power well 1", + /* Handled by the DMC firmware */ + .always_on = true, + .domains = 0, + .ops = &hsw_power_well_ops, + .id = SKL_DISP_PW_1, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_1, + .hsw.has_fuses = true, + }, + }, + { + .name = "DC off", + .domains = RKL_DISPLAY_DC_OFF_POWER_DOMAINS, + .ops = &gen9_dc_off_power_well_ops, + .id = SKL_DISP_DC_OFF, + }, + { + .name = "power well 3", + .domains = RKL_PW_3_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = ICL_DISP_PW_3, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_3, + .hsw.irq_pipe_mask = BIT(PIPE_B), + .hsw.has_vga = true, + .hsw.has_fuses = true, + }, + }, + { + .name = "power well 4", + .domains = RKL_PW_4_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_4, + .hsw.has_fuses = true, + .hsw.irq_pipe_mask = BIT(PIPE_C), + } + }, + { + .name = "DDI A IO", + .domains = ICL_DDI_IO_A_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_A, + } + }, + { + .name = "DDI B IO", + .domains = ICL_DDI_IO_B_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_B, + } + }, + { + .name = "DDI D TC1 IO", + .domains = TGL_DDI_IO_D_TC1_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, + }, + }, + { + .name = "DDI E TC2 IO", + .domains = TGL_DDI_IO_E_TC2_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, + }, + }, + { + .name = "AUX A", + .domains = ICL_AUX_A_IO_POWER_DOMAINS, + .ops = &icl_aux_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_A, + }, + }, + { + .name = "AUX B", + .domains = ICL_AUX_B_IO_POWER_DOMAINS, + .ops = &icl_aux_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_B, + }, + }, + { + .name = "AUX D TC1", + .domains = TGL_AUX_D_TC1_IO_POWER_DOMAINS, + .ops = &icl_aux_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, + }, + }, + { + .name = "AUX E TC2", + .domains = TGL_AUX_E_TC2_IO_POWER_DOMAINS, + .ops = &icl_aux_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, + }, + }, +}; + static int sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv, int disable_power_well) @@ -4322,7 +4513,7 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, mask = 0; } - if (!i915_modparams.disable_power_well) + if (!dev_priv->params.disable_power_well) max_dc = 0; if (enable_dc >= 0 && enable_dc <= max_dc) { @@ -4365,6 +4556,9 @@ __set_power_wells(struct i915_power_domains *power_domains, const struct i915_power_well_desc *power_well_descs, int power_well_count) { + struct drm_i915_private *i915 = container_of(power_domains, + struct drm_i915_private, + power_domains); u64 power_well_ids = 0; int i; @@ -4384,8 +4578,8 @@ __set_power_wells(struct i915_power_domains *power_domains, if (id == DISP_PW_ID_NONE) continue; - WARN_ON(id >= sizeof(power_well_ids) * 8); - WARN_ON(power_well_ids & BIT_ULL(id)); + drm_WARN_ON(&i915->drm, id >= sizeof(power_well_ids) * 8); + drm_WARN_ON(&i915->drm, power_well_ids & BIT_ULL(id)); power_well_ids |= BIT_ULL(id); } @@ -4408,11 +4602,11 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) struct i915_power_domains *power_domains = &dev_priv->power_domains; int err; - i915_modparams.disable_power_well = + dev_priv->params.disable_power_well = sanitize_disable_power_well_option(dev_priv, - i915_modparams.disable_power_well); + dev_priv->params.disable_power_well); dev_priv->csr.allowed_dc_mask = - get_allowed_dc_mask(dev_priv, i915_modparams.enable_dc); + get_allowed_dc_mask(dev_priv, dev_priv->params.enable_dc); dev_priv->csr.target_dc_state = sanitize_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); @@ -4428,7 +4622,9 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) * The enabling order will be from lower to higher indexed wells, * the disabling order is reversed. */ - if (IS_GEN(dev_priv, 12)) { + if (IS_ROCKETLAKE(dev_priv)) { + err = set_power_wells(power_domains, rkl_power_wells); + } else if (IS_GEN(dev_priv, 12)) { err = set_power_wells(power_domains, tgl_power_wells); } else if (IS_GEN(dev_priv, 11)) { err = set_power_wells(power_domains, icl_power_wells); @@ -4491,45 +4687,38 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv) mutex_unlock(&power_domains->lock); } -static bool intel_dbuf_slice_set(struct drm_i915_private *dev_priv, - i915_reg_t reg, bool enable) +static void gen9_dbuf_slice_set(struct drm_i915_private *dev_priv, + enum dbuf_slice slice, bool enable) { - u32 val, status; + i915_reg_t reg = DBUF_CTL_S(slice); + bool state; + u32 val; val = intel_de_read(dev_priv, reg); - val = enable ? (val | DBUF_POWER_REQUEST) : (val & ~DBUF_POWER_REQUEST); + if (enable) + val |= DBUF_POWER_REQUEST; + else + val &= ~DBUF_POWER_REQUEST; intel_de_write(dev_priv, reg, val); intel_de_posting_read(dev_priv, reg); udelay(10); - status = intel_de_read(dev_priv, reg) & DBUF_POWER_STATE; - if ((enable && !status) || (!enable && status)) { - drm_err(&dev_priv->drm, "DBus power %s timeout!\n", - enable ? "enable" : "disable"); - return false; - } - return true; + state = intel_de_read(dev_priv, reg) & DBUF_POWER_STATE; + drm_WARN(&dev_priv->drm, enable != state, + "DBuf slice %d power %s timeout!\n", + slice, enable ? "enable" : "disable"); } -static void gen9_dbuf_enable(struct drm_i915_private *dev_priv) +void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv, + u8 req_slices) { - icl_dbuf_slices_update(dev_priv, BIT(DBUF_S1)); -} - -static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) -{ - icl_dbuf_slices_update(dev_priv, 0); -} - -void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, - u8 req_slices) -{ - int i; - int max_slices = INTEL_INFO(dev_priv)->num_supported_dbuf_slices; + int num_slices = INTEL_INFO(dev_priv)->num_supported_dbuf_slices; struct i915_power_domains *power_domains = &dev_priv->power_domains; + enum dbuf_slice slice; - drm_WARN(&dev_priv->drm, hweight8(req_slices) > max_slices, - "Invalid number of dbuf slices requested\n"); + drm_WARN(&dev_priv->drm, req_slices & ~(BIT(num_slices) - 1), + "Invalid set of dbuf slices (0x%x) requested (num dbuf slices %d)\n", + req_slices, num_slices); drm_dbg_kms(&dev_priv->drm, "Updating dbuf slices to 0x%x\n", req_slices); @@ -4543,36 +4732,36 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, */ mutex_lock(&power_domains->lock); - for (i = 0; i < max_slices; i++) { - intel_dbuf_slice_set(dev_priv, - DBUF_CTL_S(i), - (req_slices & BIT(i)) != 0); - } + for (slice = DBUF_S1; slice < num_slices; slice++) + gen9_dbuf_slice_set(dev_priv, slice, req_slices & BIT(slice)); - dev_priv->enabled_dbuf_slices_mask = req_slices; + dev_priv->dbuf.enabled_slices = req_slices; mutex_unlock(&power_domains->lock); } -static void icl_dbuf_enable(struct drm_i915_private *dev_priv) +static void gen9_dbuf_enable(struct drm_i915_private *dev_priv) { - skl_ddb_get_hw_state(dev_priv); + dev_priv->dbuf.enabled_slices = + intel_enabled_dbuf_slices_mask(dev_priv); + /* * Just power up at least 1 slice, we will * figure out later which slices we have and what we need. */ - icl_dbuf_slices_update(dev_priv, dev_priv->enabled_dbuf_slices_mask | - BIT(DBUF_S1)); + gen9_dbuf_slices_update(dev_priv, BIT(DBUF_S1) | + dev_priv->dbuf.enabled_slices); } -static void icl_dbuf_disable(struct drm_i915_private *dev_priv) +static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) { - icl_dbuf_slices_update(dev_priv, 0); + gen9_dbuf_slices_update(dev_priv, 0); } static void icl_mbus_init(struct drm_i915_private *dev_priv) { - u32 mask, val; + unsigned long abox_regs = INTEL_INFO(dev_priv)->abox_mask; + u32 mask, val, i; mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK | MBUS_ABOX_BT_CREDIT_POOL2_MASK | @@ -4583,11 +4772,16 @@ static void icl_mbus_init(struct drm_i915_private *dev_priv) MBUS_ABOX_B_CREDIT(1) | MBUS_ABOX_BW_CREDIT(1); - intel_de_rmw(dev_priv, MBUS_ABOX_CTL, mask, val); - if (INTEL_GEN(dev_priv) >= 12) { - intel_de_rmw(dev_priv, MBUS_ABOX1_CTL, mask, val); - intel_de_rmw(dev_priv, MBUS_ABOX2_CTL, mask, val); - } + /* + * gen12 platforms that use abox1 and abox2 for pixel data reads still + * expect us to program the abox_ctl0 register as well, even though + * we don't have to program other instance-0 registers like BW_BUDDY. + */ + if (IS_GEN(dev_priv, 12)) + abox_regs |= BIT(0); + + for_each_set_bit(i, &abox_regs, sizeof(abox_regs)) + intel_de_rmw(dev_priv, MBUS_ABOX_CTL(i), mask, val); } static void hsw_assert_cdclk(struct drm_i915_private *dev_priv) @@ -5066,7 +5260,8 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv) enum intel_dram_type type = dev_priv->dram_info.type; u8 num_channels = dev_priv->dram_info.num_channels; const struct buddy_page_mask *table; - int i; + unsigned long abox_mask = INTEL_INFO(dev_priv)->abox_mask; + int config, i; if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B0)) /* Wa_1409767108: tgl */ @@ -5074,29 +5269,27 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv) else table = tgl_buddy_page_masks; - for (i = 0; table[i].page_mask != 0; i++) - if (table[i].num_channels == num_channels && - table[i].type == type) + for (config = 0; table[config].page_mask != 0; config++) + if (table[config].num_channels == num_channels && + table[config].type == type) break; - if (table[i].page_mask == 0) { + if (table[config].page_mask == 0) { drm_dbg(&dev_priv->drm, "Unknown memory configuration; disabling address buddy logic.\n"); - intel_de_write(dev_priv, BW_BUDDY1_CTL, BW_BUDDY_DISABLE); - intel_de_write(dev_priv, BW_BUDDY2_CTL, BW_BUDDY_DISABLE); + for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) + intel_de_write(dev_priv, BW_BUDDY_CTL(i), + BW_BUDDY_DISABLE); } else { - intel_de_write(dev_priv, BW_BUDDY1_PAGE_MASK, - table[i].page_mask); - intel_de_write(dev_priv, BW_BUDDY2_PAGE_MASK, - table[i].page_mask); - - /* Wa_22010178259:tgl */ - intel_de_rmw(dev_priv, BW_BUDDY1_CTL, - BW_BUDDY_TLB_REQ_TIMER_MASK, - REG_FIELD_PREP(BW_BUDDY_TLB_REQ_TIMER_MASK, 0x8)); - intel_de_rmw(dev_priv, BW_BUDDY2_CTL, - BW_BUDDY_TLB_REQ_TIMER_MASK, - REG_FIELD_PREP(BW_BUDDY_TLB_REQ_TIMER_MASK, 0x8)); + for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) { + intel_de_write(dev_priv, BW_BUDDY_PAGE_MASK(i), + table[config].page_mask); + + /* Wa_22010178259:tgl,rkl */ + intel_de_rmw(dev_priv, BW_BUDDY_CTL(i), + BW_BUDDY_TLB_REQ_TIMER_MASK, + BW_BUDDY_TLB_REQ_TIMER(0x8)); + } } } @@ -5105,6 +5298,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, { struct i915_power_domains *power_domains = &dev_priv->power_domains; struct i915_power_well *well; + u32 val; gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); @@ -5127,7 +5321,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, intel_cdclk_init_hw(dev_priv); /* 5. Enable DBUF. */ - icl_dbuf_enable(dev_priv); + gen9_dbuf_enable(dev_priv); /* 6. Setup MBUS. */ icl_mbus_init(dev_priv); @@ -5138,6 +5332,13 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, if (resume && dev_priv->csr.dmc_payload) intel_csr_load_program(dev_priv); + + /* Wa_14011508470 */ + if (IS_GEN(dev_priv, 12)) { + val = DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM | + DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR; + intel_uncore_rmw(&dev_priv->uncore, GEN11_CHICKEN_DCPR_2, 0, val); + } } static void icl_display_core_uninit(struct drm_i915_private *dev_priv) @@ -5150,7 +5351,7 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv) /* 1. Disable all display engine functions -> aready done */ /* 2. Disable DBUF */ - icl_dbuf_disable(dev_priv); + gen9_dbuf_disable(dev_priv); /* 3. Disable CD clock */ intel_cdclk_uninit_hw(dev_priv); @@ -5375,7 +5576,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume) intel_display_power_get(i915, POWER_DOMAIN_INIT); /* Disable power support if the user asked so. */ - if (!i915_modparams.disable_power_well) + if (!i915->params.disable_power_well) intel_display_power_get(i915, POWER_DOMAIN_INIT); intel_power_domains_sync_hw(i915); @@ -5399,7 +5600,7 @@ void intel_power_domains_driver_remove(struct drm_i915_private *i915) fetch_and_zero(&i915->power_domains.wakeref); /* Remove the refcount we took to keep power well support disabled. */ - if (!i915_modparams.disable_power_well) + if (!i915->params.disable_power_well) intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT); intel_display_power_flush_work_sync(i915); @@ -5488,7 +5689,7 @@ void intel_power_domains_suspend(struct drm_i915_private *i915, * Even if power well support was disabled we still want to disable * power wells if power domains must be deinitialized for suspend. */ - if (!i915_modparams.disable_power_well) + if (!i915->params.disable_power_well) intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT); intel_display_power_flush_work(i915); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 6c917699293b..54c20c76057e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -314,15 +314,16 @@ intel_display_power_put_async(struct drm_i915_private *i915, enum dbuf_slice { DBUF_S1, DBUF_S2, + I915_MAX_DBUF_SLICES }; +void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv, + u8 req_slices); + #define with_intel_display_power(i915, domain, wf) \ for ((wf) = intel_display_power_get((i915), (domain)); (wf); \ intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0) -void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, - u8 req_slices); - void chv_phy_powergate_lanes(struct intel_encoder *encoder, bool override, unsigned int mask); bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 2bf3d4cb4ea9..e8f809161c75 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -279,10 +279,10 @@ enum check_link_response { */ struct intel_hdcp_shim { /* Outputs the transmitter's An and Aksv values to the receiver. */ - int (*write_an_aksv)(struct intel_digital_port *intel_dig_port, u8 *an); + int (*write_an_aksv)(struct intel_digital_port *dig_port, u8 *an); /* Reads the receiver's key selection vector */ - int (*read_bksv)(struct intel_digital_port *intel_dig_port, u8 *bksv); + int (*read_bksv)(struct intel_digital_port *dig_port, u8 *bksv); /* * Reads BINFO from DP receivers and BSTATUS from HDMI receivers. The @@ -290,52 +290,52 @@ struct intel_hdcp_shim { * different. Call it BSTATUS since that's the name the HDMI spec * uses and it was there first. */ - int (*read_bstatus)(struct intel_digital_port *intel_dig_port, + int (*read_bstatus)(struct intel_digital_port *dig_port, u8 *bstatus); /* Determines whether a repeater is present downstream */ - int (*repeater_present)(struct intel_digital_port *intel_dig_port, + int (*repeater_present)(struct intel_digital_port *dig_port, bool *repeater_present); /* Reads the receiver's Ri' value */ - int (*read_ri_prime)(struct intel_digital_port *intel_dig_port, u8 *ri); + int (*read_ri_prime)(struct intel_digital_port *dig_port, u8 *ri); /* Determines if the receiver's KSV FIFO is ready for consumption */ - int (*read_ksv_ready)(struct intel_digital_port *intel_dig_port, + int (*read_ksv_ready)(struct intel_digital_port *dig_port, bool *ksv_ready); /* Reads the ksv fifo for num_downstream devices */ - int (*read_ksv_fifo)(struct intel_digital_port *intel_dig_port, + int (*read_ksv_fifo)(struct intel_digital_port *dig_port, int num_downstream, u8 *ksv_fifo); /* Reads a 32-bit part of V' from the receiver */ - int (*read_v_prime_part)(struct intel_digital_port *intel_dig_port, + int (*read_v_prime_part)(struct intel_digital_port *dig_port, int i, u32 *part); /* Enables HDCP signalling on the port */ - int (*toggle_signalling)(struct intel_digital_port *intel_dig_port, + int (*toggle_signalling)(struct intel_digital_port *dig_port, bool enable); /* Ensures the link is still protected */ - bool (*check_link)(struct intel_digital_port *intel_dig_port); + bool (*check_link)(struct intel_digital_port *dig_port); /* Detects panel's hdcp capability. This is optional for HDMI. */ - int (*hdcp_capable)(struct intel_digital_port *intel_dig_port, + int (*hdcp_capable)(struct intel_digital_port *dig_port, bool *hdcp_capable); /* HDCP adaptation(DP/HDMI) required on the port */ enum hdcp_wired_protocol protocol; /* Detects whether sink is HDCP2.2 capable */ - int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port, + int (*hdcp_2_2_capable)(struct intel_digital_port *dig_port, bool *capable); /* Write HDCP2.2 messages */ - int (*write_2_2_msg)(struct intel_digital_port *intel_dig_port, + int (*write_2_2_msg)(struct intel_digital_port *dig_port, void *buf, size_t size); /* Read HDCP2.2 messages */ - int (*read_2_2_msg)(struct intel_digital_port *intel_dig_port, + int (*read_2_2_msg)(struct intel_digital_port *dig_port, u8 msg_id, void *buf, size_t size); /* @@ -343,11 +343,11 @@ struct intel_hdcp_shim { * type to Receivers. In DP HDCP2.2 Stream type is one of the input to * the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI. */ - int (*config_stream_type)(struct intel_digital_port *intel_dig_port, + int (*config_stream_type)(struct intel_digital_port *dig_port, bool is_repeater, u8 type); /* HDCP2.2 Link Integrity Check */ - int (*check_2_2_link)(struct intel_digital_port *intel_dig_port); + int (*check_2_2_link)(struct intel_digital_port *dig_port); }; struct intel_hdcp { @@ -479,16 +479,6 @@ struct intel_atomic_state { bool dpll_set, modeset; - /* - * Does this transaction change the pipes that are active? This mask - * tracks which CRTC's have changed their active state at the end of - * the transaction (not counting the temporary disable during modesets). - * This mask should only be non-zero when intel_state->modeset is true, - * but the converse is not necessarily true; simply changing a mode may - * not flip the final active status of any CRTC's - */ - u8 active_pipe_changes; - u8 active_pipes; struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS]; @@ -506,9 +496,6 @@ struct intel_atomic_state { */ bool global_state_changed; - /* Number of enabled DBuf slices */ - u8 enabled_dbuf_slices_mask; - struct i915_sw_fence commit_ready; struct llist_node freed; @@ -643,8 +630,7 @@ struct intel_crtc_scaler_state { int scaler_id; }; -/* drm_mode->private_flags */ -#define I915_MODE_FLAG_INHERITED (1<<0) +/* {crtc,crtc_state}->mode_flags */ /* Flag to get scanline using frame time stamps */ #define I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP (1<<1) /* Flag to use the scanline counter instead of the pixel counter */ @@ -841,6 +827,7 @@ struct intel_crtc_state { bool update_wm_pre, update_wm_post; /* watermarks are updated */ bool fifo_changed; /* FIFO split is changed */ bool preload_luts; + bool inherited; /* state inherited from BIOS? */ /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, @@ -956,6 +943,9 @@ struct intel_crtc_state { /* Used by SDVO (and if we ever fix it, HDMI). */ unsigned pixel_multiplier; + /* I915_MODE_FLAG_* */ + u8 mode_flags; + u8 lane_count; /* @@ -1080,6 +1070,9 @@ struct intel_crtc_state { /* Only valid on TGL+ */ enum transcoder mst_master_transcoder; + + /* For DSB related info */ + struct intel_dsb *dsb; }; enum intel_pipe_crc_source { @@ -1118,6 +1111,10 @@ struct intel_crtc { */ bool active; u8 plane_ids_mask; + + /* I915_MODE_FLAG_* */ + u8 mode_flags; + unsigned long long enabled_power_domains; struct intel_overlay *overlay; @@ -1149,9 +1146,6 @@ struct intel_crtc { /* scalers available on this crtc */ int num_scalers; - /* per pipe DSB related info */ - struct intel_dsb dsb; - #ifdef CONFIG_DEBUG_FS struct intel_pipe_crc pipe_crc; #endif @@ -1373,6 +1367,9 @@ struct intel_dp { void (*set_idle_link_train)(struct intel_dp *intel_dp); void (*set_signal_levels)(struct intel_dp *intel_dp); + u8 (*preemph_max)(struct intel_dp *intel_dp); + u8 (*voltage_max)(struct intel_dp *intel_dp); + /* Displayport compliance testing */ struct intel_dp_compliance compliance; @@ -1437,9 +1434,9 @@ struct intel_dp_mst_encoder { }; static inline enum dpio_channel -vlv_dport_to_channel(struct intel_digital_port *dport) +vlv_dig_port_to_channel(struct intel_digital_port *dig_port) { - switch (dport->base.port) { + switch (dig_port->base.port) { case PORT_B: case PORT_D: return DPIO_CH0; @@ -1451,9 +1448,9 @@ vlv_dport_to_channel(struct intel_digital_port *dport) } static inline enum dpio_phy -vlv_dport_to_phy(struct intel_digital_port *dport) +vlv_dig_port_to_phy(struct intel_digital_port *dig_port) { - switch (dport->base.port) { + switch (dig_port->base.port) { case PORT_B: case PORT_C: return DPIO_PHY0; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f2c6d835a12f..79c27f91f42c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -140,9 +140,9 @@ static const u8 valid_dsc_slicecount[] = {1, 2, 4}; */ bool intel_dp_is_edp(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - return intel_dig_port->base.type == INTEL_OUTPUT_EDP; + return dig_port->base.type == INTEL_OUTPUT_EDP; } static void intel_dp_link_down(struct intel_encoder *encoder, @@ -216,10 +216,10 @@ static int intel_dp_max_common_rate(struct intel_dp *intel_dp) /* Theoretical max between source and sink */ static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - int source_max = intel_dig_port->max_lanes; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + int source_max = dig_port->max_lanes; int sink_max = drm_dp_max_lane_count(intel_dp->dpcd); - int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port); + int fia_max = intel_tc_port_fia_max_lane_count(dig_port); return min3(source_max, sink_max, fia_max); } @@ -251,8 +251,8 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) static int intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *encoder = &intel_dig_port->base; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &dig_port->base; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int max_dotclk = dev_priv->max_dotclk_freq; int ds_max_dotclk; @@ -409,7 +409,10 @@ static int intel_dp_rate_index(const int *rates, int len, int rate) static void intel_dp_set_common_rates(struct intel_dp *intel_dp) { - WARN_ON(!intel_dp->num_source_rates || !intel_dp->num_sink_rates); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + drm_WARN_ON(&i915->drm, + !intel_dp->num_source_rates || !intel_dp->num_sink_rates); intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates, intel_dp->num_source_rates, @@ -418,7 +421,7 @@ static void intel_dp_set_common_rates(struct intel_dp *intel_dp) intel_dp->common_rates); /* Paranoia, there should always be something in common. */ - if (WARN_ON(intel_dp->num_common_rates == 0)) { + if (drm_WARN_ON(&i915->drm, intel_dp->num_common_rates == 0)) { intel_dp->common_rates[0] = 162000; intel_dp->num_common_rates = 1; } @@ -465,6 +468,15 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, struct drm_i915_private *i915 = dp_to_i915(intel_dp); int index; + /* + * TODO: Enable fallback on MST links once MST link compute can handle + * the fallback params. + */ + if (intel_dp->is_mst) { + drm_err(&i915->drm, "Link Training Unsuccessful\n"); + return -1; + } + index = intel_dp_rate_index(intel_dp->common_rates, intel_dp->num_common_rates, link_rate); @@ -766,7 +778,7 @@ static void vlv_power_sequencer_kick(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); enum pipe pipe = intel_dp->pps_pipe; bool pll_enabled, release_cl_override = false; enum dpio_phy phy = DPIO_PHY(pipe); @@ -776,14 +788,14 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) if (drm_WARN(&dev_priv->drm, intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN, "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n", - pipe_name(pipe), intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name)) + pipe_name(pipe), dig_port->base.base.base.id, + dig_port->base.base.name)) return; drm_dbg_kms(&dev_priv->drm, "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(pipe), intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + pipe_name(pipe), dig_port->base.base.base.id, + dig_port->base.base.name); /* Preserve the BIOS-computed detected bit. This is * supposed to be read-only. @@ -879,7 +891,7 @@ static enum pipe vlv_power_sequencer_pipe(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); enum pipe pipe; lockdep_assert_held(&dev_priv->pps_mutex); @@ -908,8 +920,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) drm_dbg_kms(&dev_priv->drm, "picked pipe %c power sequencer for [ENCODER:%d:%s]\n", pipe_name(intel_dp->pps_pipe), - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + dig_port->base.base.base.id, + dig_port->base.base.name); /* init power sequencer on this pipe and port */ intel_dp_init_panel_power_sequencer(intel_dp); @@ -997,8 +1009,8 @@ static void vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - enum port port = intel_dig_port->base.port; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + enum port port = dig_port->base.port; lockdep_assert_held(&dev_priv->pps_mutex); @@ -1019,15 +1031,15 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) if (intel_dp->pps_pipe == INVALID_PIPE) { drm_dbg_kms(&dev_priv->drm, "no initial power sequencer for [ENCODER:%d:%s]\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + dig_port->base.base.base.id, + dig_port->base.base.name); return; } drm_dbg_kms(&dev_priv->drm, "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name, + dig_port->base.base.base.id, + dig_port->base.base.name, pipe_name(intel_dp->pps_pipe)); intel_dp_init_panel_power_sequencer(intel_dp); @@ -1292,9 +1304,9 @@ static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp, int send_bytes, u32 aux_clock_divider) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = - to_i915(intel_dig_port->base.base.dev); + to_i915(dig_port->base.base.dev); u32 precharge, timeout; if (IS_GEN(dev_priv, 6)) @@ -1322,10 +1334,10 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp, int send_bytes, u32 unused) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *i915 = - to_i915(intel_dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, intel_dig_port->base.port); + to_i915(dig_port->base.base.dev); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); u32 ret; ret = DP_AUX_CH_CTL_SEND_BUSY | @@ -1339,7 +1351,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp, DP_AUX_CH_CTL_SYNC_PULSE_SKL(32); if (intel_phy_is_tc(i915, phy) && - intel_dig_port->tc_mode == TC_PORT_TBT_ALT) + dig_port->tc_mode == TC_PORT_TBT_ALT) ret |= DP_AUX_CH_CTL_TBT_IO; return ret; @@ -1351,11 +1363,11 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, u8 *recv, int recv_size, u32 aux_send_ctl_flags) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *i915 = - to_i915(intel_dig_port->base.base.dev); + to_i915(dig_port->base.base.dev); struct intel_uncore *uncore = &i915->uncore; - enum phy phy = intel_port_to_phy(i915, intel_dig_port->base.port); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); bool is_tc_port = intel_phy_is_tc(i915, phy); i915_reg_t ch_ctl, ch_data[5]; u32 aux_clock_divider; @@ -1372,9 +1384,9 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i); if (is_tc_port) - intel_tc_port_lock(intel_dig_port); + intel_tc_port_lock(dig_port); - aux_domain = intel_aux_power_domain(intel_dig_port); + aux_domain = intel_aux_power_domain(dig_port); aux_wakeref = intel_display_power_get(i915, aux_domain); pps_wakeref = pps_lock(intel_dp); @@ -1533,7 +1545,7 @@ out: intel_display_power_put_async(i915, aux_domain, aux_wakeref); if (is_tc_port) - intel_tc_port_unlock(intel_dig_port); + intel_tc_port_unlock(dig_port); return ret; } @@ -1555,6 +1567,7 @@ static ssize_t intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); u8 txbuf[20], rxbuf[20]; size_t txsize, rxsize; int ret; @@ -1568,10 +1581,10 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE; rxsize = 2; /* 0 or 1 data bytes */ - if (WARN_ON(txsize > 20)) + if (drm_WARN_ON(&i915->drm, txsize > 20)) return -E2BIG; - WARN_ON(!msg->buffer != !msg->size); + drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size); if (msg->buffer) memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); @@ -1596,7 +1609,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE; rxsize = msg->size + 1; - if (WARN_ON(rxsize > 20)) + if (drm_WARN_ON(&i915->drm, rxsize > 20)) return -E2BIG; ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, @@ -1871,10 +1884,11 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) int intel_dp_max_link_rate(struct intel_dp *intel_dp) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); int len; len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->max_link_rate); - if (WARN_ON(len <= 0)) + if (drm_WARN_ON(&i915->drm, len <= 0)) return 162000; return intel_dp->common_rates[len - 1]; @@ -1882,10 +1896,11 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp) int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); int i = intel_dp_rate_index(intel_dp->sink_rates, intel_dp->num_sink_rates, rate); - if (WARN_ON(i < 0)) + if (drm_WARN_ON(&i915->drm, i < 0)) i = 0; return i; @@ -2876,7 +2891,7 @@ static u32 ilk_get_pp_control(struct intel_dp *intel_dp) static bool edp_panel_vdd_on(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); u32 pp; i915_reg_t pp_stat_reg, pp_ctrl_reg; bool need_to_disable = !intel_dp->want_panel_vdd; @@ -2893,11 +2908,11 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) return need_to_disable; intel_display_power_get(dev_priv, - intel_aux_power_domain(intel_dig_port)); + intel_aux_power_domain(dig_port)); drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + dig_port->base.base.base.id, + dig_port->base.base.name); if (!edp_have_panel_power(intel_dp)) wait_panel_power_cycle(intel_dp); @@ -2919,8 +2934,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) if (!edp_have_panel_power(intel_dp)) { drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] panel power wasn't enabled\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + dig_port->base.base.base.id, + dig_port->base.base.name); msleep(intel_dp->panel_power_up_delay); } @@ -2953,7 +2968,7 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_digital_port *intel_dig_port = + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); u32 pp; i915_reg_t pp_stat_reg, pp_ctrl_reg; @@ -2966,8 +2981,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) return; drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + dig_port->base.base.base.id, + dig_port->base.base.name); pp = ilk_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; @@ -2987,7 +3002,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) intel_dp->panel_power_off_time = ktime_get_boottime(); intel_display_power_put_unchecked(dev_priv, - intel_aux_power_domain(intel_dig_port)); + intel_aux_power_domain(dig_port)); } static void edp_panel_vdd_work(struct work_struct *__work) @@ -3818,8 +3833,8 @@ static void g4x_pre_enable_dp(struct intel_atomic_state *state, static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum pipe pipe = intel_dp->pps_pipe; i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe); @@ -3841,8 +3856,8 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) */ drm_dbg_kms(&dev_priv->drm, "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n", - pipe_name(pipe), intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + pipe_name(pipe), dig_port->base.base.base.id, + dig_port->base.base.name); intel_de_write(dev_priv, pp_on_reg, 0); intel_de_posting_read(dev_priv, pp_on_reg); @@ -3984,70 +3999,24 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATU DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE; } -/* These are source-specific values. */ -u8 -intel_dp_voltage_max(struct intel_dp *intel_dp) +static u8 intel_dp_voltage_max_2(struct intel_dp *intel_dp) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - enum port port = encoder->port; + return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; +} - if (HAS_DDI(dev_priv)) - return intel_ddi_dp_voltage_max(encoder); - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; - else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) - return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; - else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) - return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; - else - return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; +static u8 intel_dp_voltage_max_3(struct intel_dp *intel_dp) +{ + return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; } -u8 -intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing) +static u8 intel_dp_pre_empemph_max_2(struct intel_dp *intel_dp) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - enum port port = encoder->port; + return DP_TRAIN_PRE_EMPH_LEVEL_2; +} - if (HAS_DDI(dev_priv)) { - return intel_ddi_dp_pre_emphasis_max(encoder, voltage_swing); - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - return DP_TRAIN_PRE_EMPH_LEVEL_3; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - return DP_TRAIN_PRE_EMPH_LEVEL_2; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - return DP_TRAIN_PRE_EMPH_LEVEL_1; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: - default: - return DP_TRAIN_PRE_EMPH_LEVEL_0; - } - } else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) { - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - return DP_TRAIN_PRE_EMPH_LEVEL_2; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - return DP_TRAIN_PRE_EMPH_LEVEL_1; - default: - return DP_TRAIN_PRE_EMPH_LEVEL_0; - } - } else { - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - return DP_TRAIN_PRE_EMPH_LEVEL_2; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - return DP_TRAIN_PRE_EMPH_LEVEL_2; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - return DP_TRAIN_PRE_EMPH_LEVEL_1; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: - default: - return DP_TRAIN_PRE_EMPH_LEVEL_0; - } - } +static u8 intel_dp_pre_empemph_max_3(struct intel_dp *intel_dp) +{ + return DP_TRAIN_PRE_EMPH_LEVEL_3; } static void vlv_set_signal_levels(struct intel_dp *intel_dp) @@ -4330,6 +4299,7 @@ static u32 ivb_cpu_edp_signal_levels(u8 train_set) case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: return EDP_LINK_TRAIN_400MV_3_5DB_IVB; case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: return EDP_LINK_TRAIN_400MV_6DB_IVB; case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: @@ -4746,7 +4716,9 @@ intel_dp_sink_can_mst(struct intel_dp *intel_dp) static bool intel_dp_can_mst(struct intel_dp *intel_dp) { - return i915_modparams.enable_dp_mst && + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + return i915->params.enable_dp_mst && intel_dp->can_mst && intel_dp_sink_can_mst(intel_dp); } @@ -4763,13 +4735,13 @@ intel_dp_configure_mst(struct intel_dp *intel_dp) "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n", encoder->base.base.id, encoder->base.name, yesno(intel_dp->can_mst), yesno(sink_can_mst), - yesno(i915_modparams.enable_dp_mst)); + yesno(i915->params.enable_dp_mst)); if (!intel_dp->can_mst) return; intel_dp->is_mst = sink_can_mst && - i915_modparams.enable_dp_mst; + i915->params.enable_dp_mst; drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); @@ -4951,7 +4923,7 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, unsigned int type) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct dp_sdp sdp = {}; ssize_t len; @@ -4977,14 +4949,14 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder, if (drm_WARN_ON(&dev_priv->drm, len < 0)) return; - intel_dig_port->write_infoframe(encoder, crtc_state, type, &sdp, len); + dig_port->write_infoframe(encoder, crtc_state, type, &sdp, len); } void intel_write_dp_vsc_sdp(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, struct drm_dp_vsc_sdp *vsc) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct dp_sdp sdp = {}; ssize_t len; @@ -4994,7 +4966,7 @@ void intel_write_dp_vsc_sdp(struct intel_encoder *encoder, if (drm_WARN_ON(&dev_priv->drm, len < 0)) return; - intel_dig_port->write_infoframe(encoder, crtc_state, DP_SDP_VSC, + dig_port->write_infoframe(encoder, crtc_state, DP_SDP_VSC, &sdp, len); } @@ -5154,7 +5126,7 @@ static void intel_read_dp_vsc_sdp(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_dp_vsc_sdp *vsc) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); unsigned int type = DP_SDP_VSC; @@ -5169,7 +5141,7 @@ static void intel_read_dp_vsc_sdp(struct intel_encoder *encoder, intel_hdmi_infoframe_enable(type)) == 0) return; - intel_dig_port->read_infoframe(encoder, crtc_state, type, &sdp, sizeof(sdp)); + dig_port->read_infoframe(encoder, crtc_state, type, &sdp, sizeof(sdp)); ret = intel_dp_vsc_sdp_unpack(vsc, &sdp, sizeof(sdp)); @@ -5181,7 +5153,7 @@ static void intel_read_dp_hdr_metadata_infoframe_sdp(struct intel_encoder *encod struct intel_crtc_state *crtc_state, struct hdmi_drm_infoframe *drm_infoframe) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); unsigned int type = HDMI_PACKET_TYPE_GAMUT_METADATA; struct dp_sdp sdp = {}; @@ -5191,8 +5163,8 @@ static void intel_read_dp_hdr_metadata_infoframe_sdp(struct intel_encoder *encod intel_hdmi_infoframe_enable(type)) == 0) return; - intel_dig_port->read_infoframe(encoder, crtc_state, type, &sdp, - sizeof(sdp)); + dig_port->read_infoframe(encoder, crtc_state, type, &sdp, + sizeof(sdp)); ret = intel_dp_hdr_metadata_infoframe_sdp_unpack(drm_infoframe, &sdp, sizeof(sdp)); @@ -5394,10 +5366,10 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = to_i915(dp_to_dig_port(intel_dp)->base.base.dev); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_dp_phy_test_params *data = &intel_dp->compliance.test_data.phytest; - struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); + struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); enum pipe pipe = crtc->pipe; u32 pattern_val; @@ -5459,10 +5431,10 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp) static void intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); + struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); enum pipe pipe = crtc->pipe; u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value; @@ -5485,11 +5457,11 @@ intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp) static void intel_dp_autotest_phy_ddi_enable(struct intel_dp *intel_dp, uint8_t lane_cnt) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - enum port port = intel_dig_port->base.port; - struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); + enum port port = dig_port->base.port; + struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); enum pipe pipe = crtc->pipe; u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value; @@ -5595,35 +5567,46 @@ update_status: "Could not write test response to sink\n"); } -static int +/** + * intel_dp_check_mst_status - service any pending MST interrupts, check link status + * @intel_dp: Intel DP struct + * + * Read any pending MST interrupts, call MST core to handle these and ack the + * interrupts. Check if the main and AUX link state is ok. + * + * Returns: + * - %true if pending interrupts were serviced (or no interrupts were + * pending) w/o detecting an error condition. + * - %false if an error condition - like AUX failure or a loss of link - is + * detected, which needs servicing from the hotplug work. + */ +static bool intel_dp_check_mst_status(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - bool need_retrain = false; + bool link_ok = true; - if (!intel_dp->is_mst) - return -EINVAL; - - WARN_ON_ONCE(intel_dp->active_mst_links < 0); + drm_WARN_ON_ONCE(&i915->drm, intel_dp->active_mst_links < 0); for (;;) { u8 esi[DP_DPRX_ESI_LEN] = {}; - bool bret, handled; + bool handled; int retry; - bret = intel_dp_get_sink_irq_esi(intel_dp, esi); - if (!bret) { + if (!intel_dp_get_sink_irq_esi(intel_dp, esi)) { drm_dbg_kms(&i915->drm, "failed to get ESI - device may have failed\n"); - return -EINVAL; + link_ok = false; + + break; } /* check link status - esi[10] = 0x200c */ - if (intel_dp->active_mst_links > 0 && !need_retrain && + if (intel_dp->active_mst_links > 0 && link_ok && !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) { drm_dbg_kms(&i915->drm, "channel EQ not ok, retraining\n"); - need_retrain = true; + link_ok = false; } drm_dbg_kms(&i915->drm, "got esi %3ph\n", esi); @@ -5643,7 +5626,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp) } } - return need_retrain; + return link_ok; } static bool @@ -5966,7 +5949,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) u8 *dpcd = intel_dp->dpcd; u8 type; - if (WARN_ON(intel_dp_is_edp(intel_dp))) + if (drm_WARN_ON(&i915->drm, intel_dp_is_edp(intel_dp))) return connector_status_connected; if (lspcon->active) @@ -6191,7 +6174,17 @@ intel_dp_detect(struct drm_connector *connector, goto out; } - if (intel_dp->reset_link_params) { + /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */ + if (INTEL_GEN(dev_priv) >= 11) + intel_dp_get_dsc_sink_cap(intel_dp); + + intel_dp_configure_mst(intel_dp); + + /* + * TODO: Reset link params when switching to MST mode, until MST + * supports link training fallback params. + */ + if (intel_dp->reset_link_params || intel_dp->is_mst) { /* Initial max link lane count */ intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); @@ -6203,12 +6196,6 @@ intel_dp_detect(struct drm_connector *connector, intel_dp_print_rates(intel_dp); - /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */ - if (INTEL_GEN(dev_priv) >= 11) - intel_dp_get_dsc_sink_cap(intel_dp); - - intel_dp_configure_mst(intel_dp); - if (intel_dp->is_mst) { /* * If we are in MST mode then this connector @@ -6350,10 +6337,10 @@ intel_dp_connector_unregister(struct drm_connector *connector) void intel_dp_encoder_flush_work(struct drm_encoder *encoder) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(to_intel_encoder(encoder)); - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); + struct intel_dp *intel_dp = &dig_port->dp; - intel_dp_mst_encoder_cleanup(intel_dig_port); + intel_dp_mst_encoder_cleanup(dig_port); if (intel_dp_is_edp(intel_dp)) { intel_wakeref_t wakeref; @@ -6412,11 +6399,11 @@ static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) } static -int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, u8 *an) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(&intel_dig_port->base.base)); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(&dig_port->base.base)); static const struct drm_dp_aux_msg msg = { .request = DP_AUX_NATIVE_WRITE, .address = DP_AUX_HDCP_AKSV, @@ -6427,7 +6414,7 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, int ret; /* Output An first, that's easy */ - dpcd_ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux, DP_AUX_HDCP_AN, + dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN, an, DRM_HDCP_AN_LEN); if (dpcd_ret != DRM_HDCP_AN_LEN) { drm_dbg_kms(&i915->drm, @@ -6466,13 +6453,13 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, return 0; } -static int intel_dp_hdcp_read_bksv(struct intel_digital_port *intel_dig_port, +static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port, u8 *bksv) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, DRM_HDCP_KSV_LEN); if (ret != DRM_HDCP_KSV_LEN) { drm_dbg_kms(&i915->drm, @@ -6482,10 +6469,10 @@ static int intel_dp_hdcp_read_bksv(struct intel_digital_port *intel_dig_port, return 0; } -static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port, +static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port, u8 *bstatus) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; /* @@ -6493,7 +6480,7 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port, * definition by different names. In the HDMI spec, it's called BSTATUS, * but in DP it's called BINFO. */ - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BINFO, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, bstatus, DRM_HDCP_BSTATUS_LEN); if (ret != DRM_HDCP_BSTATUS_LEN) { drm_dbg_kms(&i915->drm, @@ -6504,13 +6491,13 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_read_bcaps(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_read_bcaps(struct intel_digital_port *dig_port, u8 *bcaps) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BCAPS, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BCAPS, bcaps, 1); if (ret != 1) { drm_dbg_kms(&i915->drm, @@ -6522,13 +6509,13 @@ int intel_dp_hdcp_read_bcaps(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_repeater_present(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_repeater_present(struct intel_digital_port *dig_port, bool *repeater_present) { ssize_t ret; u8 bcaps; - ret = intel_dp_hdcp_read_bcaps(intel_dig_port, &bcaps); + ret = intel_dp_hdcp_read_bcaps(dig_port, &bcaps); if (ret) return ret; @@ -6537,13 +6524,13 @@ int intel_dp_hdcp_repeater_present(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *dig_port, u8 *ri_prime) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, ri_prime, DRM_HDCP_RI_LEN); if (ret != DRM_HDCP_RI_LEN) { drm_dbg_kms(&i915->drm, "Read Ri' from DP/AUX failed (%zd)\n", @@ -6554,14 +6541,14 @@ int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, bool *ksv_ready) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; u8 bstatus; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, &bstatus, 1); if (ret != 1) { drm_dbg_kms(&i915->drm, @@ -6573,17 +6560,17 @@ int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, int num_downstream, u8 *ksv_fifo) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; int i; /* KSV list is read via 15 byte window (3 entries @ 5 bytes each) */ for (i = 0; i < num_downstream; i += 3) { size_t len = min(num_downstream - i, 3) * DRM_HDCP_KSV_LEN; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_KSV_FIFO, ksv_fifo + i * DRM_HDCP_KSV_LEN, len); @@ -6598,16 +6585,16 @@ int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, int i, u32 *part) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; if (i >= DRM_HDCP_V_PRIME_NUM_PARTS) return -EINVAL; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_V_PRIME(i), part, DRM_HDCP_V_PRIME_PART_LEN); if (ret != DRM_HDCP_V_PRIME_PART_LEN) { @@ -6619,7 +6606,7 @@ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *dig_port, bool enable) { /* Not used for single stream DisplayPort setups */ @@ -6627,13 +6614,13 @@ int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, } static -bool intel_dp_hdcp_check_link(struct intel_digital_port *intel_dig_port) +bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; u8 bstatus; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, &bstatus, 1); if (ret != 1) { drm_dbg_kms(&i915->drm, @@ -6645,13 +6632,13 @@ bool intel_dp_hdcp_check_link(struct intel_digital_port *intel_dig_port) } static -int intel_dp_hdcp_capable(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp_capable(struct intel_digital_port *dig_port, bool *hdcp_capable) { ssize_t ret; u8 bcaps; - ret = intel_dp_hdcp_read_bcaps(intel_dig_port, &bcaps); + ret = intel_dp_hdcp_read_bcaps(dig_port, &bcaps); if (ret) return ret; @@ -6709,13 +6696,13 @@ static const struct hdcp2_dp_msg_data hdcp2_dp_msg_data[] = { }; static int -intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port, +intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port, u8 *rx_status) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status, HDCP_2_2_DP_RXSTATUS_LEN); if (ret != HDCP_2_2_DP_RXSTATUS_LEN) { @@ -6728,14 +6715,14 @@ intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port, } static -int hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port, +int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port, u8 msg_id, bool *msg_ready) { u8 rx_status; int ret; *msg_ready = false; - ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status); + ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status); if (ret < 0) return ret; @@ -6761,11 +6748,11 @@ int hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port, } static ssize_t -intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port, +intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port, const struct hdcp2_dp_msg_data *hdcp2_msg_data) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_dp *dp = &intel_dig_port->dp; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_dp *dp = &dig_port->dp; struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; u8 msg_id = hdcp2_msg_data->msg_id; int ret, timeout; @@ -6789,7 +6776,7 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port, * the timeout at wait for CP_IRQ. */ intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout); - ret = hdcp2_detect_msg_availability(intel_dig_port, + ret = hdcp2_detect_msg_availability(dig_port, msg_id, &msg_ready); if (!msg_ready) ret = -ETIMEDOUT; @@ -6815,10 +6802,10 @@ static const struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id) } static -int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port, void *buf, size_t size) { - struct intel_dp *dp = &intel_dig_port->dp; + struct intel_dp *dp = &dig_port->dp; struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; unsigned int offset; u8 *byte = buf; @@ -6841,7 +6828,7 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port, len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ? DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write; - ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux, + ret = drm_dp_dpcd_write(&dig_port->dp.aux, offset, (void *)byte, len); if (ret < 0) return ret; @@ -6855,13 +6842,13 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port, } static -ssize_t get_receiver_id_list_size(struct intel_digital_port *intel_dig_port) +ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port) { u8 rx_info[HDCP_2_2_RXINFO_LEN]; u32 dev_cnt; ssize_t ret; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_HDCP_2_2_REG_RXINFO_OFFSET, (void *)rx_info, HDCP_2_2_RXINFO_LEN); if (ret != HDCP_2_2_RXINFO_LEN) @@ -6881,10 +6868,10 @@ ssize_t get_receiver_id_list_size(struct intel_digital_port *intel_dig_port) } static -int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port, u8 msg_id, void *buf, size_t size) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); unsigned int offset; u8 *byte = buf; ssize_t ret, bytes_to_recv, len; @@ -6895,12 +6882,12 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, return -EINVAL; offset = hdcp2_msg_data->offset; - ret = intel_dp_hdcp2_wait_for_msg(intel_dig_port, hdcp2_msg_data); + ret = intel_dp_hdcp2_wait_for_msg(dig_port, hdcp2_msg_data); if (ret < 0) return ret; if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) { - ret = get_receiver_id_list_size(intel_dig_port); + ret = get_receiver_id_list_size(dig_port); if (ret < 0) return ret; @@ -6915,7 +6902,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ? DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, offset, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, offset, (void *)byte, len); if (ret < 0) { drm_dbg_kms(&i915->drm, "msg_id %d, ret %zd\n", @@ -6934,7 +6921,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port, bool is_repeater, u8 content_type) { int ret; @@ -6953,7 +6940,7 @@ int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port, stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE; stream_type_msg.stream_type = content_type; - ret = intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg, + ret = intel_dp_hdcp2_write_msg(dig_port, &stream_type_msg, sizeof(stream_type_msg)); return ret < 0 ? ret : 0; @@ -6961,12 +6948,12 @@ int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port, } static -int intel_dp_hdcp2_check_link(struct intel_digital_port *intel_dig_port) +int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port) { u8 rx_status; int ret; - ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status); + ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status); if (ret) return ret; @@ -6981,14 +6968,14 @@ int intel_dp_hdcp2_check_link(struct intel_digital_port *intel_dig_port) } static -int intel_dp_hdcp2_capable(struct intel_digital_port *intel_dig_port, +int intel_dp_hdcp2_capable(struct intel_digital_port *dig_port, bool *capable) { u8 rx_caps[3]; int ret; *capable = false; - ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_HDCP_2_2_REG_RX_CAPS_OFFSET, rx_caps, HDCP_2_2_RXCAPS_LEN); if (ret != HDCP_2_2_RXCAPS_LEN) @@ -7267,12 +7254,12 @@ static bool intel_edp_have_power(struct intel_dp *intel_dp) } enum irqreturn -intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) +intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_dp *intel_dp = &dig_port->dp; - if (intel_dig_port->base.type == INTEL_OUTPUT_EDP && + if (dig_port->base.type == INTEL_OUTPUT_EDP && (long_hpd || !intel_edp_have_power(intel_dp))) { /* * vdd off can generate a long/short pulse on eDP which @@ -7283,14 +7270,14 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) drm_dbg_kms(&i915->drm, "ignoring %s hpd on eDP [ENCODER:%d:%s]\n", long_hpd ? "long" : "short", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name); + dig_port->base.base.base.id, + dig_port->base.base.name); return IRQ_HANDLED; } drm_dbg_kms(&i915->drm, "got hpd irq on [ENCODER:%d:%s] - %s\n", - intel_dig_port->base.base.base.id, - intel_dig_port->base.base.name, + dig_port->base.base.base.id, + dig_port->base.base.name, long_hpd ? "long" : "short"); if (long_hpd) { @@ -7299,35 +7286,10 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) } if (intel_dp->is_mst) { - switch (intel_dp_check_mst_status(intel_dp)) { - case -EINVAL: - /* - * If we were in MST mode, and device is not - * there, get out of MST mode - */ - drm_dbg_kms(&i915->drm, - "MST device may have disappeared %d vs %d\n", - intel_dp->is_mst, - intel_dp->mst_mgr.mst_state); - intel_dp->is_mst = false; - drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, - intel_dp->is_mst); - - return IRQ_NONE; - case 1: - return IRQ_NONE; - default: - break; - } - } - - if (!intel_dp->is_mst) { - bool handled; - - handled = intel_dp_short_pulse(intel_dp); - - if (!handled) + if (!intel_dp_check_mst_status(intel_dp)) return IRQ_NONE; + } else if (!intel_dp_short_pulse(intel_dp)) { + return IRQ_NONE; } return IRQ_HANDLED; @@ -8181,12 +8143,12 @@ static void intel_dp_modeset_retry_work_fn(struct work_struct *work) } bool -intel_dp_init_connector(struct intel_digital_port *intel_dig_port, +intel_dp_init_connector(struct intel_digital_port *dig_port, struct intel_connector *intel_connector) { struct drm_connector *connector = &intel_connector->base; - struct intel_dp *intel_dp = &intel_dig_port->dp; - struct intel_encoder *intel_encoder = &intel_dig_port->base; + struct intel_dp *intel_dp = &dig_port->dp; + struct intel_encoder *intel_encoder = &dig_port->base; struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum port port = intel_encoder->port; @@ -8197,9 +8159,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, INIT_WORK(&intel_connector->modeset_retry_work, intel_dp_modeset_retry_work_fn); - if (drm_WARN(dev, intel_dig_port->max_lanes < 1, + if (drm_WARN(dev, dig_port->max_lanes < 1, "Not enough lanes (%d) for DP on [ENCODER:%d:%s]\n", - intel_dig_port->max_lanes, intel_encoder->base.base.id, + dig_port->max_lanes, intel_encoder->base.base.id, intel_encoder->base.name)) return false; @@ -8270,12 +8232,12 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_connector->get_hw_state = intel_connector_get_hw_state; /* init MST on ports that can support it */ - intel_dp_mst_encoder_init(intel_dig_port, + intel_dp_mst_encoder_init(dig_port, intel_connector->base.base.id); if (!intel_edp_init_connector(intel_dp, intel_connector)) { intel_dp_aux_fini(intel_dp); - intel_dp_mst_encoder_cleanup(intel_dig_port); + intel_dp_mst_encoder_cleanup(dig_port); goto fail; } @@ -8310,20 +8272,20 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, i915_reg_t output_reg, enum port port) { - struct intel_digital_port *intel_dig_port; + struct intel_digital_port *dig_port; struct intel_encoder *intel_encoder; struct drm_encoder *encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); - if (!intel_dig_port) + dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); + if (!dig_port) return false; intel_connector = intel_connector_alloc(); if (!intel_connector) goto err_connector_alloc; - intel_encoder = &intel_dig_port->base; + intel_encoder = &dig_port->base; encoder = &intel_encoder->base; if (drm_encoder_init(&dev_priv->drm, &intel_encoder->base, @@ -8359,25 +8321,34 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, if ((IS_IVYBRIDGE(dev_priv) && port == PORT_A) || (HAS_PCH_CPT(dev_priv) && port != PORT_A)) - intel_dig_port->dp.set_link_train = cpt_set_link_train; + dig_port->dp.set_link_train = cpt_set_link_train; else - intel_dig_port->dp.set_link_train = g4x_set_link_train; + dig_port->dp.set_link_train = g4x_set_link_train; if (IS_CHERRYVIEW(dev_priv)) - intel_dig_port->dp.set_signal_levels = chv_set_signal_levels; + dig_port->dp.set_signal_levels = chv_set_signal_levels; else if (IS_VALLEYVIEW(dev_priv)) - intel_dig_port->dp.set_signal_levels = vlv_set_signal_levels; + dig_port->dp.set_signal_levels = vlv_set_signal_levels; else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) - intel_dig_port->dp.set_signal_levels = ivb_cpu_edp_set_signal_levels; + dig_port->dp.set_signal_levels = ivb_cpu_edp_set_signal_levels; else if (IS_GEN(dev_priv, 6) && port == PORT_A) - intel_dig_port->dp.set_signal_levels = snb_cpu_edp_set_signal_levels; + dig_port->dp.set_signal_levels = snb_cpu_edp_set_signal_levels; else - intel_dig_port->dp.set_signal_levels = g4x_set_signal_levels; + dig_port->dp.set_signal_levels = g4x_set_signal_levels; + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv) || + (HAS_PCH_SPLIT(dev_priv) && port != PORT_A)) { + dig_port->dp.preemph_max = intel_dp_pre_empemph_max_3; + dig_port->dp.voltage_max = intel_dp_voltage_max_3; + } else { + dig_port->dp.preemph_max = intel_dp_pre_empemph_max_2; + dig_port->dp.voltage_max = intel_dp_voltage_max_2; + } - intel_dig_port->dp.output_reg = output_reg; - intel_dig_port->max_lanes = 4; - intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port); - intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port); + dig_port->dp.output_reg = output_reg; + dig_port->max_lanes = 4; + dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port); + dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port); intel_encoder->type = INTEL_OUTPUT_DP; intel_encoder->power_domain = intel_port_to_power_domain(port); @@ -8392,25 +8363,25 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_encoder->cloneable = 0; intel_encoder->port = port; - intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; + dig_port->hpd_pulse = intel_dp_hpd_pulse; if (HAS_GMCH(dev_priv)) { if (IS_GM45(dev_priv)) - intel_dig_port->connected = gm45_digital_port_connected; + dig_port->connected = gm45_digital_port_connected; else - intel_dig_port->connected = g4x_digital_port_connected; + dig_port->connected = g4x_digital_port_connected; } else { if (port == PORT_A) - intel_dig_port->connected = ilk_digital_port_connected; + dig_port->connected = ilk_digital_port_connected; else - intel_dig_port->connected = ibx_digital_port_connected; + dig_port->connected = ibx_digital_port_connected; } if (port != PORT_A) - intel_infoframe_init(intel_dig_port); + intel_infoframe_init(dig_port); - intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); - if (!intel_dp_init_connector(intel_dig_port, intel_connector)) + dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); + if (!intel_dp_init_connector(dig_port, intel_connector)) goto err_init_connector; return true; @@ -8420,7 +8391,7 @@ err_init_connector: err_encoder_init: kfree(intel_connector); err_connector_alloc: - kfree(intel_dig_port); + kfree(dig_port); return false; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 1702959ca079..b901ab850cbd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -40,7 +40,7 @@ bool intel_dp_port_enabled(struct drm_i915_private *dev_priv, enum pipe *pipe); bool intel_dp_init(struct drm_i915_private *dev_priv, i915_reg_t output_reg, enum port port); -bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, +bool intel_dp_init_connector(struct intel_digital_port *dig_port, struct intel_connector *intel_connector); void intel_dp_set_link_params(struct intel_dp *intel_dp, int link_rate, u8 lane_count, @@ -61,7 +61,7 @@ int intel_dp_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state); bool intel_dp_is_edp(struct intel_dp *intel_dp); bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); -enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, +enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd); void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); @@ -92,10 +92,6 @@ intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, void intel_dp_set_signal_levels(struct intel_dp *intel_dp); void intel_dp_set_idle_link_train(struct intel_dp *intel_dp); -u8 -intel_dp_voltage_max(struct intel_dp *intel_dp); -u8 -intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing); void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, u8 *link_bw, u8 *rate_select); bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 0722540d64ad..acbd7eb66cbe 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -348,7 +348,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) struct intel_dp *intel_dp = enc_to_intel_dp(intel_connector->encoder); struct drm_i915_private *i915 = dp_to_i915(intel_dp); - if (i915_modparams.enable_dpcd_backlight == 0 || + if (i915->params.enable_dpcd_backlight == 0 || !intel_dp_aux_display_control_capable(intel_connector)) return -ENODEV; @@ -358,7 +358,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) */ if (i915->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE && - i915_modparams.enable_dpcd_backlight != 1 && + i915->params.enable_dpcd_backlight != 1 && !drm_dp_has_quirk(&intel_dp->desc, intel_dp->edid_quirks, DP_QUIRK_FORCE_DPCD_BACKLIGHT)) { drm_info(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index e4f1843170b7..a23ed7290843 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -34,9 +34,25 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE]) link_status[3], link_status[4], link_status[5]); } +static u8 dp_voltage_max(u8 preemph) +{ + switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) { + case DP_TRAIN_PRE_EMPH_LEVEL_0: + return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; + case DP_TRAIN_PRE_EMPH_LEVEL_1: + return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; + case DP_TRAIN_PRE_EMPH_LEVEL_2: + return DP_TRAIN_VOLTAGE_SWING_LEVEL_1; + case DP_TRAIN_PRE_EMPH_LEVEL_3: + default: + return DP_TRAIN_VOLTAGE_SWING_LEVEL_0; + } +} + void intel_dp_get_adjust_train(struct intel_dp *intel_dp, const u8 link_status[DP_LINK_STATUS_SIZE]) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); u8 v = 0; u8 p = 0; int lane; @@ -44,23 +60,28 @@ void intel_dp_get_adjust_train(struct intel_dp *intel_dp, u8 preemph_max; for (lane = 0; lane < intel_dp->lane_count; lane++) { - u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane); - u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); - - if (this_v > v) - v = this_v; - if (this_p > p) - p = this_p; + v = max(v, drm_dp_get_adjust_request_voltage(link_status, lane)); + p = max(p, drm_dp_get_adjust_request_pre_emphasis(link_status, lane)); } - voltage_max = intel_dp_voltage_max(intel_dp); - if (v >= voltage_max) - v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; + preemph_max = intel_dp->preemph_max(intel_dp); + drm_WARN_ON_ONCE(&i915->drm, + preemph_max != DP_TRAIN_PRE_EMPH_LEVEL_2 && + preemph_max != DP_TRAIN_PRE_EMPH_LEVEL_3); - preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); if (p >= preemph_max) p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + v = min(v, dp_voltage_max(p)); + + voltage_max = intel_dp->voltage_max(intel_dp); + drm_WARN_ON_ONCE(&i915->drm, + voltage_max != DP_TRAIN_VOLTAGE_SWING_LEVEL_2 && + voltage_max != DP_TRAIN_VOLTAGE_SWING_LEVEL_3); + + if (v >= voltage_max) + v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; + for (lane = 0; lane < 4; lane++) intel_dp->train_set[lane] = v | p; } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 2e6c6375a23b..a2d91a499700 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -317,14 +317,33 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, return ret; } +static void clear_act_sent(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + intel_de_write(i915, intel_dp->regs.dp_tp_status, + DP_TP_STATUS_ACT_SENT); +} + +static void wait_for_act_sent(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if (intel_de_wait_for_set(i915, intel_dp->regs.dp_tp_status, + DP_TP_STATUS_ACT_SENT, 1)) + drm_err(&i915->drm, "Timed out waiting for ACT sent\n"); + + drm_dp_check_act_status(&intel_dp->mst_mgr); +} + static void intel_mst_disable_dp(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_digital_port *dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -350,8 +369,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, const struct drm_connector_state *old_conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_digital_port *dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -370,6 +389,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, drm_dp_update_payload_part2(&intel_dp->mst_mgr); + clear_act_sent(intel_dp); + val = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder)); val &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC; @@ -377,11 +398,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), val); - if (intel_de_wait_for_set(dev_priv, intel_dp->regs.dp_tp_status, - DP_TP_STATUS_ACT_SENT, 1)) - drm_err(&dev_priv->drm, - "Timed out waiting for ACT sent when disabling\n"); - drm_dp_check_act_status(&intel_dp->mst_mgr); + wait_for_act_sent(intel_dp); drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); @@ -404,7 +421,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, * the transcoder clock select is set to none. */ if (last_mst_stream) - intel_dp_set_infoframes(&intel_dig_port->base, false, + intel_dp_set_infoframes(&dig_port->base, false, old_crtc_state, NULL); /* * From TGL spec: "If multi-stream slave transcoder: Configure @@ -419,7 +436,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, intel_mst->connector = NULL; if (last_mst_stream) - intel_dig_port->base.post_disable(state, &intel_dig_port->base, + dig_port->base.post_disable(state, &dig_port->base, old_crtc_state, NULL); drm_dbg_kms(&dev_priv->drm, "active links %d\n", @@ -432,11 +449,11 @@ static void intel_mst_pre_pll_enable_dp(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_digital_port *dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &dig_port->dp; if (intel_dp->active_mst_links == 0) - intel_dig_port->base.pre_pll_enable(state, &intel_dig_port->base, + dig_port->base.pre_pll_enable(state, &dig_port->base, pipe_config, NULL); } @@ -446,13 +463,12 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_digital_port *dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &dig_port->dp; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_connector *connector = to_intel_connector(conn_state->connector); int ret; - u32 temp; bool first_mst_stream; /* MST encoders are bound to a crtc, not to a connector, @@ -474,7 +490,7 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); if (first_mst_stream) - intel_dig_port->base.pre_enable(state, &intel_dig_port->base, + dig_port->base.pre_enable(state, &dig_port->base, pipe_config, NULL); ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, @@ -485,14 +501,12 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, drm_err(&dev_priv->drm, "failed to allocate vcpi\n"); intel_dp->active_mst_links++; - temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_status); - intel_de_write(dev_priv, intel_dp->regs.dp_tp_status, temp); ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); /* * Before Gen 12 this is not done as part of - * intel_dig_port->base.pre_enable() and should be done here. For + * dig_port->base.pre_enable() and should be done here. For * Gen 12+ the step in which this should be done is different for the * first MST stream, so it's done on the DDI for the first stream and * here for the following ones. @@ -511,22 +525,28 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_digital_port *dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &dig_port->dp; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + u32 val; drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder); + clear_act_sent(intel_dp); + intel_ddi_enable_transcoder_func(encoder, pipe_config); + val = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)); + val |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; + intel_de_write(dev_priv, + TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder), + val); + drm_dbg_kms(&dev_priv->drm, "active links %d\n", intel_dp->active_mst_links); - if (intel_de_wait_for_set(dev_priv, intel_dp->regs.dp_tp_status, - DP_TP_STATUS_ACT_SENT, 1)) - drm_err(&dev_priv->drm, "Timed out waiting for ACT sent\n"); - - drm_dp_check_act_status(&intel_dp->mst_mgr); + wait_for_act_sent(intel_dp); drm_dp_update_payload_part2(&intel_dp->mst_mgr); @@ -552,9 +572,9 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); - struct intel_digital_port *intel_dig_port = intel_mst->primary; + struct intel_digital_port *dig_port = intel_mst->primary; - intel_ddi_get_config(&intel_dig_port->base, pipe_config); + intel_ddi_get_config(&dig_port->base, pipe_config); } static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) @@ -619,39 +639,60 @@ static int intel_dp_mst_get_modes(struct drm_connector *connector) return intel_dp_mst_get_ddc_modes(connector); } -static enum drm_mode_status -intel_dp_mst_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static int +intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, + struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx, + enum drm_mode_status *status) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dp *intel_dp = intel_connector->mst_port; + struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; + struct drm_dp_mst_port *port = intel_connector->port; + const int min_bpp = 18; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; + int ret; - if (drm_connector_is_unregistered(connector)) - return MODE_ERROR; + if (drm_connector_is_unregistered(connector)) { + *status = MODE_ERROR; + return 0; + } - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { + *status = MODE_NO_DBLESCAN; + return 0; + } max_link_clock = intel_dp_max_link_rate(intel_dp); max_lanes = intel_dp_max_lane_count(intel_dp); max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); - mode_rate = intel_dp_link_required(mode->clock, 18); + mode_rate = intel_dp_link_required(mode->clock, min_bpp); - /* TODO - validate mode against available PBN for link */ - if (mode->clock < 10000) - return MODE_CLOCK_LOW; + ret = drm_modeset_lock(&mgr->base.lock, ctx); + if (ret) + return ret; + + if (mode_rate > max_rate || mode->clock > max_dotclk || + drm_dp_calc_pbn_mode(mode->clock, min_bpp, false) > port->full_pbn) { + *status = MODE_CLOCK_HIGH; + return 0; + } - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_H_ILLEGAL; + if (mode->clock < 10000) { + *status = MODE_CLOCK_LOW; + return 0; + } - if (mode_rate > max_rate || mode->clock > max_dotclk) - return MODE_CLOCK_HIGH; + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { + *status = MODE_H_ILLEGAL; + return 0; + } - return intel_mode_valid_max_plane_size(dev_priv, mode); + *status = intel_mode_valid_max_plane_size(dev_priv, mode); + return 0; } static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *connector, @@ -680,7 +721,7 @@ intel_dp_mst_detect(struct drm_connector *connector, static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = { .get_modes = intel_dp_mst_get_modes, - .mode_valid = intel_dp_mst_mode_valid, + .mode_valid_ctx = intel_dp_mst_mode_valid_ctx, .atomic_best_encoder = intel_mst_atomic_best_encoder, .atomic_check = intel_dp_mst_atomic_check, .detect_ctx = intel_dp_mst_detect, @@ -712,8 +753,8 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector) 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 *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_connector *intel_connector; struct drm_connector *connector; @@ -788,11 +829,11 @@ static const struct drm_dp_mst_topology_cbs mst_cbs = { }; static struct intel_dp_mst_encoder * -intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum pipe pipe) +intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe pipe) { struct intel_dp_mst_encoder *intel_mst; struct intel_encoder *intel_encoder; - struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_device *dev = dig_port->base.base.dev; intel_mst = kzalloc(sizeof(*intel_mst), GFP_KERNEL); @@ -801,14 +842,14 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum intel_mst->pipe = pipe; intel_encoder = &intel_mst->base; - intel_mst->primary = intel_dig_port; + intel_mst->primary = dig_port; drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs, DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe)); intel_encoder->type = INTEL_OUTPUT_DP_MST; - intel_encoder->power_domain = intel_dig_port->base.power_domain; - intel_encoder->port = intel_dig_port->base.port; + intel_encoder->power_domain = dig_port->base.power_domain; + intel_encoder->port = dig_port->base.port; intel_encoder->cloneable = 0; /* * This is wrong, but broken userspace uses the intersection @@ -835,29 +876,29 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum } static bool -intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port) +intel_dp_create_fake_mst_encoders(struct intel_digital_port *dig_port) { - struct intel_dp *intel_dp = &intel_dig_port->dp; - struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); + struct intel_dp *intel_dp = &dig_port->dp; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum pipe pipe; for_each_pipe(dev_priv, pipe) - intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(intel_dig_port, pipe); + intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(dig_port, pipe); return true; } int -intel_dp_mst_encoder_active_links(struct intel_digital_port *intel_dig_port) +intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port) { - return intel_dig_port->dp.active_mst_links; + return dig_port->dp.active_mst_links; } int -intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_base_id) +intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_dp *intel_dp = &intel_dig_port->dp; - enum port port = intel_dig_port->base.port; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_dp *intel_dp = &dig_port->dp; + enum port port = dig_port->base.port; int ret; if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp)) @@ -872,7 +913,7 @@ intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_ba intel_dp->mst_mgr.cbs = &mst_cbs; /* create encoders */ - intel_dp_create_fake_mst_encoders(intel_dig_port); + intel_dp_create_fake_mst_encoders(dig_port); ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm, &intel_dp->aux, 16, 3, conn_base_id); if (ret) @@ -884,9 +925,9 @@ intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_ba } void -intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port) +intel_dp_mst_encoder_cleanup(struct intel_digital_port *dig_port) { - struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_dp *intel_dp = &dig_port->dp; if (!intel_dp->can_mst) return; diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h index 854724f68f09..6afda4e86b3c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h @@ -11,9 +11,9 @@ struct intel_digital_port; struct intel_crtc_state; -int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); -void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port); -int intel_dp_mst_encoder_active_links(struct intel_digital_port *intel_dig_port); +int intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_id); +void intel_dp_mst_encoder_cleanup(struct intel_digital_port *dig_port); +int intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port); bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state); bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 399a7edb4568..7910522273b2 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -650,9 +650,9 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, bool uniq_trans_scale) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - enum dpio_channel ch = vlv_dport_to_channel(dport); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum pipe pipe = intel_crtc->pipe; u32 val; int i; @@ -746,7 +746,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, bool reset) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(encoder)); + enum dpio_channel ch = vlv_dig_port_to_channel(enc_to_dig_port(encoder)); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; u32 val; @@ -789,10 +789,10 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, void chv_phy_pre_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel ch = vlv_dport_to_channel(dport); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum pipe pipe = crtc->pipe; unsigned int lane_mask = intel_dp_unused_lane_mask(crtc_state->lane_count); @@ -803,7 +803,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, * Otherwise we can't even access the PLL. */ if (ch == DPIO_CH0 && pipe == PIPE_B) - dport->release_cl2_override = + dig_port->release_cl2_override = !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); chv_phy_powergate_lanes(encoder, true, lane_mask); @@ -870,10 +870,10 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel ch = vlv_dport_to_channel(dport); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum pipe pipe = crtc->pipe; int data, i, stagger; u32 val; @@ -948,12 +948,12 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, void chv_phy_release_cl2_override(struct intel_encoder *encoder) { - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (dport->release_cl2_override) { + if (dig_port->release_cl2_override) { chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); - dport->release_cl2_override = false; + dig_port->release_cl2_override = false; } } @@ -997,8 +997,8 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct intel_digital_port *dport = enc_to_dig_port(encoder); - enum dpio_channel port = vlv_dport_to_channel(dport); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + enum dpio_channel port = vlv_dig_port_to_channel(dig_port); enum pipe pipe = intel_crtc->pipe; vlv_dpio_get(dev_priv); @@ -1022,10 +1022,10 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dig_port_to_channel(dig_port); enum pipe pipe = crtc->pipe; /* Program Tx lane resets to default */ @@ -1052,10 +1052,10 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dig_port_to_channel(dig_port); enum pipe pipe = crtc->pipe; u32 val; @@ -1081,10 +1081,10 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, void vlv_phy_reset_lanes(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dig_port_to_channel(dig_port); enum pipe pipe = crtc->pipe; vlv_dpio_get(dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index b45185b80bec..aeb6ee395cce 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2934,6 +2934,15 @@ static const struct skl_wrpll_params tgl_tbt_pll_19_2MHz_values = { static const struct skl_wrpll_params tgl_tbt_pll_24MHz_values = { .dco_integer = 0x43, .dco_fraction = 0x4000, /* the following params are unused */ +}; + +/* + * Display WA #22010492432: tgl + * Divide the nominal .dco_fraction value by 2. + */ +static const struct skl_wrpll_params tgl_tbt_pll_38_4MHz_values = { + .dco_integer = 0x54, .dco_fraction = 0x1800, + /* the following params are unused */ .pdiv = 0, .kdiv = 0, .qdiv_mode = 0, .qdiv_ratio = 0, }; @@ -2970,12 +2979,14 @@ static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, MISSING_CASE(dev_priv->dpll.ref_clks.nssc); /* fall-through */ case 19200: - case 38400: *pll_params = tgl_tbt_pll_19_2MHz_values; break; case 24000: *pll_params = tgl_tbt_pll_24MHz_values; break; + case 38400: + *pll_params = tgl_tbt_pll_38_4MHz_values; + break; } } else { switch (dev_priv->dpll.ref_clks.nssc) { @@ -3038,49 +3049,26 @@ static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915, icl_wrpll_ref_clock(i915)); } -static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder, +static void icl_calc_dpll_state(struct drm_i915_private *i915, + const struct skl_wrpll_params *pll_params, struct intel_dpll_hw_state *pll_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - u32 cfgcr0, cfgcr1; - struct skl_wrpll_params pll_params = { 0 }; - bool ret; - - if (intel_phy_is_tc(dev_priv, intel_port_to_phy(dev_priv, - encoder->port))) - ret = icl_calc_tbt_pll(crtc_state, &pll_params); - else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) || - intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) - ret = icl_calc_wrpll(crtc_state, &pll_params); - else - ret = icl_calc_dp_combo_pll(crtc_state, &pll_params); - - if (!ret) - return false; + memset(pll_state, 0, sizeof(*pll_state)); - cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(pll_params.dco_fraction) | - pll_params.dco_integer; + pll_state->cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(pll_params->dco_fraction) | + pll_params->dco_integer; - cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params.qdiv_ratio) | - DPLL_CFGCR1_QDIV_MODE(pll_params.qdiv_mode) | - DPLL_CFGCR1_KDIV(pll_params.kdiv) | - DPLL_CFGCR1_PDIV(pll_params.pdiv); + pll_state->cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params->qdiv_ratio) | + DPLL_CFGCR1_QDIV_MODE(pll_params->qdiv_mode) | + DPLL_CFGCR1_KDIV(pll_params->kdiv) | + DPLL_CFGCR1_PDIV(pll_params->pdiv); - if (INTEL_GEN(dev_priv) >= 12) - cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL; + if (INTEL_GEN(i915) >= 12) + pll_state->cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL; else - cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400; - - memset(pll_state, 0, sizeof(*pll_state)); - - pll_state->cfgcr0 = cfgcr0; - pll_state->cfgcr1 = cfgcr1; - - return true; + pll_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400; } - static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id) { return id - DPLL_ID_ICL_MGPLL1; @@ -3493,19 +3481,29 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + struct skl_wrpll_params pll_params = { }; struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum port port = encoder->port; unsigned long dpll_mask; + int ret; - if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) { + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) || + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) + ret = icl_calc_wrpll(crtc_state, &pll_params); + else + ret = icl_calc_dp_combo_pll(crtc_state, &pll_params); + + if (!ret) { drm_dbg_kms(&dev_priv->drm, "Could not calculate combo PHY PLL state.\n"); return false; } + icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); + if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A) dpll_mask = BIT(DPLL_ID_EHL_DPLL4) | @@ -3539,16 +3537,19 @@ static bool icl_get_tc_phy_dplls(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + struct skl_wrpll_params pll_params = { }; struct icl_port_dpll *port_dpll; enum intel_dpll_id dpll_id; port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) { + if (!icl_calc_tbt_pll(crtc_state, &pll_params)) { drm_dbg_kms(&dev_priv->drm, "Could not calculate TBT PLL state.\n"); return false; } + icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); + port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, BIT(DPLL_ID_ICL_TBTPLL)); diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 29fec6a92d17..566fa72427b3 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -34,152 +34,52 @@ #define DSB_BYTE_EN_SHIFT 20 #define DSB_REG_VALUE_MASK 0xfffff -static bool is_dsb_busy(struct intel_dsb *dsb) +static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, + enum dsb_id id) { - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - - return DSB_STATUS & intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id)); + return DSB_STATUS & intel_de_read(i915, DSB_CTRL(pipe, id)); } -static bool intel_dsb_enable_engine(struct intel_dsb *dsb) +static bool intel_dsb_enable_engine(struct drm_i915_private *i915, + enum pipe pipe, enum dsb_id id) { - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; u32 dsb_ctrl; - dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id)); + dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); if (DSB_STATUS & dsb_ctrl) { - drm_dbg_kms(&dev_priv->drm, "DSB engine is busy.\n"); + drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); return false; } dsb_ctrl |= DSB_ENABLE; - intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), dsb_ctrl); + intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); - intel_de_posting_read(dev_priv, DSB_CTRL(pipe, dsb->id)); + intel_de_posting_read(i915, DSB_CTRL(pipe, id)); return true; } -static bool intel_dsb_disable_engine(struct intel_dsb *dsb) +static bool intel_dsb_disable_engine(struct drm_i915_private *i915, + enum pipe pipe, enum dsb_id id) { - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; u32 dsb_ctrl; - dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id)); + dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); if (DSB_STATUS & dsb_ctrl) { - drm_dbg_kms(&dev_priv->drm, "DSB engine is busy.\n"); + drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); return false; } dsb_ctrl &= ~DSB_ENABLE; - intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), dsb_ctrl); + intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); - intel_de_posting_read(dev_priv, DSB_CTRL(pipe, dsb->id)); + intel_de_posting_read(i915, DSB_CTRL(pipe, id)); return true; } /** - * intel_dsb_get() - Allocate DSB context and return a DSB instance. - * @crtc: intel_crtc structure to get pipe info. - * - * This function provides handle of a DSB instance, for the further DSB - * operations. - * - * Returns: address of Intel_dsb instance requested for. - * Failure: Returns the same DSB instance, but without a command buffer. - */ - -struct intel_dsb * -intel_dsb_get(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *i915 = to_i915(dev); - struct intel_dsb *dsb = &crtc->dsb; - struct drm_i915_gem_object *obj; - struct i915_vma *vma; - u32 *buf; - intel_wakeref_t wakeref; - - if (!HAS_DSB(i915)) - return dsb; - - if (dsb->refcount++ != 0) - return dsb; - - wakeref = intel_runtime_pm_get(&i915->runtime_pm); - - obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); - if (IS_ERR(obj)) { - drm_err(&i915->drm, "Gem object creation failed\n"); - goto out; - } - - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); - if (IS_ERR(vma)) { - drm_err(&i915->drm, "Vma creation failed\n"); - i915_gem_object_put(obj); - goto out; - } - - buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC); - if (IS_ERR(buf)) { - drm_err(&i915->drm, "Command buffer creation failed\n"); - goto out; - } - - dsb->id = DSB1; - dsb->vma = vma; - dsb->cmd_buf = buf; - -out: - /* - * On error dsb->cmd_buf will continue to be NULL, making the writes - * pass-through. Leave the dangling ref to be removed later by the - * corresponding intel_dsb_put(): the important error message will - * already be logged above. - */ - - intel_runtime_pm_put(&i915->runtime_pm, wakeref); - - return dsb; -} - -/** - * intel_dsb_put() - To destroy DSB context. - * @dsb: intel_dsb structure. - * - * This function destroys the DSB context allocated by a dsb_get(), by - * unpinning and releasing the VMA object associated with it. - */ - -void intel_dsb_put(struct intel_dsb *dsb) -{ - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - - if (!HAS_DSB(i915)) - return; - - if (drm_WARN_ON(&i915->drm, dsb->refcount == 0)) - return; - - if (--dsb->refcount == 0) { - i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP); - dsb->cmd_buf = NULL; - dsb->free_pos = 0; - dsb->ins_start_offset = 0; - } -} - -/** * intel_dsb_indexed_reg_write() -Write to the DSB context for auto * increment register. - * @dsb: intel_dsb structure. + * @crtc_state: intel_crtc_state structure * @reg: register address. * @val: value. * @@ -189,19 +89,20 @@ void intel_dsb_put(struct intel_dsb *dsb) * is done through mmio write. */ -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, - u32 val) +void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); + struct intel_dsb *dsb = crtc_state->dsb; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf = dsb->cmd_buf; + u32 *buf; u32 reg_val; - if (!buf) { + if (!dsb) { intel_de_write(dev_priv, reg, val); return; } - + buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; @@ -256,7 +157,7 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, /** * intel_dsb_reg_write() -Write to the DSB context for normal * register. - * @dsb: intel_dsb structure. + * @crtc_state: intel_crtc_state structure * @reg: register address. * @val: value. * @@ -265,17 +166,21 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, * and rest all erroneous condition register programming is done * through mmio write. */ -void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) +void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf = dsb->cmd_buf; + struct intel_dsb *dsb; + u32 *buf; - if (!buf) { + dsb = crtc_state->dsb; + if (!dsb) { intel_de_write(dev_priv, reg, val); return; } + buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; @@ -290,26 +195,27 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) /** * intel_dsb_commit() - Trigger workload execution of DSB. - * @dsb: intel_dsb structure. + * @crtc_state: intel_crtc_state structure * * This function is used to do actual write to hardware using DSB. * On errors, fall back to MMIO. Also this function help to reset the context. */ -void intel_dsb_commit(struct intel_dsb *dsb) +void intel_dsb_commit(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb); + struct intel_dsb *dsb = crtc_state->dsb; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum pipe pipe = crtc->pipe; u32 tail; - if (!dsb->free_pos) + if (!(dsb && dsb->free_pos)) return; - if (!intel_dsb_enable_engine(dsb)) + if (!intel_dsb_enable_engine(dev_priv, pipe, dsb->id)) goto reset; - if (is_dsb_busy(dsb)) { + if (is_dsb_busy(dev_priv, pipe, dsb->id)) { drm_err(&dev_priv->drm, "HEAD_PTR write failed - dsb engine is busy.\n"); goto reset; @@ -322,7 +228,7 @@ void intel_dsb_commit(struct intel_dsb *dsb) memset(&dsb->cmd_buf[dsb->free_pos], 0, (tail - dsb->free_pos * 4)); - if (is_dsb_busy(dsb)) { + if (is_dsb_busy(dev_priv, pipe, dsb->id)) { drm_err(&dev_priv->drm, "TAIL_PTR write failed - dsb engine is busy.\n"); goto reset; @@ -332,7 +238,7 @@ void intel_dsb_commit(struct intel_dsb *dsb) i915_ggtt_offset(dsb->vma), tail); intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id), i915_ggtt_offset(dsb->vma) + tail); - if (wait_for(!is_dsb_busy(dsb), 1)) { + if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) { drm_err(&dev_priv->drm, "Timed out waiting for DSB workload completion.\n"); goto reset; @@ -341,5 +247,83 @@ void intel_dsb_commit(struct intel_dsb *dsb) reset: dsb->free_pos = 0; dsb->ins_start_offset = 0; - intel_dsb_disable_engine(dsb); + intel_dsb_disable_engine(dev_priv, pipe, dsb->id); +} + +/** + * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. + * @crtc_state: intel_crtc_state structure to prepare associated dsb instance. + * + * This function prepare the command buffer which is used to store dsb + * instructions with data. + */ +void intel_dsb_prepare(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_dsb *dsb; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + u32 *buf; + intel_wakeref_t wakeref; + + if (!HAS_DSB(i915)) + return; + + dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); + if (!dsb) { + drm_err(&i915->drm, "DSB object creation failed\n"); + return; + } + + wakeref = intel_runtime_pm_get(&i915->runtime_pm); + + obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); + if (IS_ERR(obj)) { + drm_err(&i915->drm, "Gem object creation failed\n"); + kfree(dsb); + goto out; + } + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); + if (IS_ERR(vma)) { + drm_err(&i915->drm, "Vma creation failed\n"); + i915_gem_object_put(obj); + kfree(dsb); + goto out; + } + + buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC); + if (IS_ERR(buf)) { + drm_err(&i915->drm, "Command buffer creation failed\n"); + i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); + kfree(dsb); + goto out; + } + + dsb->id = DSB1; + dsb->vma = vma; + dsb->cmd_buf = buf; + dsb->free_pos = 0; + dsb->ins_start_offset = 0; + crtc_state->dsb = dsb; +out: + intel_runtime_pm_put(&i915->runtime_pm, wakeref); +} + +/** + * intel_dsb_cleanup() - To cleanup DSB context. + * @crtc_state: intel_crtc_state structure to cleanup associated dsb instance. + * + * This function cleanup the DSB context by unpinning and releasing + * the VMA object associated with it. + */ +void intel_dsb_cleanup(struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->dsb) + return; + + i915_vma_unpin_and_release(&crtc_state->dsb->vma, I915_VMA_RELEASE_MAP); + kfree(crtc_state->dsb); + crtc_state->dsb = NULL; } diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 395ef9ce558e..654a11f24b80 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -10,7 +10,7 @@ #include "i915_reg.h" -struct intel_crtc; +struct intel_crtc_state; struct i915_vma; enum dsb_id { @@ -22,7 +22,6 @@ enum dsb_id { }; struct intel_dsb { - long refcount; enum dsb_id id; u32 *cmd_buf; struct i915_vma *vma; @@ -41,12 +40,12 @@ struct intel_dsb { u32 ins_start_offset; }; -struct intel_dsb * -intel_dsb_get(struct intel_crtc *crtc); -void intel_dsb_put(struct intel_dsb *dsb); -void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, - u32 val); -void intel_dsb_commit(struct intel_dsb *dsb); +void intel_dsb_prepare(struct intel_crtc_state *crtc_state); +void intel_dsb_cleanup(struct intel_crtc_state *crtc_state); +void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val); +void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val); +void intel_dsb_commit(const struct intel_crtc_state *crtc_state); #endif diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 5cd09034519b..307ed8ae9a19 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -324,6 +324,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector) struct drm_i915_private *dev_priv = to_i915(connector->dev); const struct drm_display_mode *fixed_mode = to_intel_connector(connector)->panel.fixed_mode; + int num_modes; /* * We should probably have an i2c driver get_modes function for those @@ -331,21 +332,22 @@ static int intel_dvo_get_modes(struct drm_connector *connector) * (TV-out, for example), but for now with just TMDS and LVDS, * that's not the case. */ - intel_ddc_get_modes(connector, - intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); - if (!list_empty(&connector->probed_modes)) - return 1; + num_modes = intel_ddc_get_modes(connector, + intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); + if (num_modes) + return num_modes; if (fixed_mode) { struct drm_display_mode *mode; + mode = drm_mode_duplicate(connector->dev, fixed_mode); if (mode) { drm_mode_probed_add(connector, mode); - return 1; + num_modes++; } } - return 0; + return num_modes; } static const struct drm_connector_funcs intel_dvo_connector_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 1c26673acb2d..85723fba6002 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -48,19 +48,6 @@ #include "intel_frontbuffer.h" /* - * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the - * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's - * origin so the x and y offsets can actually fit the registers. As a - * consequence, the fence doesn't really start exactly at the display plane - * address we program because it starts at the real start of the buffer, so we - * have to take this into consideration here. - */ -static unsigned int get_crtc_fence_y_offset(struct intel_fbc *fbc) -{ - return fbc->state_cache.plane.y - fbc->state_cache.plane.adjusted_y; -} - -/* * For SKL+, the plane source size used by the hardware is based on the value we * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value * we wrote to PIPESRC. @@ -141,18 +128,17 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) fbc_ctl2 |= FBC_CTL_CPU_FENCE; intel_de_write(dev_priv, FBC_CONTROL2, fbc_ctl2); intel_de_write(dev_priv, FBC_FENCE_OFF, - params->crtc.fence_y_offset); + params->fence_y_offset); } /* enable it... */ - fbc_ctl = intel_de_read(dev_priv, FBC_CONTROL); - fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT; + fbc_ctl = FBC_CTL_INTERVAL(params->interval); fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC; if (IS_I945GM(dev_priv)) fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ - fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; + fbc_ctl |= FBC_CTL_STRIDE(cfb_pitch & 0xff); if (params->fence_id >= 0) - fbc_ctl |= params->fence_id; + fbc_ctl |= FBC_CTL_FENCENO(params->fence_id); intel_de_write(dev_priv, FBC_CONTROL, fbc_ctl); } @@ -175,7 +161,7 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) if (params->fence_id >= 0) { dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fence_id; intel_de_write(dev_priv, DPFC_FENCE_YOFF, - params->crtc.fence_y_offset); + params->fence_y_offset); } else { intel_de_write(dev_priv, DPFC_FENCE_YOFF, 0); } @@ -201,8 +187,30 @@ static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv) return intel_de_read(dev_priv, DPFC_CONTROL) & DPFC_CTL_EN; } +static void i8xx_fbc_recompress(struct drm_i915_private *dev_priv) +{ + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; + + spin_lock_irq(&dev_priv->uncore.lock); + intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), + intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane))); + spin_unlock_irq(&dev_priv->uncore.lock); +} + +static void i965_fbc_recompress(struct drm_i915_private *dev_priv) +{ + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; + enum i9xx_plane_id i9xx_plane = params->crtc.i9xx_plane; + + spin_lock_irq(&dev_priv->uncore.lock); + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), + intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane))); + spin_unlock_irq(&dev_priv->uncore.lock); +} + /* This function forces a CFB recompression through the nuke operation. */ -static void intel_fbc_recompress(struct drm_i915_private *dev_priv) +static void snb_fbc_recompress(struct drm_i915_private *dev_priv) { struct intel_fbc *fbc = &dev_priv->fbc; @@ -212,6 +220,16 @@ static void intel_fbc_recompress(struct drm_i915_private *dev_priv) intel_de_posting_read(dev_priv, MSG_FBC_REND_STATE); } +static void intel_fbc_recompress(struct drm_i915_private *dev_priv) +{ + if (INTEL_GEN(dev_priv) >= 6) + snb_fbc_recompress(dev_priv); + else if (INTEL_GEN(dev_priv) >= 4) + i965_fbc_recompress(dev_priv); + else + i8xx_fbc_recompress(dev_priv); +} + static void ilk_fbc_activate(struct drm_i915_private *dev_priv) { struct intel_fbc_reg_params *params = &dev_priv->fbc.params; @@ -243,7 +261,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) intel_de_write(dev_priv, SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | params->fence_id); intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, - params->crtc.fence_y_offset); + params->fence_y_offset); } } else { if (IS_GEN(dev_priv, 6)) { @@ -253,7 +271,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) } intel_de_write(dev_priv, ILK_DPFC_FENCE_YOFF, - params->crtc.fence_y_offset); + params->fence_y_offset); /* enable it... */ intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -320,7 +338,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) intel_de_write(dev_priv, SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | params->fence_id); intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, - params->crtc.fence_y_offset); + params->fence_y_offset); } else if (dev_priv->ggtt.num_fences) { intel_de_write(dev_priv, SNB_DPFC_CTL_SA, 0); intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 0); @@ -329,21 +347,6 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) if (dev_priv->fbc.false_color) dpfc_ctl |= FBC_CTL_FALSE_COLOR; - if (IS_IVYBRIDGE(dev_priv)) { - /* WaFbcAsynchFlipDisableFbcQueue:ivb */ - intel_de_write(dev_priv, ILK_DISPLAY_CHICKEN1, - intel_de_read(dev_priv, ILK_DISPLAY_CHICKEN1) | ILK_FBCQ_DIS); - } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - intel_de_write(dev_priv, CHICKEN_PIPESL_1(params->crtc.pipe), - intel_de_read(dev_priv, CHICKEN_PIPESL_1(params->crtc.pipe)) | HSW_FBCQ_DIS); - } - - if (INTEL_GEN(dev_priv) >= 11) - /* Wa_1409120013:icl,ehl,tgl */ - intel_de_write(dev_priv, ILK_DPFC_CHICKEN, - ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL); - intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); intel_fbc_recompress(dev_priv); @@ -631,8 +634,8 @@ static bool rotation_is_valid(struct drm_i915_private *dev_priv, /* * For some reason, the hardware tracking starts looking at whatever we * programmed as the display plane base address register. It does not look at - * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y} - * variables instead of just looking at the pipe/plane size. + * the X and Y offset registers. That's why we include the src x/y offsets + * instead of just looking at the plane size. */ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) { @@ -705,14 +708,22 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->plane.src_h = drm_rect_height(&plane_state->uapi.src) >> 16; cache->plane.adjusted_x = plane_state->color_plane[0].x; cache->plane.adjusted_y = plane_state->color_plane[0].y; - cache->plane.y = plane_state->uapi.src.y1 >> 16; cache->plane.pixel_blend_mode = plane_state->hw.pixel_blend_mode; cache->fb.format = fb->format; - cache->fb.stride = fb->pitches[0]; cache->fb.modifier = fb->modifier; + /* FIXME is this correct? */ + cache->fb.stride = plane_state->color_plane[0].stride; + if (drm_rotation_90_or_270(plane_state->hw.rotation)) + cache->fb.stride *= fb->format->cpp[0]; + + /* FBC1 compression interval: arbitrary choice of 1 second */ + cache->interval = drm_mode_vrefresh(&crtc_state->hw.adjusted_mode); + + cache->fence_y_offset = intel_plane_fence_y_offset(plane_state); + drm_WARN_ON(&dev_priv->drm, plane_state->flags & PLANE_HAS_FENCE && !plane_state->vma->fence); @@ -731,6 +742,25 @@ static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv) fbc->compressed_fb.size * fbc->threshold; } +static u16 intel_fbc_gen9_wa_cfb_stride(struct drm_i915_private *dev_priv) +{ + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_state_cache *cache = &fbc->state_cache; + + if ((IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) && + cache->fb.modifier != I915_FORMAT_MOD_X_TILED) + return DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8; + else + return 0; +} + +static bool intel_fbc_gen9_wa_cfb_stride_changed(struct drm_i915_private *dev_priv) +{ + struct intel_fbc *fbc = &dev_priv->fbc; + + return fbc->params.gen9_wa_cfb_stride != intel_fbc_gen9_wa_cfb_stride(dev_priv); +} + static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv) { struct intel_fbc *fbc = &dev_priv->fbc; @@ -740,7 +770,7 @@ static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv) return false; } - if (!i915_modparams.enable_fbc) { + if (!dev_priv->params.enable_fbc) { fbc->no_fbc_reason = "disabled per module param or by default"; return false; } @@ -807,6 +837,11 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return false; } + if (!pixel_format_is_valid(dev_priv, cache->fb.format->format)) { + fbc->no_fbc_reason = "pixel format is invalid"; + return false; + } + if (!rotation_is_valid(dev_priv, cache->fb.format->format, cache->plane.rotation)) { fbc->no_fbc_reason = "rotation unsupported"; @@ -823,11 +858,6 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return false; } - if (!pixel_format_is_valid(dev_priv, cache->fb.format->format)) { - fbc->no_fbc_reason = "pixel format is invalid"; - return false; - } - if (cache->plane.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE && cache->fb.format->has_alpha) { fbc->no_fbc_reason = "per-pixel alpha blending is incompatible with FBC"; @@ -883,12 +913,15 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, memset(params, 0, sizeof(*params)); params->fence_id = cache->fence_id; + params->fence_y_offset = cache->fence_y_offset; + + params->interval = cache->interval; params->crtc.pipe = crtc->pipe; params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane; - params->crtc.fence_y_offset = get_crtc_fence_y_offset(fbc); params->fb.format = cache->fb.format; + params->fb.modifier = cache->fb.modifier; params->fb.stride = cache->fb.stride; params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache); @@ -918,6 +951,9 @@ static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) if (params->fb.format != cache->fb.format) return false; + if (params->fb.modifier != cache->fb.modifier) + return false; + if (params->fb.stride != cache->fb.stride) return false; @@ -1017,7 +1053,7 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) fbc->flip_pending = false; - if (!i915_modparams.enable_fbc) { + if (!dev_priv->params.enable_fbc) { intel_fbc_deactivate(dev_priv, "disabled at runtime per module param"); __intel_fbc_disable(dev_priv); @@ -1090,11 +1126,19 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (!HAS_FBC(dev_priv)) return; + /* + * GTT tracking does not nuke the entire cfb + * so don't clear busy_bits set for some other + * reason. + */ + if (origin == ORIGIN_GTT) + return; + mutex_lock(&fbc->lock); fbc->busy_bits &= ~frontbuffer_bits; - if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP) + if (origin == ORIGIN_FLIP) goto out; if (!fbc->busy_bits && fbc->crtc && @@ -1197,7 +1241,8 @@ void intel_fbc_enable(struct intel_atomic_state *state, if (fbc->crtc) { if (fbc->crtc != crtc || - !intel_fbc_cfb_size_changed(dev_priv)) + (!intel_fbc_cfb_size_changed(dev_priv) && + !intel_fbc_gen9_wa_cfb_stride_changed(dev_priv))) goto out; __intel_fbc_disable(dev_priv); @@ -1219,12 +1264,7 @@ void intel_fbc_enable(struct intel_atomic_state *state, goto out; } - if ((IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) && - plane_state->hw.fb->modifier != I915_FORMAT_MOD_X_TILED) - cache->gen9_wa_cfb_stride = - DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8; - else - cache->gen9_wa_cfb_stride = 0; + cache->gen9_wa_cfb_stride = intel_fbc_gen9_wa_cfb_stride(dev_priv); drm_dbg_kms(&dev_priv->drm, "Enabling FBC on pipe %c\n", pipe_name(crtc->pipe)); @@ -1370,8 +1410,8 @@ void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv) */ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) { - if (i915_modparams.enable_fbc >= 0) - return !!i915_modparams.enable_fbc; + if (dev_priv->params.enable_fbc >= 0) + return !!dev_priv->params.enable_fbc; if (!HAS_FBC(dev_priv)) return 0; @@ -1415,20 +1455,15 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) if (need_fbc_vtd_wa(dev_priv)) mkwrite_device_info(dev_priv)->display.has_fbc = false; - i915_modparams.enable_fbc = intel_sanitize_fbc_option(dev_priv); + dev_priv->params.enable_fbc = intel_sanitize_fbc_option(dev_priv); drm_dbg_kms(&dev_priv->drm, "Sanitized enable_fbc value: %d\n", - i915_modparams.enable_fbc); + dev_priv->params.enable_fbc); if (!HAS_FBC(dev_priv)) { fbc->no_fbc_reason = "unsupported by this chipset"; return; } - /* This value was pulled out of someone's hat */ - if (INTEL_GEN(dev_priv) <= 4 && !IS_GM45(dev_priv)) - intel_de_write(dev_priv, FBC_CONTROL, - 500 << FBC_CTL_INTERVAL_SHIFT); - /* We still don't have any sort of hardware state readout for FBC, so * deactivate it in case the BIOS activated it to make sure software * matches the hardware state. */ diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 2cbc4619b4ce..89a4d294822d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -40,15 +40,15 @@ bool intel_hdcp_is_ksv_valid(u8 *ksv) } static -int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port, +int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim, u8 *bksv) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret, i, tries = 2; /* HDCP spec states that we must retry the bksv if it is invalid */ for (i = 0; i < tries; i++) { - ret = shim->read_bksv(intel_dig_port, bksv); + ret = shim->read_bksv(dig_port, bksv); if (ret) return ret; if (intel_hdcp_is_ksv_valid(bksv)) @@ -65,7 +65,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port, /* Is HDCP1.4 capable on Platform and Sink */ bool intel_hdcp_capable(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; bool capable = false; u8 bksv[5]; @@ -74,9 +74,9 @@ bool intel_hdcp_capable(struct intel_connector *connector) return capable; if (shim->hdcp_capable) { - shim->hdcp_capable(intel_dig_port, &capable); + shim->hdcp_capable(dig_port, &capable); } else { - if (!intel_hdcp_read_valid_bksv(intel_dig_port, shim, bksv)) + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) capable = true; } @@ -86,7 +86,7 @@ bool intel_hdcp_capable(struct intel_connector *connector) /* Is HDCP2.2 capable on Platform and Sink */ bool intel_hdcp2_capable(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; bool capable = false; @@ -104,7 +104,7 @@ bool intel_hdcp2_capable(struct intel_connector *connector) mutex_unlock(&dev_priv->hdcp_comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(intel_dig_port, &capable); + hdcp->shim->hdcp_2_2_capable(dig_port, &capable); return capable; } @@ -125,14 +125,14 @@ static bool intel_hdcp2_in_use(struct drm_i915_private *dev_priv, LINK_ENCRYPTION_STATUS; } -static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port, +static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) { int ret, read_ret; bool ksv_ready; /* Poll for ksv list ready (spec says max time allowed is 5s) */ - ret = __wait_for(read_ret = shim->read_ksv_ready(intel_dig_port, + ret = __wait_for(read_ret = shim->read_ksv_ready(dig_port, &ksv_ready), read_ret || ksv_ready, 5 * 1000 * 1000, 1000, 100 * 1000); @@ -300,16 +300,16 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, const struct intel_hdcp_shim *shim, u8 *ksv_fifo, u8 num_downstream, u8 *bstatus) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; u32 vprime, sha_text, sha_leftovers, rep_ctl; int ret, i, j, sha_idx; /* Process V' values from the receiver */ for (i = 0; i < DRM_HDCP_V_PRIME_NUM_PARTS; i++) { - ret = shim->read_v_prime_part(intel_dig_port, i, &vprime); + ret = shim->read_v_prime_part(dig_port, i, &vprime); if (ret) return ret; intel_de_write(dev_priv, HDCP_SHA_V_PRIME(i), vprime); @@ -528,20 +528,20 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, static int intel_hdcp_auth_downstream(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct intel_hdcp_shim *shim = connector->hdcp.shim; u8 bstatus[2], num_downstream, *ksv_fifo; int ret, i, tries = 3; - ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim); + ret = intel_hdcp_poll_ksv_fifo(dig_port, shim); if (ret) { drm_dbg_kms(&dev_priv->drm, "KSV list failed to become ready (%d)\n", ret); return ret; } - ret = shim->read_bstatus(intel_dig_port, bstatus); + ret = shim->read_bstatus(dig_port, bstatus); if (ret) return ret; @@ -571,12 +571,12 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector) return -ENOMEM; } - ret = shim->read_ksv_fifo(intel_dig_port, num_downstream, ksv_fifo); + ret = shim->read_ksv_fifo(dig_port, num_downstream, ksv_fifo); if (ret) goto err; if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, ksv_fifo, - num_downstream)) { + num_downstream) > 0) { drm_err(&dev_priv->drm, "Revoked Ksv(s) in ksv_fifo\n"); ret = -EPERM; goto err; @@ -611,12 +611,12 @@ err: /* Implements Part 1 of the HDCP authorization procedure */ static int intel_hdcp_auth(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; const struct intel_hdcp_shim *shim = hdcp->shim; enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; unsigned long r0_prime_gen_start; int ret, i, tries = 2; union { @@ -640,7 +640,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) * displays, this is not necessary. */ if (shim->hdcp_capable) { - ret = shim->hdcp_capable(intel_dig_port, &hdcp_capable); + ret = shim->hdcp_capable(dig_port, &hdcp_capable); if (ret) return ret; if (!hdcp_capable) { @@ -670,7 +670,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) HDCP_ANLO(dev_priv, cpu_transcoder, port)); an.reg[1] = intel_de_read(dev_priv, HDCP_ANHI(dev_priv, cpu_transcoder, port)); - ret = shim->write_an_aksv(intel_dig_port, an.shim); + ret = shim->write_an_aksv(dig_port, an.shim); if (ret) return ret; @@ -678,11 +678,11 @@ static int intel_hdcp_auth(struct intel_connector *connector) memset(&bksv, 0, sizeof(bksv)); - ret = intel_hdcp_read_valid_bksv(intel_dig_port, shim, bksv.shim); + ret = intel_hdcp_read_valid_bksv(dig_port, shim, bksv.shim); if (ret < 0) return ret; - if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, bksv.shim, 1)) { + if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, bksv.shim, 1) > 0) { drm_err(&dev_priv->drm, "BKSV is revoked\n"); return -EPERM; } @@ -692,14 +692,14 @@ static int intel_hdcp_auth(struct intel_connector *connector) intel_de_write(dev_priv, HDCP_BKSVHI(dev_priv, cpu_transcoder, port), bksv.reg[1]); - ret = shim->repeater_present(intel_dig_port, &repeater_present); + ret = shim->repeater_present(dig_port, &repeater_present); if (ret) return ret; if (repeater_present) intel_de_write(dev_priv, HDCP_REP_CTL, intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, port)); - ret = shim->toggle_signalling(intel_dig_port, true); + ret = shim->toggle_signalling(dig_port, true); if (ret) return ret; @@ -732,7 +732,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) */ for (i = 0; i < tries; i++) { ri.reg = 0; - ret = shim->read_ri_prime(intel_dig_port, ri.shim); + ret = shim->read_ri_prime(dig_port, ri.shim); if (ret) return ret; intel_de_write(dev_priv, @@ -776,10 +776,10 @@ static int intel_hdcp_auth(struct intel_connector *connector) static int _intel_hdcp_disable(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; enum transcoder cpu_transcoder = hdcp->cpu_transcoder; int ret; @@ -796,7 +796,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector) return -ETIMEDOUT; } - ret = hdcp->shim->toggle_signalling(intel_dig_port, false); + ret = hdcp->shim->toggle_signalling(dig_port, false); if (ret) { drm_err(&dev_priv->drm, "Failed to disable HDCP signalling\n"); return ret; @@ -859,10 +859,10 @@ static struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp) /* Implements Part 3 of the HDCP authorization procedure */ static int intel_hdcp_check_link(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; enum transcoder cpu_transcoder; int ret = 0; @@ -888,7 +888,7 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - if (hdcp->shim->check_link(intel_dig_port)) { + if (hdcp->shim->check_link(dig_port)) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; schedule_work(&hdcp->prop_work); @@ -1242,7 +1242,7 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector) /* Authentication flow starts from here */ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; union { @@ -1264,12 +1264,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) if (ret < 0) return ret; - ret = shim->write_2_2_msg(intel_dig_port, &msgs.ake_init, + ret = shim->write_2_2_msg(dig_port, &msgs.ake_init, sizeof(msgs.ake_init)); if (ret < 0) return ret; - ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_CERT, + ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_CERT, &msgs.send_cert, sizeof(msgs.send_cert)); if (ret < 0) return ret; @@ -1283,7 +1283,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, msgs.send_cert.cert_rx.receiver_id, - 1)) { + 1) > 0) { drm_err(&dev_priv->drm, "Receiver ID is revoked\n"); return -EPERM; } @@ -1298,11 +1298,11 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) if (ret < 0) return ret; - ret = shim->write_2_2_msg(intel_dig_port, &msgs.no_stored_km, size); + ret = shim->write_2_2_msg(dig_port, &msgs.no_stored_km, size); if (ret < 0) return ret; - ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_HPRIME, + ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_HPRIME, &msgs.send_hprime, sizeof(msgs.send_hprime)); if (ret < 0) return ret; @@ -1313,7 +1313,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) if (!hdcp->is_paired) { /* Pairing is required */ - ret = shim->read_2_2_msg(intel_dig_port, + ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_PAIRING_INFO, &msgs.pairing_info, sizeof(msgs.pairing_info)); @@ -1331,7 +1331,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) static int hdcp2_locality_check(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; union { struct hdcp2_lc_init lc_init; @@ -1345,12 +1345,12 @@ static int hdcp2_locality_check(struct intel_connector *connector) if (ret < 0) continue; - ret = shim->write_2_2_msg(intel_dig_port, &msgs.lc_init, + ret = shim->write_2_2_msg(dig_port, &msgs.lc_init, sizeof(msgs.lc_init)); if (ret < 0) continue; - ret = shim->read_2_2_msg(intel_dig_port, + ret = shim->read_2_2_msg(dig_port, HDCP_2_2_LC_SEND_LPRIME, &msgs.send_lprime, sizeof(msgs.send_lprime)); @@ -1367,7 +1367,7 @@ static int hdcp2_locality_check(struct intel_connector *connector) static int hdcp2_session_key_exchange(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; struct hdcp2_ske_send_eks send_eks; int ret; @@ -1376,7 +1376,7 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector) if (ret < 0) return ret; - ret = hdcp->shim->write_2_2_msg(intel_dig_port, &send_eks, + ret = hdcp->shim->write_2_2_msg(dig_port, &send_eks, sizeof(send_eks)); if (ret < 0) return ret; @@ -1387,7 +1387,7 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector) static int hdcp2_propagate_stream_management_info(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; union { @@ -1409,12 +1409,12 @@ int hdcp2_propagate_stream_management_info(struct intel_connector *connector) msgs.stream_manage.streams[0].stream_type = hdcp->content_type; /* Send it to Repeater */ - ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage, + ret = shim->write_2_2_msg(dig_port, &msgs.stream_manage, sizeof(msgs.stream_manage)); if (ret < 0) return ret; - ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_STREAM_READY, + ret = shim->read_2_2_msg(dig_port, HDCP_2_2_REP_STREAM_READY, &msgs.stream_ready, sizeof(msgs.stream_ready)); if (ret < 0) return ret; @@ -1439,7 +1439,7 @@ int hdcp2_propagate_stream_management_info(struct intel_connector *connector) static int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; union { @@ -1451,7 +1451,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) u8 *rx_info; int ret; - ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_SEND_RECVID_LIST, + ret = shim->read_2_2_msg(dig_port, HDCP_2_2_REP_SEND_RECVID_LIST, &msgs.recvid_list, sizeof(msgs.recvid_list)); if (ret < 0) return ret; @@ -1484,7 +1484,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) HDCP_2_2_DEV_COUNT_LO(rx_info[1])); if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, msgs.recvid_list.receiver_ids, - device_cnt)) { + device_cnt) > 0) { drm_err(&dev_priv->drm, "Revoked receiver ID(s) is in list\n"); return -EPERM; } @@ -1496,7 +1496,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) return ret; hdcp->seq_num_v = seq_num_v; - ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack, + ret = shim->write_2_2_msg(dig_port, &msgs.rep_ack, sizeof(msgs.rep_ack)); if (ret < 0) return ret; @@ -1517,7 +1517,7 @@ static int hdcp2_authenticate_repeater(struct intel_connector *connector) static int hdcp2_authenticate_sink(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; const struct intel_hdcp_shim *shim = hdcp->shim; @@ -1543,7 +1543,7 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector) } if (shim->config_stream_type) { - ret = shim->config_stream_type(intel_dig_port, + ret = shim->config_stream_type(dig_port, hdcp->is_repeater, hdcp->content_type); if (ret < 0) @@ -1569,10 +1569,10 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector) static int hdcp2_enable_encryption(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; enum transcoder cpu_transcoder = hdcp->cpu_transcoder; int ret; @@ -1580,7 +1580,7 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)) & LINK_ENCRYPTION_STATUS); if (hdcp->shim->toggle_signalling) { - ret = hdcp->shim->toggle_signalling(intel_dig_port, true); + ret = hdcp->shim->toggle_signalling(dig_port, true); if (ret) { drm_err(&dev_priv->drm, "Failed to enable HDCP signalling. %d\n", @@ -1608,10 +1608,10 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) static int hdcp2_disable_encryption(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; enum transcoder cpu_transcoder = hdcp->cpu_transcoder; int ret; @@ -1630,7 +1630,7 @@ static int hdcp2_disable_encryption(struct intel_connector *connector) drm_dbg_kms(&dev_priv->drm, "Disable Encryption Timedout"); if (hdcp->shim->toggle_signalling) { - ret = hdcp->shim->toggle_signalling(intel_dig_port, false); + ret = hdcp->shim->toggle_signalling(dig_port, false); if (ret) { drm_err(&dev_priv->drm, "Failed to disable HDCP signalling. %d\n", @@ -1723,10 +1723,10 @@ static int _intel_hdcp2_disable(struct intel_connector *connector) /* Implements the Link Integrity Check for HDCP2.2 */ static int intel_hdcp2_check_link(struct intel_connector *connector) { - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - enum port port = intel_dig_port->base.port; + enum port port = dig_port->base.port; enum transcoder cpu_transcoder; int ret = 0; @@ -1751,7 +1751,7 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) goto out; } - ret = hdcp->shim->check_2_2_link(intel_dig_port); + ret = hdcp->shim->check_2_2_link(dig_port); if (ret == HDCP_LINK_PROTECTED) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; @@ -1923,8 +1923,11 @@ static bool is_hdcp2_supported(struct drm_i915_private *dev_priv) if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP)) return false; - return (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) || - IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)); + return (INTEL_GEN(dev_priv) >= 10 || + IS_GEMINILAKE(dev_priv) || + IS_KABYLAKE(dev_priv) || + IS_COFFEELAKE(dev_priv) || + IS_COMETLAKE(dev_priv)); } void intel_hdcp_component_init(struct drm_i915_private *dev_priv) @@ -2083,6 +2086,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, (conn_state->hdcp_content_type != hdcp->content_type && conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED); + bool desired_and_not_enabled = false; /* * During the HDCP encryption session if Type change is requested, @@ -2105,8 +2109,15 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, } if (conn_state->content_protection == - DRM_MODE_CONTENT_PROTECTION_DESIRED || - content_protection_type_changed) + DRM_MODE_CONTENT_PROTECTION_DESIRED) { + mutex_lock(&hdcp->mutex); + /* Avoid enabling hdcp, if it already ENABLED */ + desired_and_not_enabled = + hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED; + mutex_unlock(&hdcp->mutex); + } + + if (desired_and_not_enabled || content_protection_type_changed) intel_hdcp_enable(connector, crtc_state->cpu_transcoder, (u8)conn_state->hdcp_content_type); @@ -2155,6 +2166,19 @@ void intel_hdcp_atomic_check(struct drm_connector *connector, return; } + crtc_state = drm_atomic_get_new_crtc_state(new_state->state, + new_state->crtc); + /* + * Fix the HDCP uapi content protection state in case of modeset. + * FIXME: As per HDCP content protection property uapi doc, an uevent() + * need to be sent if there is transition from ENABLED->DESIRED. + */ + if (drm_atomic_crtc_needs_modeset(crtc_state) && + (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED && + new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + /* * Nothing to do if the state didn't change, or HDCP was activated since * the last commit. And also no change in hdcp content type. @@ -2167,8 +2191,6 @@ void intel_hdcp_atomic_check(struct drm_connector *connector, return; } - crtc_state = drm_atomic_get_new_crtc_state(new_state->state, - new_state->crtc); crtc_state->mode_changed = true; } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 010f37240710..de2ce5632b94 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -88,10 +88,10 @@ assert_hdmi_transcoder_func_disabled(struct drm_i915_private *dev_priv, struct intel_hdmi *enc_to_intel_hdmi(struct intel_encoder *encoder) { - struct intel_digital_port *intel_dig_port = + struct intel_digital_port *dig_port = container_of(&encoder->base, struct intel_digital_port, base.base); - return &intel_dig_port->hdmi; + return &dig_port->hdmi; } static struct intel_hdmi *intel_attached_hdmi(struct intel_connector *connector) @@ -660,7 +660,7 @@ static void intel_write_infoframe(struct intel_encoder *encoder, enum hdmi_infoframe_type type, const union hdmi_infoframe *frame) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); u8 buffer[VIDEO_DIP_DATA_SIZE]; ssize_t len; @@ -681,7 +681,7 @@ static void intel_write_infoframe(struct intel_encoder *encoder, buffer[3] = 0; len++; - intel_dig_port->write_infoframe(encoder, crtc_state, type, buffer, len); + dig_port->write_infoframe(encoder, crtc_state, type, buffer, len); } void intel_read_infoframe(struct intel_encoder *encoder, @@ -689,7 +689,7 @@ void intel_read_infoframe(struct intel_encoder *encoder, enum hdmi_infoframe_type type, union hdmi_infoframe *frame) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); u8 buffer[VIDEO_DIP_DATA_SIZE]; int ret; @@ -697,7 +697,7 @@ void intel_read_infoframe(struct intel_encoder *encoder, intel_hdmi_infoframe_enable(type)) == 0) return; - intel_dig_port->read_infoframe(encoder, crtc_state, + dig_port->read_infoframe(encoder, crtc_state, type, buffer, sizeof(buffer)); /* Fill the 'hole' (see big comment above) at position 3 */ @@ -872,8 +872,8 @@ static void g4x_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + struct intel_hdmi *intel_hdmi = &dig_port->hdmi; i915_reg_t reg = VIDEO_DIP_CTL; u32 val = intel_de_read(dev_priv, reg); u32 port = VIDEO_DIP_PORT(encoder->port); @@ -1057,8 +1057,8 @@ static void ibx_set_infoframes(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + struct intel_hdmi *intel_hdmi = &dig_port->hdmi; i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = intel_de_read(dev_priv, reg); u32 port = VIDEO_DIP_PORT(encoder->port); @@ -1275,11 +1275,11 @@ void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) adapter, enable); } -static int intel_hdmi_hdcp_read(struct intel_digital_port *intel_dig_port, +static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port, unsigned int offset, void *buffer, size_t size) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_hdmi *hdmi = &intel_dig_port->hdmi; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_hdmi *hdmi = &dig_port->hdmi; struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915, hdmi->ddc_bus); int ret; @@ -1304,11 +1304,11 @@ static int intel_hdmi_hdcp_read(struct intel_digital_port *intel_dig_port, return ret >= 0 ? -EIO : ret; } -static int intel_hdmi_hdcp_write(struct intel_digital_port *intel_dig_port, +static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port, unsigned int offset, void *buffer, size_t size) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_hdmi *hdmi = &intel_dig_port->hdmi; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_hdmi *hdmi = &dig_port->hdmi; struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915, hdmi->ddc_bus); int ret; @@ -1338,16 +1338,16 @@ static int intel_hdmi_hdcp_write(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *dig_port, u8 *an) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_hdmi *hdmi = &intel_dig_port->hdmi; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_hdmi *hdmi = &dig_port->hdmi; struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915, hdmi->ddc_bus); int ret; - ret = intel_hdmi_hdcp_write(intel_dig_port, DRM_HDCP_DDC_AN, an, + ret = intel_hdmi_hdcp_write(dig_port, DRM_HDCP_DDC_AN, an, DRM_HDCP_AN_LEN); if (ret) { drm_dbg_kms(&i915->drm, "Write An over DDC failed (%d)\n", @@ -1363,13 +1363,13 @@ int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, return 0; } -static int intel_hdmi_hdcp_read_bksv(struct intel_digital_port *intel_dig_port, +static int intel_hdmi_hdcp_read_bksv(struct intel_digital_port *dig_port, u8 *bksv) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BKSV, bksv, + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BKSV, bksv, DRM_HDCP_KSV_LEN); if (ret) drm_dbg_kms(&i915->drm, "Read Bksv over DDC failed (%d)\n", @@ -1378,13 +1378,13 @@ static int intel_hdmi_hdcp_read_bksv(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_read_bstatus(struct intel_digital_port *dig_port, u8 *bstatus) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BSTATUS, + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BSTATUS, bstatus, DRM_HDCP_BSTATUS_LEN); if (ret) drm_dbg_kms(&i915->drm, "Read bstatus over DDC failed (%d)\n", @@ -1393,14 +1393,14 @@ int intel_hdmi_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_repeater_present(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_repeater_present(struct intel_digital_port *dig_port, bool *repeater_present) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; u8 val; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BCAPS, &val, 1); + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BCAPS, &val, 1); if (ret) { drm_dbg_kms(&i915->drm, "Read bcaps over DDC failed (%d)\n", ret); @@ -1411,13 +1411,13 @@ int intel_hdmi_hdcp_repeater_present(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_read_ri_prime(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_read_ri_prime(struct intel_digital_port *dig_port, u8 *ri_prime) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_RI_PRIME, + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_RI_PRIME, ri_prime, DRM_HDCP_RI_LEN); if (ret) drm_dbg_kms(&i915->drm, "Read Ri' over DDC failed (%d)\n", @@ -1426,14 +1426,14 @@ int intel_hdmi_hdcp_read_ri_prime(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_read_ksv_ready(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, bool *ksv_ready) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; u8 val; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BCAPS, &val, 1); + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BCAPS, &val, 1); if (ret) { drm_dbg_kms(&i915->drm, "Read bcaps over DDC failed (%d)\n", ret); @@ -1444,12 +1444,12 @@ int intel_hdmi_hdcp_read_ksv_ready(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_read_ksv_fifo(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, int num_downstream, u8 *ksv_fifo) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_KSV_FIFO, + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_KSV_FIFO, ksv_fifo, num_downstream * DRM_HDCP_KSV_LEN); if (ret) { drm_dbg_kms(&i915->drm, @@ -1460,16 +1460,16 @@ int intel_hdmi_hdcp_read_ksv_fifo(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, int i, u32 *part) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int ret; if (i >= DRM_HDCP_V_PRIME_NUM_PARTS) return -EINVAL; - ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_V_PRIME(i), + ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_V_PRIME(i), part, DRM_HDCP_V_PRIME_PART_LEN); if (ret) drm_dbg_kms(&i915->drm, "Read V'[%d] over DDC failed (%d)\n", @@ -1480,7 +1480,7 @@ int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port, static int kbl_repositioning_enc_en_signal(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_crtc *crtc = connector->base.state->crtc; struct intel_crtc *intel_crtc = container_of(crtc, struct intel_crtc, base); @@ -1494,13 +1494,13 @@ static int kbl_repositioning_enc_en_signal(struct intel_connector *connector) usleep_range(25, 50); } - ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, false); + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, false); if (ret) { drm_err(&dev_priv->drm, "Disable HDCP signalling failed (%d)\n", ret); return ret; } - ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, true); + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, true); if (ret) { drm_err(&dev_priv->drm, "Enable HDCP signalling failed (%d)\n", ret); @@ -1511,10 +1511,10 @@ static int kbl_repositioning_enc_en_signal(struct intel_connector *connector) } static -int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port, bool enable) { - struct intel_hdmi *hdmi = &intel_dig_port->hdmi; + struct intel_hdmi *hdmi = &dig_port->hdmi; struct intel_connector *connector = hdmi->attached_connector; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); int ret; @@ -1522,7 +1522,7 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, if (!enable) usleep_range(6, 60); /* Bspec says >= 6us */ - ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, enable); + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, enable); if (ret) { drm_err(&dev_priv->drm, "%s HDCP signalling failed (%d)\n", enable ? "Enable" : "Disable", ret); @@ -1540,12 +1540,12 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, } static -bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) +bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct intel_connector *connector = - intel_dig_port->hdmi.attached_connector; - enum port port = intel_dig_port->base.port; + dig_port->hdmi.attached_connector; + enum port port = dig_port->base.port; enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder; int ret; union { @@ -1553,7 +1553,7 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) u8 shim[DRM_HDCP_RI_LEN]; } ri; - ret = intel_hdmi_hdcp_read_ri_prime(intel_dig_port, ri.shim); + ret = intel_hdmi_hdcp_read_ri_prime(dig_port, ri.shim); if (ret) return false; @@ -1563,8 +1563,7 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) if (wait_for((intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) & (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC)) == (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) { - drm_err(&i915->drm, - "Ri' mismatch detected, link check failed (%x)\n", + drm_dbg_kms(&i915->drm, "Ri' mismatch detected (%x)\n", intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port))); return false; @@ -1572,6 +1571,20 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) return true; } +static +bool intel_hdmi_hdcp_check_link(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + int retry; + + for (retry = 0; retry < 3; retry++) + if (intel_hdmi_hdcp_check_link_once(dig_port)) + return true; + + drm_err(&i915->drm, "Link check failed\n"); + return false; +} + struct hdcp2_hdmi_msg_timeout { u8 msg_id; u16 timeout; @@ -1586,10 +1599,10 @@ static const struct hdcp2_hdmi_msg_timeout hdcp2_msg_timeout[] = { }; static -int intel_hdmi_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp2_read_rx_status(struct intel_digital_port *dig_port, u8 *rx_status) { - return intel_hdmi_hdcp_read(intel_dig_port, + return intel_hdmi_hdcp_read(dig_port, HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET, rx_status, HDCP_2_2_HDMI_RXSTATUS_LEN); @@ -1615,15 +1628,15 @@ static int get_hdcp2_msg_timeout(u8 msg_id, bool is_paired) } static int -hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port, +hdcp2_detect_msg_availability(struct intel_digital_port *dig_port, u8 msg_id, bool *msg_ready, ssize_t *msg_sz) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN]; int ret; - ret = intel_hdmi_hdcp2_read_rx_status(intel_dig_port, rx_status); + ret = intel_hdmi_hdcp2_read_rx_status(dig_port, rx_status); if (ret < 0) { drm_dbg_kms(&i915->drm, "rx_status read failed. Err %d\n", ret); @@ -1643,10 +1656,10 @@ hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port, } static ssize_t -intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port, +intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *dig_port, u8 msg_id, bool paired) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); bool msg_ready = false; int timeout, ret; ssize_t msg_sz = 0; @@ -1655,7 +1668,7 @@ intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port, if (timeout < 0) return timeout; - ret = __wait_for(ret = hdcp2_detect_msg_availability(intel_dig_port, + ret = __wait_for(ret = hdcp2_detect_msg_availability(dig_port, msg_id, &msg_ready, &msg_sz), !ret && msg_ready && msg_sz, timeout * 1000, @@ -1668,26 +1681,26 @@ intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *dig_port, void *buf, size_t size) { unsigned int offset; offset = HDCP_2_2_HDMI_REG_WR_MSG_OFFSET; - return intel_hdmi_hdcp_write(intel_dig_port, offset, buf, size); + return intel_hdmi_hdcp_write(dig_port, offset, buf, size); } static -int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *dig_port, u8 msg_id, void *buf, size_t size) { - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_hdmi *hdmi = &intel_dig_port->hdmi; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_hdmi *hdmi = &dig_port->hdmi; struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp; unsigned int offset; ssize_t ret; - ret = intel_hdmi_hdcp2_wait_for_msg(intel_dig_port, msg_id, + ret = intel_hdmi_hdcp2_wait_for_msg(dig_port, msg_id, hdcp->is_paired); if (ret < 0) return ret; @@ -1704,7 +1717,7 @@ int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, } offset = HDCP_2_2_HDMI_REG_RD_MSG_OFFSET; - ret = intel_hdmi_hdcp_read(intel_dig_port, offset, buf, ret); + ret = intel_hdmi_hdcp_read(dig_port, offset, buf, ret); if (ret) drm_dbg_kms(&i915->drm, "Failed to read msg_id: %d(%zd)\n", msg_id, ret); @@ -1713,12 +1726,12 @@ int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, } static -int intel_hdmi_hdcp2_check_link(struct intel_digital_port *intel_dig_port) +int intel_hdmi_hdcp2_check_link(struct intel_digital_port *dig_port) { u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN]; int ret; - ret = intel_hdmi_hdcp2_read_rx_status(intel_dig_port, rx_status); + ret = intel_hdmi_hdcp2_read_rx_status(dig_port, rx_status); if (ret) return ret; @@ -1735,14 +1748,14 @@ int intel_hdmi_hdcp2_check_link(struct intel_digital_port *intel_dig_port) } static -int intel_hdmi_hdcp2_capable(struct intel_digital_port *intel_dig_port, +int intel_hdmi_hdcp2_capable(struct intel_digital_port *dig_port, bool *capable) { u8 hdcp2_version; int ret; *capable = false; - ret = intel_hdmi_hdcp_read(intel_dig_port, HDCP_2_2_HDMI_REG_VER_OFFSET, + ret = intel_hdmi_hdcp_read(dig_port, HDCP_2_2_HDMI_REG_VER_OFFSET, &hdcp2_version, sizeof(hdcp2_version)); if (!ret && hdcp2_version & HDCP_2_2_HDMI_SUPPORT_MASK) *capable = true; @@ -2050,7 +2063,7 @@ static void intel_disable_hdmi(struct intel_atomic_state *state, struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - struct intel_digital_port *intel_dig_port = + struct intel_digital_port *dig_port = hdmi_to_dig_port(intel_hdmi); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); u32 temp; @@ -2094,7 +2107,7 @@ static void intel_disable_hdmi(struct intel_atomic_state *state, intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } - intel_dig_port->set_infoframes(encoder, + dig_port->set_infoframes(encoder, false, old_crtc_state, old_conn_state); @@ -2229,8 +2242,11 @@ intel_hdmi_mode_valid(struct drm_connector *connector, if (clock > max_dotclk) return MODE_CLOCK_HIGH; - if (mode->flags & DRM_MODE_FLAG_DBLCLK) + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { + if (!has_hdmi_sink) + return MODE_CLOCK_LOW; clock *= 2; + } if (drm_mode_is_420_only(&connector->display_info, mode)) clock /= 2; @@ -2415,8 +2431,8 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder, return 0; } -static bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) +bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { const struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); @@ -2709,12 +2725,12 @@ static void intel_hdmi_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct intel_digital_port *intel_dig_port = + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); intel_hdmi_prepare(encoder, pipe_config); - intel_dig_port->set_infoframes(encoder, + dig_port->set_infoframes(encoder, pipe_config->has_infoframe, pipe_config, conn_state); } @@ -2724,7 +2740,7 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); vlv_phy_pre_encoder_enable(encoder, pipe_config); @@ -2733,13 +2749,13 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state, vlv_set_phy_signal_level(encoder, 0x2b245f5f, 0x00002000, 0x5578b83a, 0x2b247878); - dport->set_infoframes(encoder, + dig_port->set_infoframes(encoder, pipe_config->has_infoframe, pipe_config, conn_state); g4x_enable_hdmi(state, encoder, pipe_config, conn_state); - vlv_wait_port_ready(dev_priv, dport, 0x0); + vlv_wait_port_ready(dev_priv, dig_port, 0x0); } static void vlv_hdmi_pre_pll_enable(struct intel_atomic_state *state, @@ -2800,7 +2816,7 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct intel_digital_port *dport = enc_to_dig_port(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -2810,13 +2826,13 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state, /* Use 800mV-0dB */ chv_set_phy_signal_level(encoder, 128, 102, false); - dport->set_infoframes(encoder, + dig_port->set_infoframes(encoder, pipe_config->has_infoframe, pipe_config, conn_state); g4x_enable_hdmi(state, encoder, pipe_config, conn_state); - vlv_wait_port_ready(dev_priv, dport, 0x0); + vlv_wait_port_ready(dev_priv, dig_port, 0x0); /* Second common lane will stay alive on its own now */ chv_phy_release_cl2_override(encoder); @@ -2867,19 +2883,13 @@ intel_hdmi_connector_register(struct drm_connector *connector) return ret; } -static void intel_hdmi_destroy(struct drm_connector *connector) +static void intel_hdmi_connector_unregister(struct drm_connector *connector) { struct cec_notifier *n = intel_attached_hdmi(to_intel_connector(connector))->cec_notifier; cec_notifier_conn_unregister(n); - intel_connector_destroy(connector); -} - -static void intel_hdmi_connector_unregister(struct drm_connector *connector) -{ intel_hdmi_remove_i2c_symlink(connector); - intel_connector_unregister(connector); } @@ -2891,7 +2901,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { .atomic_set_property = intel_digital_connector_atomic_set_property, .late_register = intel_hdmi_connector_register, .early_unregister = intel_hdmi_connector_unregister, - .destroy = intel_hdmi_destroy, + .destroy = intel_connector_destroy, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_duplicate_state = intel_digital_connector_duplicate_state, }; @@ -2910,7 +2920,7 @@ static void intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_digital_port *intel_dig_port = + struct intel_digital_port *dig_port = hdmi_to_dig_port(intel_hdmi); intel_attach_force_audio_property(connector); @@ -2922,7 +2932,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c * ToDo: This needs to be extended for LSPCON implementation * as well. Will be implemented separately. */ - if (!intel_dig_port->lspcon.active) + if (!dig_port->lspcon.active) intel_attach_colorspace_property(connector); drm_connector_attach_content_type_property(connector); @@ -3082,6 +3092,24 @@ static u8 mcc_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) return ddc_pin; } +static u8 rkl_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +{ + enum phy phy = intel_port_to_phy(dev_priv, port); + + WARN_ON(port == PORT_C); + + /* + * Pin mapping for RKL depends on which PCH is present. With TGP, the + * final two outputs use type-c pins, even though they're actually + * combo outputs. With CMP, the traditional DDI A-D pins are used for + * all outputs. + */ + if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && phy >= PHY_C) + return GMBUS_PIN_9_TC1_ICP + phy - PHY_C; + + return GMBUS_PIN_1_BXT + phy; +} + static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) { @@ -3119,7 +3147,9 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) return ddc_pin; } - if (HAS_PCH_MCC(dev_priv)) + if (IS_ROCKETLAKE(dev_priv)) + ddc_pin = rkl_port_to_ddc_pin(dev_priv, port); + else if (HAS_PCH_MCC(dev_priv)) ddc_pin = mcc_port_to_ddc_pin(dev_priv, port); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) ddc_pin = icl_port_to_ddc_pin(dev_priv, port); @@ -3139,52 +3169,52 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) return ddc_pin; } -void intel_infoframe_init(struct intel_digital_port *intel_dig_port) +void intel_infoframe_init(struct intel_digital_port *dig_port) { struct drm_i915_private *dev_priv = - to_i915(intel_dig_port->base.base.dev); + to_i915(dig_port->base.base.dev); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - intel_dig_port->write_infoframe = vlv_write_infoframe; - intel_dig_port->read_infoframe = vlv_read_infoframe; - intel_dig_port->set_infoframes = vlv_set_infoframes; - intel_dig_port->infoframes_enabled = vlv_infoframes_enabled; + dig_port->write_infoframe = vlv_write_infoframe; + dig_port->read_infoframe = vlv_read_infoframe; + dig_port->set_infoframes = vlv_set_infoframes; + dig_port->infoframes_enabled = vlv_infoframes_enabled; } else if (IS_G4X(dev_priv)) { - intel_dig_port->write_infoframe = g4x_write_infoframe; - intel_dig_port->read_infoframe = g4x_read_infoframe; - intel_dig_port->set_infoframes = g4x_set_infoframes; - intel_dig_port->infoframes_enabled = g4x_infoframes_enabled; + dig_port->write_infoframe = g4x_write_infoframe; + dig_port->read_infoframe = g4x_read_infoframe; + dig_port->set_infoframes = g4x_set_infoframes; + dig_port->infoframes_enabled = g4x_infoframes_enabled; } else if (HAS_DDI(dev_priv)) { - if (intel_dig_port->lspcon.active) { - intel_dig_port->write_infoframe = lspcon_write_infoframe; - intel_dig_port->read_infoframe = lspcon_read_infoframe; - intel_dig_port->set_infoframes = lspcon_set_infoframes; - intel_dig_port->infoframes_enabled = lspcon_infoframes_enabled; + if (dig_port->lspcon.active) { + dig_port->write_infoframe = lspcon_write_infoframe; + dig_port->read_infoframe = lspcon_read_infoframe; + dig_port->set_infoframes = lspcon_set_infoframes; + dig_port->infoframes_enabled = lspcon_infoframes_enabled; } else { - intel_dig_port->write_infoframe = hsw_write_infoframe; - intel_dig_port->read_infoframe = hsw_read_infoframe; - intel_dig_port->set_infoframes = hsw_set_infoframes; - intel_dig_port->infoframes_enabled = hsw_infoframes_enabled; + dig_port->write_infoframe = hsw_write_infoframe; + dig_port->read_infoframe = hsw_read_infoframe; + dig_port->set_infoframes = hsw_set_infoframes; + dig_port->infoframes_enabled = hsw_infoframes_enabled; } } else if (HAS_PCH_IBX(dev_priv)) { - intel_dig_port->write_infoframe = ibx_write_infoframe; - intel_dig_port->read_infoframe = ibx_read_infoframe; - intel_dig_port->set_infoframes = ibx_set_infoframes; - intel_dig_port->infoframes_enabled = ibx_infoframes_enabled; + dig_port->write_infoframe = ibx_write_infoframe; + dig_port->read_infoframe = ibx_read_infoframe; + dig_port->set_infoframes = ibx_set_infoframes; + dig_port->infoframes_enabled = ibx_infoframes_enabled; } else { - intel_dig_port->write_infoframe = cpt_write_infoframe; - intel_dig_port->read_infoframe = cpt_read_infoframe; - intel_dig_port->set_infoframes = cpt_set_infoframes; - intel_dig_port->infoframes_enabled = cpt_infoframes_enabled; + dig_port->write_infoframe = cpt_write_infoframe; + dig_port->read_infoframe = cpt_read_infoframe; + dig_port->set_infoframes = cpt_set_infoframes; + dig_port->infoframes_enabled = cpt_infoframes_enabled; } } -void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, +void intel_hdmi_init_connector(struct intel_digital_port *dig_port, struct intel_connector *intel_connector) { struct drm_connector *connector = &intel_connector->base; - struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; - struct intel_encoder *intel_encoder = &intel_dig_port->base; + struct intel_hdmi *intel_hdmi = &dig_port->hdmi; + struct intel_encoder *intel_encoder = &dig_port->base; struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct i2c_adapter *ddc; @@ -3198,9 +3228,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, if (INTEL_GEN(dev_priv) < 12 && drm_WARN_ON(dev, port == PORT_A)) return; - if (drm_WARN(dev, intel_dig_port->max_lanes < 4, + if (drm_WARN(dev, dig_port->max_lanes < 4, "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n", - intel_dig_port->max_lanes, intel_encoder->base.base.id, + dig_port->max_lanes, intel_encoder->base.base.id, intel_encoder->base.name)) return; @@ -3289,21 +3319,21 @@ intel_hdmi_hotplug(struct intel_encoder *encoder, void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, enum port port) { - struct intel_digital_port *intel_dig_port; + struct intel_digital_port *dig_port; struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); - if (!intel_dig_port) + dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); + if (!dig_port) return; intel_connector = intel_connector_alloc(); if (!intel_connector) { - kfree(intel_dig_port); + kfree(dig_port); return; } - intel_encoder = &intel_dig_port->base; + intel_encoder = &dig_port->base; drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS, @@ -3360,12 +3390,12 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, if (IS_G4X(dev_priv)) intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; - intel_dig_port->hdmi.hdmi_reg = hdmi_reg; - intel_dig_port->dp.output_reg = INVALID_MMIO_REG; - intel_dig_port->max_lanes = 4; + dig_port->hdmi.hdmi_reg = hdmi_reg; + dig_port->dp.output_reg = INVALID_MMIO_REG; + dig_port->max_lanes = 4; - intel_infoframe_init(intel_dig_port); + intel_infoframe_init(dig_port); - intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); - intel_hdmi_init_connector(intel_dig_port, intel_connector); + dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); + intel_hdmi_init_connector(dig_port, intel_connector); } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 8ff1f76a63df..5b348dcab77a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -25,7 +25,7 @@ enum port; void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, enum port port); -void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, +void intel_hdmi_init_connector(struct intel_digital_port *dig_port, struct intel_connector *intel_connector); struct intel_hdmi *enc_to_intel_hdmi(struct intel_encoder *encoder); int intel_hdmi_compute_config(struct intel_encoder *encoder, @@ -36,7 +36,7 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, bool high_tmds_clock_ratio, bool scrambling); void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); -void intel_infoframe_init(struct intel_digital_port *intel_dig_port); +void intel_infoframe_init(struct intel_digital_port *dig_port); u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); u32 intel_hdmi_infoframe_enable(unsigned int type); @@ -46,5 +46,7 @@ void intel_read_infoframe(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, enum hdmi_infoframe_type type, union hdmi_infoframe *frame); +bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); #endif /* __INTEL_HDMI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 252090ccecc4..3f1d7b804a66 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -89,6 +89,15 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, { enum phy phy = intel_port_to_phy(dev_priv, port); + /* + * RKL + TGP PCH is a special case; we effectively choose the hpd_pin + * based on the DDI rather than the PHY (i.e., the last two outputs + * shold be HPD_PORT_{D,E} rather than {C,D}. Note that this differs + * from the behavior of both TGL+TGP and RKL+CMP. + */ + if (IS_ROCKETLAKE(dev_priv) && HAS_PCH_TGP(dev_priv)) + return HPD_PORT_A + port - PORT_A; + switch (phy) { case PHY_F: return IS_CNL_WITH_PORT_F(dev_priv) ? HPD_PORT_E : HPD_PORT_F; diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 6ff7b226f0a1..b781bf469644 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -550,11 +550,11 @@ void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon) lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); } -bool lspcon_init(struct intel_digital_port *intel_dig_port) +bool lspcon_init(struct intel_digital_port *dig_port) { - struct intel_dp *dp = &intel_dig_port->dp; - struct intel_lspcon *lspcon = &intel_dig_port->lspcon; - struct drm_device *dev = intel_dig_port->base.base.dev; + struct intel_dp *dp = &dig_port->dp; + struct intel_lspcon *lspcon = &dig_port->lspcon; + struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_connector *connector = &dp->attached_connector->base; diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h index 37cfddf8a9c5..1cffe8a42a08 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.h +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h @@ -15,7 +15,7 @@ struct intel_digital_port; struct intel_encoder; struct intel_lspcon; -bool lspcon_init(struct intel_digital_port *intel_dig_port); +bool lspcon_init(struct intel_digital_port *dig_port); void lspcon_resume(struct intel_lspcon *lspcon); void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); void lspcon_write_infoframe(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 872f2a489339..1888611244db 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -784,8 +784,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) struct drm_i915_private *dev_priv = to_i915(dev); /* use the module option value if specified */ - if (i915_modparams.lvds_channel_mode > 0) - return i915_modparams.lvds_channel_mode == 2; + if (dev_priv->params.lvds_channel_mode > 0) + return dev_priv->params.lvds_channel_mode == 2; /* single channel LVDS is limited to 112 MHz */ if (lvds_encoder->attached_connector->panel.fixed_mode->clock > 112999) diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index cc6b00959586..de995362f428 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -801,7 +801,7 @@ static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv) { struct intel_opregion *opregion = &dev_priv->opregion; const struct firmware *fw = NULL; - const char *name = i915_modparams.vbt_firmware; + const char *name = dev_priv->params.vbt_firmware; int ret; if (!name || !*name) diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 66711e62fa71..52b4f6193b4c 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -100,12 +100,15 @@ #define CLK_RGB24_MASK 0x0 #define CLK_RGB16_MASK 0x070307 #define CLK_RGB15_MASK 0x070707 -#define CLK_RGB8I_MASK 0xffffff +#define RGB30_TO_COLORKEY(c) \ + ((((c) & 0x3fc00000) >> 6) | (((c) & 0x000ff000) >> 4) | (((c) & 0x000003fc) >> 2)) #define RGB16_TO_COLORKEY(c) \ - (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) + ((((c) & 0xf800) << 8) | (((c) & 0x07e0) << 5) | (((c) & 0x001f) << 3)) #define RGB15_TO_COLORKEY(c) \ - (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) + ((((c) & 0x7c00) << 9) | (((c) & 0x03e0) << 6) | (((c) & 0x001f) << 3)) +#define RGB8I_TO_COLORKEY(c) \ + ((((c) & 0xff) << 16) | (((c) & 0xff) << 8) | (((c) & 0xff) << 0)) /* overlay flip addr flag */ #define OFC_UPDATE 0x1 @@ -682,8 +685,8 @@ static void update_colorkey(struct intel_overlay *overlay, switch (format) { case DRM_FORMAT_C8: - key = 0; - flags |= CLK_RGB8I_MASK; + key = RGB8I_TO_COLORKEY(key); + flags |= CLK_RGB24_MASK; break; case DRM_FORMAT_XRGB1555: key = RGB15_TO_COLORKEY(key); @@ -693,6 +696,11 @@ static void update_colorkey(struct intel_overlay *overlay, key = RGB16_TO_COLORKEY(key); flags |= CLK_RGB16_MASK; break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + key = RGB30_TO_COLORKEY(key); + flags |= CLK_RGB24_MASK; + break; default: flags |= CLK_RGB24_MASK; break; @@ -777,9 +785,15 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB); if (!overlay->active) { - u32 oconfig; - - oconfig = OCONF_CC_OUT_8BIT; + const struct intel_crtc_state *crtc_state = + overlay->crtc->config; + u32 oconfig = 0; + + if (crtc_state->gamma_enable && + crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) + oconfig |= OCONF_CC_OUT_8BIT; + if (crtc_state->gamma_enable) + oconfig |= OCONF_GAMMA2_ENABLE; if (IS_GEN(dev_priv, 4)) oconfig |= OCONF_CSC_MODE_BT709; oconfig |= pipe == 0 ? diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3c5056dbf607..aaed9eb3b56c 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -521,10 +521,10 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector, drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0); - if (i915_modparams.invert_brightness < 0) + if (dev_priv->params.invert_brightness < 0) return val; - if (i915_modparams.invert_brightness > 0 || + if (dev_priv->params.invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { return panel->backlight.max - val + panel->backlight.min; } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index b7a2c102648a..bf9e320c547d 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -83,7 +83,7 @@ static bool psr_global_enabled(struct drm_i915_private *i915) { switch (i915->psr.debug & I915_PSR_DEBUG_MODE_MASK) { case I915_PSR_DEBUG_DEFAULT: - return i915_modparams.enable_psr; + return i915->params.enable_psr; case I915_PSR_DEBUG_DISABLE: return false; default: @@ -426,6 +426,12 @@ static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 11) val |= EDP_PSR_TP4_TIME_0US; + if (dev_priv->params.psr_safest_params) { + val |= EDP_PSR_TP1_TIME_2500us; + val |= EDP_PSR_TP2_TP3_TIME_2500us; + goto check_tp3_sel; + } + if (dev_priv->vbt.psr.tp1_wakeup_time_us == 0) val |= EDP_PSR_TP1_TIME_0us; else if (dev_priv->vbt.psr.tp1_wakeup_time_us <= 100) @@ -444,6 +450,7 @@ static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) else val |= EDP_PSR_TP2_TP3_TIME_2500us; +check_tp3_sel: if (intel_dp_source_supports_hbr2(intel_dp) && drm_dp_tps3_supported(intel_dp->dpcd)) val |= EDP_PSR_TP1_TP3_SEL; @@ -495,18 +502,13 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp) intel_de_write(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder), val); } -static void hsw_activate_psr2(struct intel_dp *intel_dp) +static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u32 val; - - val = psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT; - - val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) - val |= EDP_Y_COORDINATE_ENABLE; + u32 val = 0; - val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); + if (dev_priv->params.psr_safest_params) + return EDP_PSR2_TP2_TIME_2500us; if (dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us >= 0 && dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 50) @@ -518,6 +520,39 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) else val |= EDP_PSR2_TP2_TIME_2500us; + return val; +} + +static void hsw_activate_psr2(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + u32 val; + + val = psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT; + + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) + val |= EDP_Y_COORDINATE_ENABLE; + + val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); + val |= intel_psr2_get_tp_time(intel_dp); + + if (INTEL_GEN(dev_priv) >= 12) { + /* + * TODO: 7 lines of IO_BUFFER_WAKE and FAST_WAKE are default + * values from BSpec. In order to setting an optimal power + * consumption, lower than 4k resoluition mode needs to decrese + * IO_BUFFER_WAKE and FAST_WAKE. And higher than 4K resolution + * mode needs to increase IO_BUFFER_WAKE and FAST_WAKE. + */ + val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; + val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(7); + val |= TGL_EDP_PSR2_FAST_WAKE(7); + } else if (INTEL_GEN(dev_priv) >= 9) { + val |= EDP_PSR2_IO_BUFFER_WAKE(7); + val |= EDP_PSR2_FAST_WAKE(7); + } + /* * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is * recommending keep this bit unset while PSR2 is enabled. @@ -657,6 +692,12 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } + if (crtc_state->crc_enabled) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled because it would inhibit pipe CRC calculation\n"); + return false; + } + if (INTEL_GEN(dev_priv) >= 12) { psr_max_h = 5120; psr_max_v = 3200; @@ -671,14 +712,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, max_bpp = 24; } - if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) { - drm_dbg_kms(&dev_priv->drm, - "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n", - crtc_hdisplay, crtc_vdisplay, - psr_max_h, psr_max_v); - return false; - } - if (crtc_state->pipe_bpp > max_bpp) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, pipe bpp %d > max supported %d\n", @@ -699,9 +732,26 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - if (crtc_state->crc_enabled) { + /* + * Some platforms lack PSR2 HW tracking and instead require manual + * tracking by software. In this case, the driver is required to track + * the areas that need updates and program hardware to send selective + * updates. + * + * So until the software tracking is implemented, PSR2 needs to be + * disabled for platforms without PSR2 HW tracking. + */ + if (!HAS_PSR_HW_TRACKING(dev_priv)) { drm_dbg_kms(&dev_priv->drm, - "PSR2 not enabled because it would inhibit pipe CRC calculation\n"); + "No PSR2 HW tracking in the platform\n"); + return false; + } + + if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n", + crtc_hdisplay, crtc_vdisplay, + psr_max_h, psr_max_v); return false; } @@ -855,8 +905,8 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, const struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = dev_priv->psr.dp; - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *encoder = &intel_dig_port->base; + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &dig_port->base; u32 val; drm_WARN_ON(&dev_priv->drm, dev_priv->psr.enabled); @@ -1450,9 +1500,9 @@ void intel_psr_init(struct drm_i915_private *dev_priv) */ dev_priv->hsw_psr_mmio_adjust = _SRD_CTL_EDP - _HSW_EDP_PSR_BASE; - if (i915_modparams.enable_psr == -1) + if (dev_priv->params.enable_psr == -1) if (INTEL_GEN(dev_priv) < 9 || !dev_priv->vbt.psr.enable) - i915_modparams.enable_psr = 0; + dev_priv->params.enable_psr = 0; /* Set link_standby x link_off defaults */ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index bc6c26818e15..2da4388e1540 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -94,6 +94,8 @@ struct intel_sdvo { */ struct intel_sdvo_caps caps; + u8 colorimetry_cap; + /* Pixel clock limitations reported by the SDVO device, in kHz */ int pixel_clock_min, pixel_clock_max; @@ -411,6 +413,7 @@ static const char *sdvo_cmd_name(u8 cmd) static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, const void *args, int args_len) { + struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); const char *cmd_name; int i, pos = 0; char buffer[64]; @@ -431,7 +434,7 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, else BUF_PRINT("(%02X)", cmd); - WARN_ON(pos >= sizeof(buffer) - 1); + drm_WARN_ON(&dev_priv->drm, pos >= sizeof(buffer) - 1); #undef BUF_PRINT DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer); @@ -533,6 +536,7 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, void *response, int response_len) { + struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); const char *cmd_status; u8 retry = 15; /* 5 quick checks, followed by 10 long checks */ u8 status; @@ -597,7 +601,7 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, BUF_PRINT(" %02X", ((u8 *)response)[i]); } - WARN_ON(pos >= sizeof(buffer) - 1); + drm_WARN_ON(&dev_priv->drm, pos >= sizeof(buffer) - 1); #undef BUF_PRINT DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer); @@ -940,6 +944,13 @@ static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo, return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1); } +static bool intel_sdvo_set_pixel_replication(struct intel_sdvo *intel_sdvo, + u8 pixel_repeat) +{ + return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_PIXEL_REPLI, + &pixel_repeat, 1); +} + static bool intel_sdvo_set_audio_state(struct intel_sdvo *intel_sdvo, u8 audio_state) { @@ -1081,6 +1092,7 @@ static bool intel_sdvo_compute_avi_infoframe(struct intel_sdvo *intel_sdvo, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -1106,7 +1118,7 @@ static bool intel_sdvo_compute_avi_infoframe(struct intel_sdvo *intel_sdvo, HDMI_QUANTIZATION_RANGE_FULL); ret = hdmi_avi_infoframe_check(frame); - if (WARN_ON(ret)) + if (drm_WARN_ON(&dev_priv->drm, ret)) return false; return true; @@ -1115,6 +1127,7 @@ static bool intel_sdvo_compute_avi_infoframe(struct intel_sdvo *intel_sdvo, static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, const struct intel_crtc_state *crtc_state) { + struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); u8 sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; const union hdmi_infoframe *frame = &crtc_state->infoframes.avi; ssize_t len; @@ -1123,11 +1136,12 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI)) == 0) return true; - if (WARN_ON(frame->any.type != HDMI_INFOFRAME_TYPE_AVI)) + if (drm_WARN_ON(&dev_priv->drm, + frame->any.type != HDMI_INFOFRAME_TYPE_AVI)) return false; len = hdmi_infoframe_pack_only(frame, sdvo_data, sizeof(sdvo_data)); - if (WARN_ON(len < 0)) + if (drm_WARN_ON(&dev_priv->drm, len < 0)) return false; return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, @@ -1237,6 +1251,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config) { + struct drm_i915_private *dev_priv = to_i915(pipe_config->uapi.crtc->dev); unsigned dotclock = pipe_config->port_clock; struct dpll *clock = &pipe_config->dpll; @@ -1257,7 +1272,8 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config) clock->m1 = 12; clock->m2 = 8; } else { - WARN(1, "SDVO TV clock out of range: %i\n", dotclock); + drm_WARN(&dev_priv->drm, 1, + "SDVO TV clock out of range: %i\n", dotclock); } pipe_config->clock_set = true; @@ -1270,6 +1286,18 @@ static bool intel_has_hdmi_sink(struct intel_sdvo *sdvo, READ_ONCE(to_intel_digital_connector_state(conn_state)->force_audio) != HDMI_AUDIO_OFF_DVI; } +static bool intel_sdvo_limited_color_range(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); + + if ((intel_sdvo->colorimetry_cap & SDVO_COLORIMETRY_RGB220) == 0) + return false; + + return intel_hdmi_limited_color_range(crtc_state, conn_state); +} + static int intel_sdvo_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -1335,21 +1363,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, intel_sdvo_state->base.force_audio == HDMI_AUDIO_ON; } - if (intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { - /* - * See CEA-861-E - 5.1 Default Encoding Parameters - * - * FIXME: This bit is only valid when using TMDS encoding and 8 - * bit per color mode. - */ - if (pipe_config->has_hdmi_sink && - drm_match_cea_mode(adjusted_mode) > 1) - pipe_config->limited_color_range = true; - } else { - if (pipe_config->has_hdmi_sink && - intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED) - pipe_config->limited_color_range = true; - } + pipe_config->limited_color_range = + intel_sdvo_limited_color_range(encoder, pipe_config, + conn_state); /* Clock computation needs to happen after pixel multiplier. */ if (IS_TV(intel_sdvo_connector)) @@ -1488,8 +1504,13 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state, if (crtc_state->has_hdmi_sink) { intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI); intel_sdvo_set_colorimetry(intel_sdvo, + crtc_state->limited_color_range ? + SDVO_COLORIMETRY_RGB220 : SDVO_COLORIMETRY_RGB256); intel_sdvo_set_avi_infoframe(intel_sdvo, crtc_state); + intel_sdvo_set_pixel_replication(intel_sdvo, + !!(adjusted_mode->flags & + DRM_MODE_FLAG_DBLCLK)); } else intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI); @@ -1523,8 +1544,6 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state, /* The real mode polarity is set by the SDVO commands, using * struct intel_sdvo_dtd. */ sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; - if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range) - sdvox |= HDMI_COLOR_RANGE_16_235; if (INTEL_GEN(dev_priv) < 5) sdvox |= SDVO_BORDER_ENABLE; } else { @@ -1682,8 +1701,11 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, "SDVO pixel multiplier mismatch, port: %i, encoder: %i\n", pipe_config->pixel_multiplier, encoder_pixel_multiplier); - if (sdvox & HDMI_COLOR_RANGE_16_235) - pipe_config->limited_color_range = true; + if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_COLORIMETRY, + &val, 1)) { + if (val == SDVO_COLORIMETRY_RGB220) + pipe_config->limited_color_range = true; + } if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT, &val, 1)) { @@ -1843,17 +1865,26 @@ intel_sdvo_mode_valid(struct drm_connector *connector, struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + bool has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, connector->state); + int clock = mode->clock; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; - if (intel_sdvo->pixel_clock_min > mode->clock) - return MODE_CLOCK_LOW; - if (intel_sdvo->pixel_clock_max < mode->clock) + if (clock > max_dotclk) return MODE_CLOCK_HIGH; - if (mode->clock > max_dotclk) + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { + if (!has_hdmi_sink) + return MODE_CLOCK_LOW; + clock *= 2; + } + + if (intel_sdvo->pixel_clock_min > clock) + return MODE_CLOCK_LOW; + + if (intel_sdvo->pixel_clock_max < clock) return MODE_CLOCK_HIGH; if (IS_LVDS(intel_sdvo_connector)) { @@ -1907,6 +1938,17 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in return true; } +static u8 intel_sdvo_get_colorimetry_cap(struct intel_sdvo *intel_sdvo) +{ + u8 cap; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_COLORIMETRY_CAP, + &cap, sizeof(cap))) + return SDVO_COLORIMETRY_RGB256; + + return cap; +} + static u16 intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) { struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); @@ -2093,8 +2135,9 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) return ret; } -static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) +static int intel_sdvo_get_ddc_modes(struct drm_connector *connector) { + int num_modes = 0; struct edid *edid; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", @@ -2109,18 +2152,19 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) * DDC fails, check to see if the analog output is disconnected, in * which case we'll look there for the digital DDC data. */ - if (edid == NULL) + if (!edid) edid = intel_sdvo_get_analog_edid(connector); - if (edid != NULL) { - if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), - edid)) { - drm_connector_update_edid_property(connector, edid); - drm_add_edid_modes(connector, edid); - } + if (!edid) + return 0; - kfree(edid); - } + if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), + edid)) + num_modes += intel_connector_update_modes(connector, edid); + + kfree(edid); + + return num_modes; } /* @@ -2188,12 +2232,13 @@ static const struct drm_display_mode sdvo_tv_modes[] = { DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, }; -static void intel_sdvo_get_tv_modes(struct drm_connector *connector) +static int intel_sdvo_get_tv_modes(struct drm_connector *connector) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector)); const struct drm_connector_state *conn_state = connector->state; struct intel_sdvo_sdtv_resolution_request tv_res; u32 reply = 0, format_map = 0; + int num_modes = 0; int i; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", @@ -2208,31 +2253,37 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) min(sizeof(format_map), sizeof(struct intel_sdvo_sdtv_resolution_request))); if (!intel_sdvo_set_target_output(intel_sdvo, intel_sdvo->attached_output)) - return; + return 0; BUILD_BUG_ON(sizeof(tv_res) != 3); if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, &tv_res, sizeof(tv_res))) - return; + return 0; if (!intel_sdvo_read_response(intel_sdvo, &reply, 3)) - return; + return 0; - for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) + for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) { if (reply & (1 << i)) { struct drm_display_mode *nmode; nmode = drm_mode_duplicate(connector->dev, &sdvo_tv_modes[i]); - if (nmode) + if (nmode) { drm_mode_probed_add(connector, nmode); + num_modes++; + } } + } + + return num_modes; } -static void intel_sdvo_get_lvds_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); struct drm_display_mode *newmode; + int num_modes = 0; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); @@ -2249,6 +2300,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) newmode->type = (DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER); drm_mode_probed_add(connector, newmode); + num_modes++; } } @@ -2257,7 +2309,9 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) * Assume that the preferred modes are * arranged in priority order. */ - intel_ddc_get_modes(connector, &intel_sdvo->ddc); + num_modes += intel_ddc_get_modes(connector, &intel_sdvo->ddc); + + return num_modes; } static int intel_sdvo_get_modes(struct drm_connector *connector) @@ -2265,13 +2319,11 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); if (IS_TV(intel_sdvo_connector)) - intel_sdvo_get_tv_modes(connector); + return intel_sdvo_get_tv_modes(connector); else if (IS_LVDS(intel_sdvo_connector)) - intel_sdvo_get_lvds_modes(connector); + return intel_sdvo_get_lvds_modes(connector); else - intel_sdvo_get_ddc_modes(connector); - - return !list_empty(&connector->probed_modes); + return intel_sdvo_get_ddc_modes(connector); } static int @@ -2293,7 +2345,7 @@ intel_sdvo_connector_atomic_get_property(struct drm_connector *connector, return 0; } - WARN_ON(1); + drm_WARN_ON(connector->dev, 1); *val = 0; } else if (property == intel_sdvo_connector->top || property == intel_sdvo_connector->bottom) @@ -2662,12 +2714,9 @@ static void intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.base.dev); - intel_attach_force_audio_property(&connector->base.base); - if (INTEL_GEN(dev_priv) >= 4 && IS_MOBILE(dev_priv)) { + if (intel_sdvo->colorimetry_cap & SDVO_COLORIMETRY_RGB220) intel_attach_broadcast_rgb_property(&connector->base.base); - } intel_attach_aspect_ratio_property(&connector->base.base); } @@ -3308,6 +3357,9 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; + intel_sdvo->colorimetry_cap = + intel_sdvo_get_colorimetry_cap(intel_sdvo); + if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { drm_dbg_kms(&dev_priv->drm, diff --git a/drivers/gpu/drm/i915/display/intel_sdvo_regs.h b/drivers/gpu/drm/i915/display/intel_sdvo_regs.h index 13b9a8e257bb..74dc6c042b6e 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/display/intel_sdvo_regs.h @@ -705,10 +705,10 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_GET_PIXEL_REPLI 0x8c #define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d #define SDVO_CMD_SET_COLORIMETRY 0x8e - #define SDVO_COLORIMETRY_RGB256 0x0 - #define SDVO_COLORIMETRY_RGB220 0x1 - #define SDVO_COLORIMETRY_YCrCb422 0x3 - #define SDVO_COLORIMETRY_YCrCb444 0x4 + #define SDVO_COLORIMETRY_RGB256 (1 << 0) + #define SDVO_COLORIMETRY_RGB220 (1 << 1) + #define SDVO_COLORIMETRY_YCrCb422 (1 << 2) + #define SDVO_COLORIMETRY_YCrCb444 (1 << 3) #define SDVO_CMD_GET_COLORIMETRY 0x8f #define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90 #define SDVO_CMD_SET_AUDIO_STAT 0x91 diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 0000ec7055f7..d03860fef2d7 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -34,6 +34,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_color_mgmt.h> #include <drm/drm_crtc.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> #include <drm/drm_rect.h> @@ -333,6 +334,21 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) return 0; } +static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915) +{ + if (IS_ROCKETLAKE(i915)) + return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3); + else + return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5); +} + +bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, + enum plane_id plane_id) +{ + return INTEL_GEN(dev_priv) >= 11 && + icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id); +} + bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id) { return INTEL_GEN(dev_priv) >= 11 && @@ -3003,7 +3019,7 @@ static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv, if (icl_is_hdr_plane(dev_priv, plane_id)) { *num_formats = ARRAY_SIZE(icl_hdr_plane_formats); return icl_hdr_plane_formats; - } else if (icl_is_nv12_y_plane(plane_id)) { + } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) { *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats); return icl_sdr_y_plane_formats; } else { @@ -3046,6 +3062,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, struct intel_plane *plane; enum drm_plane_type plane_type; unsigned int supported_rotations; + unsigned int supported_csc; const u64 *modifiers; const u32 *formats; int num_formats; @@ -3120,9 +3137,13 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, DRM_MODE_ROTATE_0, supported_rotations); + supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709); + + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) + supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020); + drm_plane_create_color_properties(&plane->base, - BIT(DRM_COLOR_YCBCR_BT601) | - BIT(DRM_COLOR_YCBCR_BT709), + supported_csc, BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | BIT(DRM_COLOR_YCBCR_FULL_RANGE), DRM_COLOR_YCBCR_BT709, @@ -3136,6 +3157,9 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, drm_plane_create_zpos_immutable_property(&plane->base, plane_id); + if (INTEL_GEN(dev_priv) >= 12) + drm_plane_enable_fb_damage_clips(&plane->base); + drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); return plane; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h index 5eeaa92420d1..cd2104ba1ca1 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.h +++ b/drivers/gpu/drm/i915/display/intel_sprite.h @@ -32,21 +32,14 @@ struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id); -static inline bool icl_is_nv12_y_plane(enum plane_id id) -{ - /* Don't need to do a gen check, these planes are only available on gen11 */ - if (id == PLANE_SPRITE4 || id == PLANE_SPRITE5) - return true; - - return false; -} - static inline u8 icl_hdr_plane_mask(void) { return BIT(PLANE_PRIMARY) | BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1); } +bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, + enum plane_id plane_id); bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id); int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index b161c15baf86..5b5dc86a5737 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -360,12 +360,12 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port, } if (!icl_tc_phy_set_safe_mode(dig_port, false) && - !WARN_ON(dig_port->tc_legacy_port)) + !drm_WARN_ON(&i915->drm, dig_port->tc_legacy_port)) goto out_set_tbt_alt_mode; max_lanes = intel_tc_port_fia_max_lane_count(dig_port); if (dig_port->tc_legacy_port) { - WARN_ON(max_lanes != 4); + drm_WARN_ON(&i915->drm, max_lanes != 4); dig_port->tc_mode = TC_PORT_LEGACY; return; @@ -445,18 +445,20 @@ static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port) static enum tc_port_mode intel_tc_port_get_current_mode(struct intel_digital_port *dig_port) { + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); u32 live_status_mask = tc_port_live_status_mask(dig_port); bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port); enum tc_port_mode mode; - if (in_safe_mode || WARN_ON(!icl_tc_phy_status_complete(dig_port))) + if (in_safe_mode || + drm_WARN_ON(&i915->drm, !icl_tc_phy_status_complete(dig_port))) return TC_PORT_TBT_ALT; mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT; if (live_status_mask) { enum tc_port_mode live_mode = fls(live_status_mask) - 1; - if (!WARN_ON(live_mode == TC_PORT_TBT_ALT)) + if (!drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT)) mode = live_mode; } @@ -505,7 +507,9 @@ static void intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port, int refcount) { - WARN_ON(dig_port->tc_link_refcount); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + + drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount); dig_port->tc_link_refcount = refcount; } diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index abc67207f2f3..777032d9697b 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1158,7 +1158,7 @@ intel_tv_get_config(struct intel_encoder *encoder, /* pixel counter doesn't work on i965gm TV output */ if (IS_I965GM(dev_priv)) - adjusted_mode->private_flags |= + pipe_config->mode_flags |= I915_MODE_FLAG_USE_SCANLINE_COUNTER; } @@ -1328,7 +1328,7 @@ intel_tv_compute_config(struct intel_encoder *encoder, /* pixel counter doesn't work on i965gm TV output */ if (IS_I965GM(dev_priv)) - adjusted_mode->private_flags |= + pipe_config->mode_flags |= I915_MODE_FLAG_USE_SCANLINE_COUNTER; return 0; diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index aef7fe932d1a..6faabd4f6d49 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -820,6 +820,7 @@ struct bdb_lfp_power { u16 adb; u16 lace_enabled_status; struct agressiveness_profile_entry aggressivenes[16]; + u16 hobl; /* 232+ */ } __packed; /* diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 95ad87d4ccb3..c5735c365659 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -476,13 +476,13 @@ intel_dsc_power_domain(const struct intel_crtc_state *crtc_state) * POWER_DOMAIN_TRANSCODER_VDSC_PW2 power domain in two cases: * * - ICL eDP/DSI transcoder - * - TGL pipe A + * - Gen12+ (except RKL) pipe A * * For any other pipe, VDSC/joining uses the power well associated with * the pipe in use. Hence another reference on the pipe power domain * will suffice. (Except no VDSC/joining on ICL pipe A.) */ - if (INTEL_GEN(i915) >= 12 && pipe == PIPE_A) + if (INTEL_GEN(i915) >= 12 && !IS_ROCKETLAKE(i915) && pipe == PIPE_A) return POWER_DOMAIN_TRANSCODER_VDSC_PW2; else if (is_pipe_dsc(crtc_state)) return POWER_DOMAIN_PIPE(pipe); @@ -1045,7 +1045,7 @@ static void intel_dsc_dp_pps_write(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; struct drm_dsc_pps_infoframe dp_dsc_pps_sdp; @@ -1055,9 +1055,9 @@ static void intel_dsc_dp_pps_write(struct intel_encoder *encoder, /* Fill the PPS payload bytes as per DSC spec 1.2 Table 4-1 */ drm_dsc_pps_payload_pack(&dp_dsc_pps_sdp.pps_payload, vdsc_cfg); - intel_dig_port->write_infoframe(encoder, crtc_state, - DP_SDP_PPS, &dp_dsc_pps_sdp, - sizeof(dp_dsc_pps_sdp)); + dig_port->write_infoframe(encoder, crtc_state, + DP_SDP_PPS, &dp_dsc_pps_sdp, + sizeof(dp_dsc_pps_sdp)); } void intel_dsc_enable(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index f582ab52f0b0..052e0b31a2da 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -298,7 +298,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder, if (IS_GEN9_LP(dev_priv)) { /* Enable Frame time stamp based scanline reporting */ - adjusted_mode->private_flags |= + pipe_config->mode_flags |= I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; /* Dual link goes to DSI transcoder A. */ @@ -1097,8 +1097,8 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc); /* Enable Frame time stamo based scanline reporting */ - adjusted_mode->private_flags |= - I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; + pipe_config->mode_flags |= + I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; /* In terms of pixels */ adjusted_mode->crtc_hdisplay = |