summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display')
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c81
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c151
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c111
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c66
-rw-r--r--drivers/gpu/drm/i915/display/intel_combo_phy.c80
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_csr.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c481
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c359
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c21
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c377
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h7
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h73
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c559
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_link_training.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c185
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.c38
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c256
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.h17
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c104
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c160
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c300
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c53
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_lspcon.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_lspcon.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_opregion.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.c30
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c98
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c166
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo_regs.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c30
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_vbt_defs.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c12
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c6
51 files changed, 2545 insertions, 1561 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 26996e1839e2..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);
}
@@ -4823,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) {
@@ -4890,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;
@@ -6435,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;
@@ -7223,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;
@@ -7517,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)
@@ -7590,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;
@@ -7663,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;
}
@@ -7880,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)
@@ -8151,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);
}
@@ -8897,7 +8915,6 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;
- mode->vrefresh = drm_mode_vrefresh(mode);
drm_mode_set_name(mode);
}
@@ -10056,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)
@@ -10894,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;
@@ -10904,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.
@@ -10917,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;
@@ -12511,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))
@@ -12557,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);
}
@@ -12580,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,
@@ -12593,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)
@@ -12607,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;
@@ -12619,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,
@@ -13582,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)
@@ -13607,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,
@@ -14019,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 */
@@ -14416,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.
*
@@ -14563,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);
@@ -14653,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;
@@ -14699,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);
@@ -14707,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
@@ -14718,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;
}
@@ -14769,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;
}
@@ -14880,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
@@ -14908,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)
@@ -14921,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) &&
@@ -14951,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)
@@ -15124,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);
}
@@ -15216,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);
@@ -15405,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);
}
@@ -15479,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);
@@ -15536,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);
@@ -15547,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 */
@@ -15696,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;
@@ -16252,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;
@@ -16417,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;
@@ -16757,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);
@@ -17432,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) {
@@ -17590,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;
@@ -17677,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 {
@@ -17723,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;
@@ -18239,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;
@@ -18269,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);
@@ -18360,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 3a06f72c9859..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,
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 70525623bcdf..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");
@@ -1099,10 +1099,10 @@ static void drrs_status_per_crtc(struct seq_file *m,
seq_puts(m, "\n\t\t");
if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
- vrefresh = panel->fixed_mode->vrefresh;
+ vrefresh = drm_mode_vrefresh(panel->fixed_mode);
} else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
- vrefresh = panel->downclock_mode->vrefresh;
+ vrefresh = drm_mode_vrefresh(panel->downclock_mode);
} else {
seq_printf(m, "DRRS_State: Unknown(%d)\n",
drrs->refresh_rate_type);
@@ -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 ed9e53c373a7..d6295eb20b63 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;
-
- if (!intel_dp->is_mst)
- return -EINVAL;
+ bool link_ok = true;
- 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
@@ -6345,10 +6332,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;
@@ -6407,11 +6394,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,
@@ -6422,7 +6409,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,
@@ -6461,13 +6448,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,
@@ -6477,10 +6464,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;
/*
@@ -6488,7 +6475,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,
@@ -6499,13 +6486,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,
@@ -6517,13 +6504,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;
@@ -6532,13 +6519,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",
@@ -6549,14 +6536,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,
@@ -6568,17 +6555,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);
@@ -6593,16 +6580,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) {
@@ -6614,7 +6601,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 */
@@ -6622,13 +6609,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,
@@ -6640,13 +6627,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;
@@ -6704,13 +6691,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) {
@@ -6723,14 +6710,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;
@@ -6756,11 +6743,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;
@@ -6784,7 +6771,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;
@@ -6810,10 +6797,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;
@@ -6836,7 +6823,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;
@@ -6850,13 +6837,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)
@@ -6876,10 +6863,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;
@@ -6890,12 +6877,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;
@@ -6910,7 +6897,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",
@@ -6929,7 +6916,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;
@@ -6948,7 +6935,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;
@@ -6956,12 +6943,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;
@@ -6976,14 +6963,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)
@@ -7262,12 +7249,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
@@ -7278,14 +7265,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) {
@@ -7294,35 +7281,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;
@@ -7694,7 +7656,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
return;
}
- if (intel_dp->attached_connector->panel.downclock_mode->vrefresh ==
+ if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) ==
refresh_rate)
index = DRRS_LOW_RR;
@@ -7807,7 +7769,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp,
if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
intel_dp_set_drrs_state(dev_priv, old_crtc_state,
- intel_dp->attached_connector->panel.fixed_mode->vrefresh);
+ drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
dev_priv->drrs.dp = NULL;
mutex_unlock(&dev_priv->drrs.mutex);
@@ -7840,7 +7802,7 @@ static void intel_edp_drrs_downclock_work(struct work_struct *work)
struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
- intel_dp->attached_connector->panel.downclock_mode->vrefresh);
+ drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode));
}
unlock:
@@ -7860,6 +7822,7 @@ unlock:
void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits)
{
+ struct intel_dp *intel_dp;
struct drm_crtc *crtc;
enum pipe pipe;
@@ -7869,12 +7832,14 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
cancel_delayed_work(&dev_priv->drrs.work);
mutex_lock(&dev_priv->drrs.mutex);
- if (!dev_priv->drrs.dp) {
+
+ intel_dp = dev_priv->drrs.dp;
+ if (!intel_dp) {
mutex_unlock(&dev_priv->drrs.mutex);
return;
}
- crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
+ crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
pipe = to_intel_crtc(crtc)->pipe;
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -7883,7 +7848,7 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
/* invalidate means busy screen hence upclock */
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
- dev_priv->drrs.dp->attached_connector->panel.fixed_mode->vrefresh);
+ drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
mutex_unlock(&dev_priv->drrs.mutex);
}
@@ -7903,6 +7868,7 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits)
{
+ struct intel_dp *intel_dp;
struct drm_crtc *crtc;
enum pipe pipe;
@@ -7912,12 +7878,14 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
cancel_delayed_work(&dev_priv->drrs.work);
mutex_lock(&dev_priv->drrs.mutex);
- if (!dev_priv->drrs.dp) {
+
+ intel_dp = dev_priv->drrs.dp;
+ if (!intel_dp) {
mutex_unlock(&dev_priv->drrs.mutex);
return;
}
- crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
+ crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
pipe = to_intel_crtc(crtc)->pipe;
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -7926,7 +7894,7 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
/* flush means busy screen hence upclock */
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
- dev_priv->drrs.dp->attached_connector->panel.fixed_mode->vrefresh);
+ drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
/*
* flush also means no more activity hence schedule downclock, if all
@@ -8167,12 +8135,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;
@@ -8183,9 +8151,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;
@@ -8256,12 +8224,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;
}
@@ -8296,20 +8264,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,
@@ -8345,25 +8313,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);
@@ -8378,25 +8355,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;
@@ -8406,7 +8383,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 f29e51ce489c..a2d91a499700 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -33,6 +33,7 @@
#include "intel_connector.h"
#include "intel_ddi.h"
#include "intel_display_types.h"
+#include "intel_hotplug.h"
#include "intel_dp.h"
#include "intel_dp_mst.h"
#include "intel_dpio_phy.h"
@@ -316,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);
@@ -349,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);
@@ -369,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;
@@ -376,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);
@@ -403,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
@@ -418,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",
@@ -431,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);
}
@@ -445,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,
@@ -473,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,
@@ -484,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.
@@ -510,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);
@@ -551,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)
@@ -618,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->flags & DRM_MODE_FLAG_DBLCLK)
- return MODE_H_ILLEGAL;
+ 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_rate > max_rate || mode->clock > max_dotclk)
- return MODE_CLOCK_HIGH;
+ if (mode->clock < 10000) {
+ *status = MODE_CLOCK_LOW;
+ return 0;
+ }
+
+ 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,
@@ -679,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,
@@ -711,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;
@@ -773,16 +815,25 @@ err:
return NULL;
}
+static void
+intel_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+
+ intel_hpd_trigger_irq(dp_to_dig_port(intel_dp));
+}
+
static const struct drm_dp_mst_topology_cbs mst_cbs = {
.add_connector = intel_dp_add_mst_connector,
+ .poll_hpd_irq = intel_dp_mst_poll_hpd_irq,
};
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);
@@ -791,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
@@ -825,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))
@@ -862,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)
@@ -874,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 61807e4b1aca..24c3a0f212c6 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -132,14 +132,13 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
}
/* 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);
}
@@ -188,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;
@@ -199,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;
@@ -316,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);
@@ -696,9 +712,16 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
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 &&
@@ -747,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;
}
@@ -814,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";
@@ -830,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";
@@ -892,6 +915,8 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
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;
@@ -1028,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);
@@ -1101,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 &&
@@ -1377,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;
@@ -1422,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 95b6d9457910..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);
@@ -2904,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);
@@ -2916,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);
@@ -3076,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)
{
@@ -3113,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);
@@ -3133,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;
@@ -3192,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;
@@ -3283,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,
@@ -3354,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 4f6f560e093e..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;
@@ -274,24 +283,30 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
{
struct drm_device *dev = connector->base.dev;
enum drm_connector_status old_status;
+ u64 old_epoch_counter;
+ bool ret = false;
drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex));
old_status = connector->base.status;
+ old_epoch_counter = connector->base.epoch_counter;
connector->base.status =
drm_helper_probe_detect(&connector->base, NULL, false);
- if (old_status == connector->base.status)
- return INTEL_HOTPLUG_UNCHANGED;
-
- drm_dbg_kms(&to_i915(dev)->drm,
- "[CONNECTOR:%d:%s] status updated from %s to %s\n",
- connector->base.base.id,
- connector->base.name,
- drm_get_connector_status_name(old_status),
- drm_get_connector_status_name(connector->base.status));
+ if (old_epoch_counter != connector->base.epoch_counter)
+ ret = true;
- return INTEL_HOTPLUG_CHANGED;
+ if (ret) {
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s (epoch counter %llu->%llu)\n",
+ connector->base.base.id,
+ connector->base.name,
+ drm_get_connector_status_name(old_status),
+ drm_get_connector_status_name(connector->base.status),
+ old_epoch_counter,
+ connector->base.epoch_counter);
+ return INTEL_HOTPLUG_CHANGED;
+ }
+ return INTEL_HOTPLUG_UNCHANGED;
}
static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder)
@@ -347,6 +362,24 @@ static void i915_digport_work_func(struct work_struct *work)
}
}
+/**
+ * intel_hpd_trigger_irq - trigger an hpd irq event for a port
+ * @dig_port: digital port
+ *
+ * Trigger an HPD interrupt event for the given port, emulating a short pulse
+ * generated by the sink, and schedule the dig port work to handle it.
+ */
+void intel_hpd_trigger_irq(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+ spin_lock_irq(&i915->irq_lock);
+ i915->hotplug.short_port_mask |= BIT(dig_port->base.port);
+ spin_unlock_irq(&i915->irq_lock);
+
+ queue_work(i915->hotplug.dp_wq, &i915->hotplug.dig_port_work);
+}
+
/*
* Handle hotplug events outside the interrupt handler proper.
*/
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h
index 777b0743257e..a704d7c94d16 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.h
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.h
@@ -10,6 +10,7 @@
struct drm_i915_private;
struct intel_connector;
+struct intel_digital_port;
struct intel_encoder;
enum port;
@@ -18,6 +19,7 @@ enum intel_hotplug_state intel_encoder_hotplug(struct intel_encoder *encoder,
struct intel_connector *connector);
void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
u32 pin_mask, u32 long_mask);
+void intel_hpd_trigger_irq(struct intel_digital_port *dig_port);
void intel_hpd_init(struct drm_i915_private *dev_priv);
void intel_hpd_init_work(struct drm_i915_private *dev_priv);
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
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 fbe12aad7d58..777032d9697b 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -1038,9 +1038,6 @@ intel_tv_mode_to_mode(struct drm_display_mode *mode,
/* TV has it's own notion of sync and other mode flags, so clear them. */
mode->flags = 0;
- mode->vrefresh = 0;
- mode->vrefresh = drm_mode_vrefresh(mode);
-
snprintf(mode->name, sizeof(mode->name),
"%dx%d%c (%s)",
mode->hdisplay, mode->vdisplay,
@@ -1161,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;
}
@@ -1331,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 =