Backmerge to bring Xe driver to drm-intel-next.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
if (controller == 1 &&
INTEL_PCH_TYPE(i915) >= PCH_ICP &&
- INTEL_PCH_TYPE(i915) < PCH_MTP)
+ INTEL_PCH_TYPE(i915) <= PCH_ADP)
return intel_de_read(i915, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT;
return true;
if (IS_DGFX(i915))
return vbt_pin;
- if (INTEL_PCH_TYPE(i915) >= PCH_LNL || HAS_PCH_MTP(i915) ||
- IS_ALDERLAKE_P(i915)) {
+ if (INTEL_PCH_TYPE(i915) >= PCH_MTL || IS_ALDERLAKE_P(i915)) {
ddc_pin_map = adlp_ddc_pin_map;
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
} else if (IS_ALDERLAKE_S(i915)) {
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
-bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
int dsc_max_bpc);
-bool intel_bios_port_supports_typec_usb(struct drm_i915_private *i915, enum port port);
-bool intel_bios_port_supports_tbt(struct drm_i915_private *i915, enum port port);
const struct intel_bios_encoder_data *
intel_bios_encoder_data_lookup(struct drm_i915_private *i915, enum port port);
u32 cdclk;
u16 refclk;
u16 waveform;
- u8 divider; /* CD2X divider * 2 */
u8 ratio;
};
static const struct intel_cdclk_vals bxt_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 144000, .divider = 8, .ratio = 60 },
- { .refclk = 19200, .cdclk = 288000, .divider = 4, .ratio = 60 },
- { .refclk = 19200, .cdclk = 384000, .divider = 3, .ratio = 60 },
- { .refclk = 19200, .cdclk = 576000, .divider = 2, .ratio = 60 },
- { .refclk = 19200, .cdclk = 624000, .divider = 2, .ratio = 65 },
+ { .refclk = 19200, .cdclk = 144000, .ratio = 60 },
+ { .refclk = 19200, .cdclk = 288000, .ratio = 60 },
+ { .refclk = 19200, .cdclk = 384000, .ratio = 60 },
+ { .refclk = 19200, .cdclk = 576000, .ratio = 60 },
+ { .refclk = 19200, .cdclk = 624000, .ratio = 65 },
{}
};
static const struct intel_cdclk_vals glk_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 79200, .divider = 8, .ratio = 33 },
- { .refclk = 19200, .cdclk = 158400, .divider = 4, .ratio = 33 },
- { .refclk = 19200, .cdclk = 316800, .divider = 2, .ratio = 33 },
+ { .refclk = 19200, .cdclk = 79200, .ratio = 33 },
+ { .refclk = 19200, .cdclk = 158400, .ratio = 33 },
+ { .refclk = 19200, .cdclk = 316800, .ratio = 33 },
{}
};
static const struct intel_cdclk_vals icl_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 172800, .divider = 2, .ratio = 18 },
- { .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
- { .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
- { .refclk = 19200, .cdclk = 326400, .divider = 4, .ratio = 68 },
- { .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
- { .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
-
- { .refclk = 24000, .cdclk = 180000, .divider = 2, .ratio = 15 },
- { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
- { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
- { .refclk = 24000, .cdclk = 324000, .divider = 4, .ratio = 54 },
- { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
- { .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
-
- { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 9 },
- { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
- { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
- { .refclk = 38400, .cdclk = 326400, .divider = 4, .ratio = 34 },
- { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ { .refclk = 19200, .cdclk = 172800, .ratio = 18 },
+ { .refclk = 19200, .cdclk = 192000, .ratio = 20 },
+ { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
+ { .refclk = 19200, .cdclk = 326400, .ratio = 68 },
+ { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
+ { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
+
+ { .refclk = 24000, .cdclk = 180000, .ratio = 15 },
+ { .refclk = 24000, .cdclk = 192000, .ratio = 16 },
+ { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
+ { .refclk = 24000, .cdclk = 324000, .ratio = 54 },
+ { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
+ { .refclk = 24000, .cdclk = 648000, .ratio = 54 },
+
+ { .refclk = 38400, .cdclk = 172800, .ratio = 9 },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 10 },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 326400, .ratio = 34 },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
{}
};
static const struct intel_cdclk_vals rkl_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 172800, .divider = 4, .ratio = 36 },
- { .refclk = 19200, .cdclk = 192000, .divider = 4, .ratio = 40 },
- { .refclk = 19200, .cdclk = 307200, .divider = 4, .ratio = 64 },
- { .refclk = 19200, .cdclk = 326400, .divider = 8, .ratio = 136 },
- { .refclk = 19200, .cdclk = 556800, .divider = 4, .ratio = 116 },
- { .refclk = 19200, .cdclk = 652800, .divider = 4, .ratio = 136 },
-
- { .refclk = 24000, .cdclk = 180000, .divider = 4, .ratio = 30 },
- { .refclk = 24000, .cdclk = 192000, .divider = 4, .ratio = 32 },
- { .refclk = 24000, .cdclk = 312000, .divider = 4, .ratio = 52 },
- { .refclk = 24000, .cdclk = 324000, .divider = 8, .ratio = 108 },
- { .refclk = 24000, .cdclk = 552000, .divider = 4, .ratio = 92 },
- { .refclk = 24000, .cdclk = 648000, .divider = 4, .ratio = 108 },
-
- { .refclk = 38400, .cdclk = 172800, .divider = 4, .ratio = 18 },
- { .refclk = 38400, .cdclk = 192000, .divider = 4, .ratio = 20 },
- { .refclk = 38400, .cdclk = 307200, .divider = 4, .ratio = 32 },
- { .refclk = 38400, .cdclk = 326400, .divider = 8, .ratio = 68 },
- { .refclk = 38400, .cdclk = 556800, .divider = 4, .ratio = 58 },
- { .refclk = 38400, .cdclk = 652800, .divider = 4, .ratio = 68 },
+ { .refclk = 19200, .cdclk = 172800, .ratio = 36 },
+ { .refclk = 19200, .cdclk = 192000, .ratio = 40 },
+ { .refclk = 19200, .cdclk = 307200, .ratio = 64 },
+ { .refclk = 19200, .cdclk = 326400, .ratio = 136 },
+ { .refclk = 19200, .cdclk = 556800, .ratio = 116 },
+ { .refclk = 19200, .cdclk = 652800, .ratio = 136 },
+
+ { .refclk = 24000, .cdclk = 180000, .ratio = 30 },
+ { .refclk = 24000, .cdclk = 192000, .ratio = 32 },
+ { .refclk = 24000, .cdclk = 312000, .ratio = 52 },
+ { .refclk = 24000, .cdclk = 324000, .ratio = 108 },
+ { .refclk = 24000, .cdclk = 552000, .ratio = 92 },
+ { .refclk = 24000, .cdclk = 648000, .ratio = 108 },
+
+ { .refclk = 38400, .cdclk = 172800, .ratio = 18 },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 20 },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 32 },
+ { .refclk = 38400, .cdclk = 326400, .ratio = 68 },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 58 },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 68 },
{}
};
static const struct intel_cdclk_vals adlp_a_step_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
- { .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
- { .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
+ { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
+ { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
+ { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
- { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
- { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
- { .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 },
+ { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
+ { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
+ { .refclk = 24400, .cdclk = 648000, .ratio = 54 },
- { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
- { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
{}
};
static const struct intel_cdclk_vals adlp_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 172800, .divider = 3, .ratio = 27 },
- { .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
- { .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
- { .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
- { .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
-
- { .refclk = 24000, .cdclk = 176000, .divider = 3, .ratio = 22 },
- { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
- { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
- { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
- { .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
-
- { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
- { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
- { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
- { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ { .refclk = 19200, .cdclk = 172800, .ratio = 27 },
+ { .refclk = 19200, .cdclk = 192000, .ratio = 20 },
+ { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
+ { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
+ { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
+
+ { .refclk = 24000, .cdclk = 176000, .ratio = 22 },
+ { .refclk = 24000, .cdclk = 192000, .ratio = 16 },
+ { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
+ { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
+ { .refclk = 24000, .cdclk = 648000, .ratio = 54 },
+
+ { .refclk = 38400, .cdclk = 179200, .ratio = 14 },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 10 },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
{}
};
static const struct intel_cdclk_vals rplu_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 172800, .divider = 3, .ratio = 27 },
- { .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
- { .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
- { .refclk = 19200, .cdclk = 480000, .divider = 2, .ratio = 50 },
- { .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
- { .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
-
- { .refclk = 24000, .cdclk = 176000, .divider = 3, .ratio = 22 },
- { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
- { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
- { .refclk = 24000, .cdclk = 480000, .divider = 2, .ratio = 40 },
- { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
- { .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
-
- { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
- { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
- { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
- { .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25 },
- { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ { .refclk = 19200, .cdclk = 172800, .ratio = 27 },
+ { .refclk = 19200, .cdclk = 192000, .ratio = 20 },
+ { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
+ { .refclk = 19200, .cdclk = 480000, .ratio = 50 },
+ { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
+ { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
+
+ { .refclk = 24000, .cdclk = 176000, .ratio = 22 },
+ { .refclk = 24000, .cdclk = 192000, .ratio = 16 },
+ { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
+ { .refclk = 24000, .cdclk = 480000, .ratio = 40 },
+ { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
+ { .refclk = 24000, .cdclk = 648000, .ratio = 54 },
+
+ { .refclk = 38400, .cdclk = 179200, .ratio = 14 },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 10 },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 480000, .ratio = 25 },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
{}
};
static const struct intel_cdclk_vals dg2_cdclk_table[] = {
- { .refclk = 38400, .cdclk = 163200, .divider = 2, .ratio = 34, .waveform = 0x8888 },
- { .refclk = 38400, .cdclk = 204000, .divider = 2, .ratio = 34, .waveform = 0x9248 },
- { .refclk = 38400, .cdclk = 244800, .divider = 2, .ratio = 34, .waveform = 0xa4a4 },
- { .refclk = 38400, .cdclk = 285600, .divider = 2, .ratio = 34, .waveform = 0xa54a },
- { .refclk = 38400, .cdclk = 326400, .divider = 2, .ratio = 34, .waveform = 0xaaaa },
- { .refclk = 38400, .cdclk = 367200, .divider = 2, .ratio = 34, .waveform = 0xad5a },
- { .refclk = 38400, .cdclk = 408000, .divider = 2, .ratio = 34, .waveform = 0xb6b6 },
- { .refclk = 38400, .cdclk = 448800, .divider = 2, .ratio = 34, .waveform = 0xdbb6 },
- { .refclk = 38400, .cdclk = 489600, .divider = 2, .ratio = 34, .waveform = 0xeeee },
- { .refclk = 38400, .cdclk = 530400, .divider = 2, .ratio = 34, .waveform = 0xf7de },
- { .refclk = 38400, .cdclk = 571200, .divider = 2, .ratio = 34, .waveform = 0xfefe },
- { .refclk = 38400, .cdclk = 612000, .divider = 2, .ratio = 34, .waveform = 0xfffe },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 163200, .ratio = 34, .waveform = 0x8888 },
+ { .refclk = 38400, .cdclk = 204000, .ratio = 34, .waveform = 0x9248 },
+ { .refclk = 38400, .cdclk = 244800, .ratio = 34, .waveform = 0xa4a4 },
+ { .refclk = 38400, .cdclk = 285600, .ratio = 34, .waveform = 0xa54a },
+ { .refclk = 38400, .cdclk = 326400, .ratio = 34, .waveform = 0xaaaa },
+ { .refclk = 38400, .cdclk = 367200, .ratio = 34, .waveform = 0xad5a },
+ { .refclk = 38400, .cdclk = 408000, .ratio = 34, .waveform = 0xb6b6 },
+ { .refclk = 38400, .cdclk = 448800, .ratio = 34, .waveform = 0xdbb6 },
+ { .refclk = 38400, .cdclk = 489600, .ratio = 34, .waveform = 0xeeee },
+ { .refclk = 38400, .cdclk = 530400, .ratio = 34, .waveform = 0xf7de },
+ { .refclk = 38400, .cdclk = 571200, .ratio = 34, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 612000, .ratio = 34, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
{}
};
static const struct intel_cdclk_vals mtl_cdclk_table[] = {
- { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a },
- { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 },
- { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0x0000 },
- { .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0x0000 },
- { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0x0000 },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0x0000 },
+ { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16, .waveform = 0x0000 },
+ { .refclk = 38400, .cdclk = 480000, .ratio = 25, .waveform = 0x0000 },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29, .waveform = 0x0000 },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0x0000 },
{}
};
static const struct intel_cdclk_vals lnl_cdclk_table[] = {
- { .refclk = 38400, .cdclk = 153600, .divider = 2, .ratio = 16, .waveform = 0xaaaa },
- { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a },
- { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 },
- { .refclk = 38400, .cdclk = 211200, .divider = 2, .ratio = 16, .waveform = 0xdbb6 },
- { .refclk = 38400, .cdclk = 230400, .divider = 2, .ratio = 16, .waveform = 0xeeee },
- { .refclk = 38400, .cdclk = 249600, .divider = 2, .ratio = 16, .waveform = 0xf7de },
- { .refclk = 38400, .cdclk = 268800, .divider = 2, .ratio = 16, .waveform = 0xfefe },
- { .refclk = 38400, .cdclk = 288000, .divider = 2, .ratio = 16, .waveform = 0xfffe },
- { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0xffff },
- { .refclk = 38400, .cdclk = 330000, .divider = 2, .ratio = 25, .waveform = 0xdbb6 },
- { .refclk = 38400, .cdclk = 360000, .divider = 2, .ratio = 25, .waveform = 0xeeee },
- { .refclk = 38400, .cdclk = 390000, .divider = 2, .ratio = 25, .waveform = 0xf7de },
- { .refclk = 38400, .cdclk = 420000, .divider = 2, .ratio = 25, .waveform = 0xfefe },
- { .refclk = 38400, .cdclk = 450000, .divider = 2, .ratio = 25, .waveform = 0xfffe },
- { .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0xffff },
- { .refclk = 38400, .cdclk = 487200, .divider = 2, .ratio = 29, .waveform = 0xfefe },
- { .refclk = 38400, .cdclk = 522000, .divider = 2, .ratio = 29, .waveform = 0xfffe },
- { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0xffff },
- { .refclk = 38400, .cdclk = 571200, .divider = 2, .ratio = 34, .waveform = 0xfefe },
- { .refclk = 38400, .cdclk = 612000, .divider = 2, .ratio = 34, .waveform = 0xfffe },
- { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 153600, .ratio = 16, .waveform = 0xaaaa },
+ { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 },
+ { .refclk = 38400, .cdclk = 211200, .ratio = 16, .waveform = 0xdbb6 },
+ { .refclk = 38400, .cdclk = 230400, .ratio = 16, .waveform = 0xeeee },
+ { .refclk = 38400, .cdclk = 249600, .ratio = 16, .waveform = 0xf7de },
+ { .refclk = 38400, .cdclk = 268800, .ratio = 16, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 288000, .ratio = 16, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 330000, .ratio = 25, .waveform = 0xdbb6 },
+ { .refclk = 38400, .cdclk = 360000, .ratio = 25, .waveform = 0xeeee },
+ { .refclk = 38400, .cdclk = 390000, .ratio = 25, .waveform = 0xf7de },
+ { .refclk = 38400, .cdclk = 420000, .ratio = 25, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 450000, .ratio = 25, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 480000, .ratio = 25, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 487200, .ratio = 29, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 522000, .ratio = 29, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 571200, .ratio = 34, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 612000, .ratio = 34, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
{}
};
dev_priv->display.cdclk.hw.vco > 0;
}
+static u32 bxt_cdclk_ctl(struct drm_i915_private *i915,
+ const struct intel_cdclk_config *cdclk_config,
+ enum pipe pipe)
+{
+ int cdclk = cdclk_config->cdclk;
+ int vco = cdclk_config->vco;
+ int unsquashed_cdclk;
+ u16 waveform;
+ u32 val;
+
+ waveform = cdclk_squash_waveform(i915, cdclk);
+
+ unsquashed_cdclk = DIV_ROUND_CLOSEST(cdclk * cdclk_squash_len,
+ cdclk_squash_divider(waveform));
+
+ val = bxt_cdclk_cd2x_div_sel(i915, unsquashed_cdclk, vco) |
+ bxt_cdclk_cd2x_pipe(i915, pipe);
+
+ /*
+ * Disable SSA Precharge when CD clock frequency < 500 MHz,
+ * enable otherwise.
+ */
+ if ((IS_GEMINILAKE(i915) || IS_BROXTON(i915)) &&
+ cdclk >= 500000)
+ val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
+
+ if (DISPLAY_VER(i915) >= 20)
+ val |= MDCLK_SOURCE_SEL_CDCLK_PLL;
+ else
+ val |= skl_cdclk_decimal(cdclk);
+
+ return val;
+}
+
static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
int cdclk = cdclk_config->cdclk;
int vco = cdclk_config->vco;
- int unsquashed_cdclk;
u16 waveform;
- u32 val;
if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 &&
!cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) {
waveform = cdclk_squash_waveform(dev_priv, cdclk);
- unsquashed_cdclk = DIV_ROUND_CLOSEST(cdclk * cdclk_squash_len,
- cdclk_squash_divider(waveform));
-
if (HAS_CDCLK_SQUASH(dev_priv))
dg2_cdclk_squash_program(dev_priv, waveform);
- val = bxt_cdclk_cd2x_div_sel(dev_priv, unsquashed_cdclk, vco) |
- bxt_cdclk_cd2x_pipe(dev_priv, pipe);
-
- /*
- * Disable SSA Precharge when CD clock frequency < 500 MHz,
- * enable otherwise.
- */
- if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
- cdclk >= 500000)
- val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
-
- if (DISPLAY_VER(dev_priv) >= 20)
- val |= MDCLK_SOURCE_SEL_CDCLK_PLL;
- else
- val |= skl_cdclk_decimal(cdclk);
-
- intel_de_write(dev_priv, CDCLK_CTL, val);
+ intel_de_write(dev_priv, CDCLK_CTL, bxt_cdclk_ctl(dev_priv, cdclk_config, pipe));
if (pipe != INVALID_PIPE)
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe));
static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
{
u32 cdctl, expected;
- int cdclk, clock, vco;
+ int cdclk, vco;
intel_update_cdclk(dev_priv);
intel_cdclk_dump_config(dev_priv, &dev_priv->display.cdclk.hw, "Current CDCLK");
dev_priv->display.cdclk.hw.cdclk == dev_priv->display.cdclk.hw.bypass)
goto sanitize;
- /* DPLL okay; verify the cdclock
- *
- * Some BIOS versions leave an incorrect decimal frequency value and
- * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
- * so sanitize this register.
- */
- cdctl = intel_de_read(dev_priv, CDCLK_CTL);
- /*
- * Let's ignore the pipe field, since BIOS could have configured the
- * dividers both synching to an active pipe, or asynchronously
- * (PIPE_NONE).
- */
- cdctl &= ~bxt_cdclk_cd2x_pipe(dev_priv, INVALID_PIPE);
-
/* Make sure this is a legal cdclk value for the platform */
cdclk = bxt_calc_cdclk(dev_priv, dev_priv->display.cdclk.hw.cdclk);
if (cdclk != dev_priv->display.cdclk.hw.cdclk)
if (vco != dev_priv->display.cdclk.hw.vco)
goto sanitize;
- expected = skl_cdclk_decimal(cdclk);
-
- /* Figure out what CD2X divider we should be using for this cdclk */
- if (HAS_CDCLK_SQUASH(dev_priv))
- clock = dev_priv->display.cdclk.hw.vco / 2;
- else
- clock = dev_priv->display.cdclk.hw.cdclk;
-
- expected |= bxt_cdclk_cd2x_div_sel(dev_priv, clock,
- dev_priv->display.cdclk.hw.vco);
+ /*
+ * Some BIOS versions leave an incorrect decimal frequency value and
+ * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
+ * so sanitize this register.
+ */
+ cdctl = intel_de_read(dev_priv, CDCLK_CTL);
+ expected = bxt_cdclk_ctl(dev_priv, &dev_priv->display.cdclk.hw, INVALID_PIPE);
/*
- * Disable SSA Precharge when CD clock frequency < 500 MHz,
- * enable otherwise.
+ * Let's ignore the pipe field, since BIOS could have configured the
+ * dividers both synching to an active pipe, or asynchronously
+ * (PIPE_NONE).
*/
- if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
- dev_priv->display.cdclk.hw.cdclk >= 500000)
- expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
+ cdctl &= ~bxt_cdclk_cd2x_pipe(dev_priv, INVALID_PIPE);
+ expected &= ~bxt_cdclk_cd2x_pipe(dev_priv, INVALID_PIPE);
if (cdctl == expected)
/* All well; nothing to sanitize */
{
u32 freq;
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
- freq = dg1_rawclk(dev_priv);
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTL)
/*
* MTL always uses a 38.4 MHz rawclk. The bspec tells us
* "RAWCLK_FREQ defaults to the values for 38.4 and does
* not need to be programmed."
*/
freq = 38400;
+ else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
+ freq = dg1_rawclk(dev_priv);
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
freq = cnp_rawclk(dev_priv);
else if (HAS_PCH_SPLIT(dev_priv))
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fdi_regs.h"
if (!intel_display_device_enabled(dev_priv))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(dev_priv))
+ return connector->status;
+
if (dev_priv->display.params.load_detect_test) {
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
} else {
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
}
+ intel_connector->base.polled = intel_connector->polled;
if (HAS_DDI(dev_priv)) {
assert_port_valid(dev_priv, PORT_E);
return base + plane_state->view.color_plane[0].offset;
}
-static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
+static u32 intel_cursor_position(const struct intel_crtc_state *crtc_state,
+ const struct intel_plane_state *plane_state,
+ bool early_tpt)
{
int x = plane_state->uapi.dst.x1;
int y = plane_state->uapi.dst.y1;
u32 pos = 0;
+ /*
+ * Formula from Bspec:
+ * MAX(-1 * <Cursor vertical size from CUR_CTL base on cursor mode
+ * select setting> + 1, CUR_POS Y Position - Update region Y position
+ */
+ if (early_tpt)
+ y = max(-1 * drm_rect_height(&plane_state->uapi.dst) + 1,
+ y - crtc_state->psr2_su_area.y1);
+
if (x < 0) {
pos |= CURSOR_POS_X_SIGN;
x = -x;
size = CURSOR_HEIGHT(height) | CURSOR_WIDTH(width);
base = intel_cursor_base(plane_state);
- pos = intel_cursor_position(plane_state);
+ pos = intel_cursor_position(crtc_state, plane_state, false);
}
/* On these chipsets we can only modify the base/size/stride
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
- struct drm_i915_private *i915 = to_i915(plane->base.dev);
+ struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe;
if (!crtc_state->enable_psr2_sel_fetch)
return;
- if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
- intel_de_write_fw(i915, PLANE_SEL_FETCH_CTL(pipe, plane->id),
+ if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) {
+ if (crtc_state->enable_psr2_su_region_et) {
+ u32 val = intel_cursor_position(crtc_state, plane_state,
+ true);
+ intel_de_write_fw(dev_priv, CURPOS_ERLY_TPT(pipe), val);
+ }
+
+ intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id),
plane_state->ctl);
- else
+ } else {
i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state);
+ }
}
/* TODO: split into noarm+arm pair */
fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1);
base = intel_cursor_base(plane_state);
- pos = intel_cursor_position(plane_state);
+ pos = intel_cursor_position(crtc_state, plane_state, false);
}
/*
return intel_c20pll_calc_state(crtc_state, encoder);
}
-static bool intel_c20_use_mplla(u32 clock)
+static bool intel_c20phy_use_mpllb(const struct intel_c20pll_state *state)
{
- /* 10G and 20G rates use MPLLA */
- if (clock == 1000000 || clock == 2000000)
- return true;
+ return state->tx[0] & C20_PHY_USE_MPLLB;
+}
- return false;
+static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_c20pll_state *pll_state)
+{
+ unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
+ unsigned int multiplier, refclk = 38400;
+ unsigned int tx_clk_div;
+ unsigned int ref_clk_mpllb_div;
+ unsigned int fb_clk_div4_en;
+ unsigned int ref, vco;
+ unsigned int tx_rate_mult;
+ unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
+
+ if (intel_c20phy_use_mpllb(pll_state)) {
+ tx_rate_mult = 1;
+ frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
+ frac_quot = pll_state->mpllb[8];
+ frac_rem = pll_state->mpllb[9];
+ frac_den = pll_state->mpllb[7];
+ multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mpllb[0]);
+ tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, pll_state->mpllb[0]);
+ ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mpllb[6]);
+ fb_clk_div4_en = 0;
+ } else {
+ tx_rate_mult = 2;
+ frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
+ frac_quot = pll_state->mplla[8];
+ frac_rem = pll_state->mplla[9];
+ frac_den = pll_state->mplla[7];
+ multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mplla[0]);
+ tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, pll_state->mplla[1]);
+ ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mplla[6]);
+ fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, pll_state->mplla[0]);
+ }
+
+ if (frac_en)
+ frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
+ else
+ frac = 0;
+
+ ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << ref_clk_mpllb_div);
+ vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + frac) >> 17, 10);
+
+ return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
}
static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
PHY_C20_A_CMN_CNTX_CFG(i));
}
- if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+ if (intel_c20phy_use_mpllb(pll_state)) {
/* MPLLB configuration */
for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
}
}
+ pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state);
+
intel_cx0_phy_transaction_end(encoder, wakeref);
}
drm_dbg_kms(&i915->drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n",
hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]);
- if (intel_c20_use_mplla(hw_state->clock)) {
- for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
- drm_dbg_kms(&i915->drm, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]);
- } else {
+ if (intel_c20phy_use_mpllb(hw_state)) {
for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
drm_dbg_kms(&i915->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+ drm_dbg_kms(&i915->drm, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]);
}
}
}
/* 3.3 mpllb or mplla configuration */
- if (intel_c20_use_mplla(clock)) {
- for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
+ if (intel_c20phy_use_mpllb(pll_state)) {
+ for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
- PHY_C20_A_MPLLA_CNTX_CFG(i),
- pll_state->mplla[i]);
+ PHY_C20_A_MPLLB_CNTX_CFG(i),
+ pll_state->mpllb[i]);
else
intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
- PHY_C20_B_MPLLA_CNTX_CFG(i),
- pll_state->mplla[i]);
+ PHY_C20_B_MPLLB_CNTX_CFG(i),
+ pll_state->mpllb[i]);
}
} else {
- for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
+ for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
- PHY_C20_A_MPLLB_CNTX_CFG(i),
- pll_state->mpllb[i]);
+ PHY_C20_A_MPLLA_CNTX_CFG(i),
+ pll_state->mplla[i]);
else
intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
- PHY_C20_B_MPLLB_CNTX_CFG(i),
- pll_state->mpllb[i]);
+ PHY_C20_B_MPLLA_CNTX_CFG(i),
+ pll_state->mplla[i]);
}
}
return tmpclk;
}
-static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
- const struct intel_c20pll_state *pll_state)
-{
- unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
- unsigned int multiplier, refclk = 38400;
- unsigned int tx_clk_div;
- unsigned int ref_clk_mpllb_div;
- unsigned int fb_clk_div4_en;
- unsigned int ref, vco;
- unsigned int tx_rate_mult;
- unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
-
- if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
- tx_rate_mult = 1;
- frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
- frac_quot = pll_state->mpllb[8];
- frac_rem = pll_state->mpllb[9];
- frac_den = pll_state->mpllb[7];
- multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mpllb[0]);
- tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, pll_state->mpllb[0]);
- ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mpllb[6]);
- fb_clk_div4_en = 0;
- } else {
- tx_rate_mult = 2;
- frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
- frac_quot = pll_state->mplla[8];
- frac_rem = pll_state->mplla[9];
- frac_den = pll_state->mplla[7];
- multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mplla[0]);
- tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, pll_state->mplla[1]);
- ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mplla[6]);
- fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, pll_state->mplla[0]);
- }
-
- if (frac_en)
- frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
- else
- frac = 0;
-
- ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << ref_clk_mpllb_div);
- vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + frac) >> 17, 10);
-
- return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
-}
-
static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
bool lane_reversal)
const struct intel_c10pll_state *mpllb_sw_state = &state->cx0pll_state.c10;
int i;
+ if (intel_crtc_needs_fastset(state))
+ return;
+
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
u8 expected = mpllb_sw_state->pll[i];
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct intel_c20pll_state *mpll_sw_state = &state->cx0pll_state.c20;
- bool sw_use_mpllb = mpll_sw_state->tx[0] & C20_PHY_USE_MPLLB;
- bool hw_use_mpllb = mpll_hw_state->tx[0] & C20_PHY_USE_MPLLB;
+ bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state);
+ bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state);
int i;
+ I915_STATE_WARN(i915, mpll_hw_state->clock != mpll_sw_state->clock,
+ "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)",
+ crtc->base.base.id, crtc->base.name,
+ mpll_sw_state->clock, mpll_hw_state->clock);
+
I915_STATE_WARN(i915, sw_use_mpllb != hw_use_mpllb,
"[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)",
crtc->base.base.id, crtc->base.name,
if (DISPLAY_VER(dev_priv) >= 8)
bdw_get_trans_port_sync_config(pipe_config);
+ intel_psr_get_config(encoder, pipe_config);
+
intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
- intel_psr_get_config(encoder, pipe_config);
-
intel_audio_codec_get_config(encoder, pipe_config);
}
encoder->suspend_complete = intel_ddi_tc_encoder_suspend_complete;
encoder->shutdown_complete = intel_ddi_tc_encoder_shutdown_complete;
+ dig_port->lock = intel_tc_port_lock;
+ dig_port->unlock = intel_tc_port_unlock;
+
if (intel_tc_port_init(dig_port, is_legacy) < 0)
goto err;
}
#include "intel_pmdemand.h"
#include "intel_pps.h"
#include "intel_psr.h"
+#include "intel_psr_regs.h"
#include "intel_sdvo.h"
#include "intel_snps_phy.h"
#include "intel_tc.h"
*/
intel_de_write(dev_priv, PIPESRC(pipe),
PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1));
+
+ if (!crtc_state->enable_psr2_su_region_et)
+ return;
+
+ width = drm_rect_width(&crtc_state->psr2_su_area);
+ height = drm_rect_height(&crtc_state->psr2_su_area);
+
+ intel_de_write(dev_priv, PIPE_SRCSZ_ERLY_TPT(pipe),
+ PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1));
}
static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
intel_compare_dp_vsc_sdp(const struct drm_dp_vsc_sdp *a,
const struct drm_dp_vsc_sdp *b)
{
- return memcmp(a, b, sizeof(*a)) == 0;
+ return a->pixelformat == b->pixelformat &&
+ a->colorimetry == b->colorimetry &&
+ a->bpc == b->bpc &&
+ a->dynamic_range == b->dynamic_range &&
+ a->content_type == b->content_type;
}
static bool
} while (0)
#define PIPE_CONF_CHECK_DP_VSC_SDP(name) do { \
- if (!current_config->has_psr && !pipe_config->has_psr && \
- !intel_compare_dp_vsc_sdp(¤t_config->infoframes.name, \
+ if (!intel_compare_dp_vsc_sdp(¤t_config->infoframes.name, \
&pipe_config->infoframes.name)) { \
pipe_config_dp_vsc_sdp_mismatch(dev_priv, fastset, __stringify(name), \
¤t_config->infoframes.name, \
PIPE_CONF_CHECK_CSC(csc);
PIPE_CONF_CHECK_CSC(output_csc);
-
- if (current_config->active_planes) {
- PIPE_CONF_CHECK_BOOL(has_psr);
- PIPE_CONF_CHECK_BOOL(has_psr2);
- PIPE_CONF_CHECK_BOOL(enable_psr2_sel_fetch);
- PIPE_CONF_CHECK_I(dc3co_exitline);
- }
}
PIPE_CONF_CHECK_BOOL(double_wide);
int ret, i;
bool any_ms = false;
+ if (!intel_display_driver_check_access(dev_priv))
+ return -ENODEV;
+
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
/*
#include "intel_opregion.h"
#include "intel_wm_types.h"
+struct task_struct;
+
struct drm_i915_private;
struct drm_property;
struct drm_property_blob;
struct work_struct poll_init_work;
bool poll_enabled;
+ /*
+ * Queuing of hotplug_work, reenable_work and poll_init_work is
+ * enabled. Protected by drm_i915_private::irq_lock.
+ */
+ bool detection_work_enabled;
+
unsigned int hpd_storm_threshold;
/* Whether or not to count short HPD IRQs in HPD storms */
u8 hpd_short_storm_enabled;
const struct intel_audio_funcs *audio;
} funcs;
+ struct {
+ bool any_task_allowed;
+ struct task_struct *allowed_task;
+ } access;
+
struct {
/* backlight registers and fields in struct intel_panel */
struct mutex lock;
goto display_fused_off;
}
- if (IS_GRAPHICS_VER(i915, 7, 8) && HAS_PCH_SPLIT(i915)) {
+ if (IS_DISPLAY_VER(i915, 7, 8) && HAS_PCH_SPLIT(i915)) {
u32 fuse_strap = intel_de_read(i915, FUSE_STRAP);
u32 sfuse_strap = intel_de_read(i915, SFUSE_STRAP);
#include "intel_hdcp.h"
#include "intel_hotplug.h"
#include "intel_hti.h"
+#include "intel_modeset_lock.h"
#include "intel_modeset_setup.h"
#include "intel_opregion.h"
#include "intel_overlay.h"
return ret;
}
+static void set_display_access(struct drm_i915_private *i915,
+ bool any_task_allowed,
+ struct task_struct *allowed_task)
+{
+ struct drm_modeset_acquire_ctx ctx;
+ int err;
+
+ intel_modeset_lock_ctx_retry(&ctx, NULL, 0, err) {
+ err = drm_modeset_lock_all_ctx(&i915->drm, &ctx);
+ if (err)
+ continue;
+
+ i915->display.access.any_task_allowed = any_task_allowed;
+ i915->display.access.allowed_task = allowed_task;
+ }
+
+ drm_WARN_ON(&i915->drm, err);
+}
+
+/**
+ * intel_display_driver_enable_user_access - Enable display HW access for all threads
+ * @i915: i915 device instance
+ *
+ * Enable the display HW access for all threads. Examples for such accesses
+ * are modeset commits and connector probing.
+ *
+ * This function should be called during driver loading and system resume once
+ * all the HW initialization steps are done.
+ */
+void intel_display_driver_enable_user_access(struct drm_i915_private *i915)
+{
+ set_display_access(i915, true, NULL);
+
+ intel_hpd_enable_detection_work(i915);
+}
+
+/**
+ * intel_display_driver_disable_user_access - Disable display HW access for user threads
+ * @i915: i915 device instance
+ *
+ * Disable the display HW access for user threads. Examples for such accesses
+ * are modeset commits and connector probing. For the current thread the
+ * access is still enabled, which should only perform HW init/deinit
+ * programming (as the initial modeset during driver loading or the disabling
+ * modeset during driver unloading and system suspend/shutdown). This function
+ * should be followed by calling either intel_display_driver_enable_user_access()
+ * after completing the HW init programming or
+ * intel_display_driver_suspend_access() after completing the HW deinit
+ * programming.
+ *
+ * This function should be called during driver loading/unloading and system
+ * suspend/shutdown before starting the HW init/deinit programming.
+ */
+void intel_display_driver_disable_user_access(struct drm_i915_private *i915)
+{
+ intel_hpd_disable_detection_work(i915);
+
+ set_display_access(i915, false, current);
+}
+
+/**
+ * intel_display_driver_suspend_access - Suspend display HW access for all threads
+ * @i915: i915 device instance
+ *
+ * Disable the display HW access for all threads. Examples for such accesses
+ * are modeset commits and connector probing. This call should be either
+ * followed by calling intel_display_driver_resume_access(), or the driver
+ * should be unloaded/shutdown.
+ *
+ * This function should be called during driver unloading and system
+ * suspend/shutdown after completing the HW deinit programming.
+ */
+void intel_display_driver_suspend_access(struct drm_i915_private *i915)
+{
+ set_display_access(i915, false, NULL);
+}
+
+/**
+ * intel_display_driver_resume_access - Resume display HW access for the resume thread
+ * @i915: i915 device instance
+ *
+ * Enable the display HW access for the current resume thread, keeping the
+ * access disabled for all other (user) threads. Examples for such accesses
+ * are modeset commits and connector probing. The resume thread should only
+ * perform HW init programming (as the restoring modeset). This function
+ * should be followed by calling intel_display_driver_enable_user_access(),
+ * after completing the HW init programming steps.
+ *
+ * This function should be called during system resume before starting the HW
+ * init steps.
+ */
+void intel_display_driver_resume_access(struct drm_i915_private *i915)
+{
+ set_display_access(i915, false, current);
+}
+
+/**
+ * intel_display_driver_check_access - Check if the current thread has disaplay HW access
+ * @i915: i915 device instance
+ *
+ * Check whether the current thread has display HW access, print a debug
+ * message if it doesn't. Such accesses are modeset commits and connector
+ * probing. If the function returns %false any HW access should be prevented.
+ *
+ * Returns %true if the current thread has display HW access, %false
+ * otherwise.
+ */
+bool intel_display_driver_check_access(struct drm_i915_private *i915)
+{
+ char comm[TASK_COMM_LEN];
+ char current_task[TASK_COMM_LEN + 16];
+ char allowed_task[TASK_COMM_LEN + 16] = "none";
+
+ if (i915->display.access.any_task_allowed ||
+ i915->display.access.allowed_task == current)
+ return true;
+
+ snprintf(current_task, sizeof(current_task), "%s[%d]",
+ get_task_comm(comm, current),
+ task_pid_vnr(current));
+
+ if (i915->display.access.allowed_task)
+ snprintf(allowed_task, sizeof(allowed_task), "%s[%d]",
+ get_task_comm(comm, i915->display.access.allowed_task),
+ task_pid_vnr(i915->display.access.allowed_task));
+
+ drm_dbg_kms(&i915->drm,
+ "Reject display access from task %s (allowed to %s)\n",
+ current_task, allowed_task);
+
+ return false;
+}
+
/* part #2: call after irq install, but before gem init */
int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
{
intel_vga_disable(i915);
intel_setup_outputs(i915);
+ intel_display_driver_disable_user_access(i915);
+
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(i915, dev->mode_config.acquire_ctx);
intel_acpi_assign_connector_fwnodes(i915);
/* Only enable hotplug handling once the fbdev is fully set up. */
intel_hpd_init(i915);
- intel_hpd_poll_disable(i915);
skl_watermark_ipc_init(i915);
intel_audio_init(i915);
+ intel_display_driver_enable_user_access(i915);
+
intel_display_debugfs_register(i915);
/*
* fbdev->async_cookie.
*/
drm_kms_helper_poll_init(&i915->drm);
+ intel_hpd_poll_disable(i915);
intel_display_device_info_print(DISPLAY_INFO(i915),
DISPLAY_RUNTIME_INFO(i915), &p);
if (!HAS_DISPLAY(i915))
return;
+ intel_display_driver_suspend_access(i915);
+
/*
* Due to the hpd irq storm handling the hotplug work can re-arm the
* poll handlers. Hence disable polling after hpd handling is shut down.
return;
intel_fbdev_unregister(i915);
- intel_audio_deinit(i915);
-
/*
* After flushing the fbdev (incl. a late async config which
* will have delayed queuing of a hotplug event), then flush
* the hotplug events.
*/
drm_kms_helper_poll_fini(&i915->drm);
+
+ intel_display_driver_disable_user_access(i915);
+
+ intel_audio_deinit(i915);
+
drm_atomic_helper_shutdown(&i915->drm);
acpi_video_unregister();
struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx);
+void intel_display_driver_enable_user_access(struct drm_i915_private *i915);
+void intel_display_driver_disable_user_access(struct drm_i915_private *i915);
+void intel_display_driver_suspend_access(struct drm_i915_private *i915);
+void intel_display_driver_resume_access(struct drm_i915_private *i915);
+bool intel_display_driver_check_access(struct drm_i915_private *i915);
+
#endif /* __INTEL_DISPLAY_DRIVER_H__ */
* their flags both in the PICA and SDE IIR.
*/
if (*pch_iir & SDE_PICAINTERRUPT) {
- drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP);
+ drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTL);
pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0);
*pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR);
struct intel_uncore *uncore = &i915->uncore;
u32 display_mask, extra_mask;
- if (GRAPHICS_VER(i915) >= 7) {
+ if (DISPLAY_VER(i915) >= 7) {
display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
bool has_psr;
bool has_psr2;
bool enable_psr2_sel_fetch;
+ bool enable_psr2_su_region_et;
bool req_psr2_sdp_prior_scanline;
bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
- struct drm_dp_vsc_sdp psr_vsc;
/*
* Frequence the dpll for the port should run at. Differs from the
u32 psr2_man_track_ctl;
+ struct drm_rect psr2_su_area;
+
/* Variable Refresh Rate state */
struct {
bool enable, in_range;
/* Mutex for PSR state of the transcoder */
struct mutex lock;
-#define I915_PSR_DEBUG_MODE_MASK 0x0f
-#define I915_PSR_DEBUG_DEFAULT 0x00
-#define I915_PSR_DEBUG_DISABLE 0x01
-#define I915_PSR_DEBUG_ENABLE 0x02
-#define I915_PSR_DEBUG_FORCE_PSR1 0x03
-#define I915_PSR_DEBUG_ENABLE_SEL_FETCH 0x4
-#define I915_PSR_DEBUG_IRQ 0x10
+#define I915_PSR_DEBUG_MODE_MASK 0x0f
+#define I915_PSR_DEBUG_DEFAULT 0x00
+#define I915_PSR_DEBUG_DISABLE 0x01
+#define I915_PSR_DEBUG_ENABLE 0x02
+#define I915_PSR_DEBUG_FORCE_PSR1 0x03
+#define I915_PSR_DEBUG_ENABLE_SEL_FETCH 0x4
+#define I915_PSR_DEBUG_IRQ 0x10
+#define I915_PSR_DEBUG_SU_REGION_ET_DISABLE 0x20
u32 debug;
bool sink_support;
unsigned int busy_frontbuffer_bits;
bool sink_psr2_support;
bool link_standby;
- bool colorimetry_support;
bool psr2_enabled;
bool psr2_sel_fetch_enabled;
bool psr2_sel_fetch_cff_enabled;
/* When we last wrote the OUI for eDP */
unsigned long last_oui_write;
+
+ bool colorimetry_support;
};
enum lspcon_vendor {
u32 (*infoframes_enabled)(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config);
bool (*connected)(struct intel_encoder *encoder);
+
+ void (*lock)(struct intel_digital_port *dig_port);
+ void (*unlock)(struct intel_digital_port *dig_port);
};
struct intel_dp_mst_encoder {
str_yes_no(intel_dmc_has_payload(i915)));
seq_printf(m, "path: %s\n", dmc ? dmc->fw_path : "N/A");
seq_printf(m, "Pipe A fw needed: %s\n",
- str_yes_no(GRAPHICS_VER(i915) >= 12));
+ str_yes_no(DISPLAY_VER(i915) >= 12));
seq_printf(m, "Pipe A fw loaded: %s\n",
str_yes_no(has_dmc_id_fw(i915, DMC_FW_PIPEA)));
seq_printf(m, "Pipe B fw needed: %s\n",
#include "intel_cx0_phy.h"
#include "intel_ddi.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct drm_dp_vsc_sdp *vsc = &crtc_state->infoframes.vsc;
+ struct drm_dp_vsc_sdp *vsc;
- /* When a crtc state has PSR, VSC SDP will be handled by PSR routine */
- if (crtc_state->has_psr)
+ if ((!intel_dp->colorimetry_support ||
+ !intel_dp_needs_vsc_sdp(crtc_state, conn_state)) &&
+ !crtc_state->has_psr)
return;
- if (!intel_dp_needs_vsc_sdp(crtc_state, conn_state))
- return;
+ vsc = &crtc_state->infoframes.vsc;
crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC);
vsc->sdp_type = DP_SDP_VSC;
- intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
- &crtc_state->infoframes.vsc);
-}
-void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state,
- struct drm_dp_vsc_sdp *vsc)
-{
- vsc->sdp_type = DP_SDP_VSC;
-
- if (crtc_state->has_psr2) {
- if (intel_dp->psr.colorimetry_support &&
- intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
- /* [PSR2, +Colorimetry] */
- intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
- vsc);
- } else {
- /*
- * [PSR2, -Colorimetry]
- * Prepare VSC Header for SU as per eDP 1.4 spec, Table 6-11
- * 3D stereo + PSR/PSR2 + Y-coordinate.
- */
- vsc->revision = 0x4;
- vsc->length = 0xe;
- }
+ /* Needs colorimetry */
+ if (intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
+ intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
+ vsc);
+ } else if (crtc_state->has_psr2) {
+ /*
+ * [PSR2 without colorimetry]
+ * Prepare VSC Header for SU as per eDP 1.4 spec, Table 6-11
+ * 3D stereo + PSR/PSR2 + Y-coordinate.
+ */
+ vsc->revision = 0x4;
+ vsc->length = 0xe;
} else if (crtc_state->has_panel_replay) {
- if (intel_dp->psr.colorimetry_support &&
- intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
- /* [Panel Replay with colorimetry info] */
- intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
- vsc);
- } else {
- /*
- * [Panel Replay without colorimetry info]
- * Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
- * VSC SDP supporting 3D stereo + Panel Replay.
- */
- vsc->revision = 0x6;
- vsc->length = 0x10;
- }
+ /*
+ * [Panel Replay without colorimetry info]
+ * Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+ * VSC SDP supporting 3D stereo + Panel Replay.
+ */
+ vsc->revision = 0x6;
+ vsc->length = 0x10;
} else {
/*
* [PSR1]
fastset = false;
}
- if (CAN_PSR(intel_dp)) {
- drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute PSR state\n",
- encoder->base.base.id, encoder->base.name);
- crtc_state->uapi.mode_changed = true;
- fastset = false;
- }
-
return fastset;
}
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,
- const struct drm_dp_vsc_sdp *vsc)
-{
- 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;
-
- len = intel_dp_vsc_sdp_pack(vsc, &sdp, sizeof(sdp));
-
- if (drm_WARN_ON(&dev_priv->drm, len < 0))
- return;
-
- dig_port->write_infoframe(encoder, crtc_state, DP_SDP_VSC,
- &sdp, len);
-}
-
void intel_dp_set_infoframes(struct intel_encoder *encoder,
bool enable,
const struct intel_crtc_state *crtc_state,
if (!enable)
return;
- /* When PSR is enabled, VSC SDP is handled by PSR routine */
- if (!crtc_state->has_psr)
- intel_write_dp_sdp(encoder, crtc_state, DP_SDP_VSC);
+ intel_write_dp_sdp(encoder, crtc_state, DP_SDP_VSC);
intel_write_dp_sdp(encoder, crtc_state, HDMI_PACKET_TYPE_GAMUT_METADATA);
}
struct dp_sdp sdp = {};
int ret;
- /* When PSR is enabled, VSC SDP is handled by PSR routine */
- if (crtc_state->has_psr)
- return;
-
if ((crtc_state->infoframes.enable &
intel_hdmi_infoframe_enable(type)) == 0)
return;
struct drm_dp_phy_test_params *data =
&intel_dp->compliance.test_data.phytest;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
enum pipe pipe = crtc->pipe;
u32 pattern_val;
switch (data->phy_pattern) {
- case DP_PHY_TEST_PATTERN_NONE:
+ case DP_LINK_QUAL_PATTERN_DISABLE:
drm_dbg_kms(&dev_priv->drm, "Disable Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe), 0x0);
+ if (DISPLAY_VER(dev_priv) >= 10)
+ intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
+ DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
+ DP_TP_CTL_LINK_TRAIN_NORMAL);
break;
- case DP_PHY_TEST_PATTERN_D10_2:
+ case DP_LINK_QUAL_PATTERN_D10_2:
drm_dbg_kms(&dev_priv->drm, "Set D10.2 Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2);
break;
- case DP_PHY_TEST_PATTERN_ERROR_COUNT:
+ case DP_LINK_QUAL_PATTERN_ERROR_RATE:
drm_dbg_kms(&dev_priv->drm, "Set Error Count Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE |
DDI_DP_COMP_CTL_SCRAMBLED_0);
break;
- case DP_PHY_TEST_PATTERN_PRBS7:
+ case DP_LINK_QUAL_PATTERN_PRBS7:
drm_dbg_kms(&dev_priv->drm, "Set PRBS7 Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7);
break;
- case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
+ case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM:
/*
* FIXME: Ideally pattern should come from DPCD 0x250. As
* current firmware of DPR-100 could not set it, so hardcoding
DDI_DP_COMP_CTL_ENABLE |
DDI_DP_COMP_CTL_CUSTOM80);
break;
- case DP_PHY_TEST_PATTERN_CP2520:
+ case DP_LINK_QUAL_PATTERN_CP2520_PAT_1:
/*
* FIXME: Ideally pattern should come from DPCD 0x24A. As
* current firmware of DPR-100 could not set it, so hardcoding
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 |
pattern_val);
break;
+ case DP_LINK_QUAL_PATTERN_CP2520_PAT_3:
+ if (DISPLAY_VER(dev_priv) < 10) {
+ drm_warn(&dev_priv->drm, "Platform does not support TPS4\n");
+ break;
+ }
+ drm_dbg_kms(&dev_priv->drm, "Set TPS4 compliance Phy Test Pattern\n");
+ intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe), 0x0);
+ intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
+ DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
+ DP_TP_CTL_TRAIN_PAT4_SEL_TP4A | DP_TP_CTL_LINK_TRAIN_PAT4);
+ break;
default:
- WARN(1, "Invalid Phy Test Pattern\n");
+ drm_warn(&dev_priv->drm, "Invalid Phy Test Pattern\n");
}
}
intel_dp->train_set, crtc_state->lane_count);
drm_dp_set_phy_test_pattern(&intel_dp->aux, data,
- link_status[DP_DPCD_REV]);
+ intel_dp->dpcd[DP_DPCD_REV]);
}
static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
return connector_status_connected;
}
+void intel_digital_port_lock(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (dig_port->lock)
+ dig_port->lock(dig_port);
+}
+
+void intel_digital_port_unlock(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (dig_port->unlock)
+ dig_port->unlock(dig_port);
+}
+
/*
- * intel_digital_port_connected - is the specified port connected?
+ * intel_digital_port_connected_locked - is the specified port connected?
* @encoder: intel_encoder
*
* In cases where there's a connector physically connected but it can't be used
* pretty much treat the port as disconnected. This is relevant for type-C
* (starting on ICL) where there's ownership involved.
*
+ * The caller must hold the lock acquired by calling intel_digital_port_lock()
+ * when calling this function.
+ *
* Return %true if port is connected, %false otherwise.
*/
-bool intel_digital_port_connected(struct intel_encoder *encoder)
+bool intel_digital_port_connected_locked(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ bool is_glitch_free = intel_tc_port_handles_hpd_glitches(dig_port);
bool is_connected = false;
intel_wakeref_t wakeref;
- with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
- is_connected = dig_port->connected(encoder);
+ with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+ unsigned long wait_expires = jiffies + msecs_to_jiffies_timeout(4);
+
+ do {
+ is_connected = dig_port->connected(encoder);
+ if (is_connected || is_glitch_free)
+ break;
+ usleep_range(10, 30);
+ } while (time_before(jiffies, wait_expires));
+ }
return is_connected;
}
+bool intel_digital_port_connected(struct intel_encoder *encoder)
+{
+ bool ret;
+
+ intel_digital_port_lock(encoder);
+ ret = intel_digital_port_connected_locked(encoder);
+ intel_digital_port_unlock(encoder);
+
+ return ret;
+}
+
static const struct drm_edid *
intel_dp_get_edid(struct intel_dp *intel_dp)
{
if (!intel_display_device_enabled(dev_priv))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(dev_priv))
+ return connector->status;
+
/* Can't disconnect eDP */
if (intel_dp_is_edp(intel_dp))
status = edp_detect(intel_dp);
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
+
+ if (!intel_display_driver_check_access(dev_priv))
+ return;
+
intel_dp_unset_edid(intel_dp);
if (connector->status != connector_status_connected)
spin_unlock_irq(&i915->irq_lock);
if (need_work)
- queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
+ intel_hpd_schedule_detection(i915);
}
static const struct drm_connector_funcs intel_dp_connector_funcs = {
connector->interlace_allowed = true;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
+ intel_connector->base.polled = intel_connector->polled;
intel_connector_attach_encoder(intel_connector, intel_encoder);
"HDCP init failed, skipping.\n");
}
+ intel_dp->colorimetry_support =
+ intel_dp_get_colorimetry_status(intel_dp);
+
intel_dp->frl.is_trained = false;
intel_dp->frl.trained_rate_gbps = 0;
bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp);
bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
-void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state,
- struct drm_dp_vsc_sdp *vsc);
-void intel_write_dp_vsc_sdp(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- const struct drm_dp_vsc_sdp *vsc);
void intel_dp_set_infoframes(struct intel_encoder *encoder, bool enable,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
void intel_read_dp_sdp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
unsigned int type);
+void intel_digital_port_lock(struct intel_encoder *encoder);
+void intel_digital_port_unlock(struct intel_encoder *encoder);
bool intel_digital_port_connected(struct intel_encoder *encoder);
+bool intel_digital_port_connected_locked(struct intel_encoder *encoder);
int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
u8 dsc_max_bpc);
u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
#include "intel_bios.h"
#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_dp_aux_regs.h"
#include "intel_pps.h"
u32 aux_send_ctl_flags)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct intel_encoder *encoder = &dig_port->base;
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
- 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;
enum intel_display_power_domain aux_domain;
for (i = 0; i < ARRAY_SIZE(ch_data); i++)
ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
- if (is_tc_port) {
- intel_tc_port_lock(dig_port);
- /*
- * Abort transfers on a disconnected port as required by
- * DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX
- * timeouts that would otherwise happen.
- * TODO: abort the transfer on non-TC ports as well.
- */
- if (!intel_tc_port_connected_locked(&dig_port->base)) {
- ret = -ENXIO;
- goto out_unlock;
- }
+ intel_digital_port_lock(encoder);
+ /*
+ * Abort transfers on a disconnected port as required by
+ * DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX
+ * timeouts that would otherwise happen.
+ */
+ if (!intel_dp_is_edp(intel_dp) &&
+ !intel_digital_port_connected_locked(&dig_port->base)) {
+ ret = -ENXIO;
+ goto out_unlock;
}
aux_domain = intel_aux_power_domain(dig_port);
intel_pps_unlock(intel_dp, pps_wakeref);
intel_display_power_put_async(i915, aux_domain, aux_wakeref);
out_unlock:
- if (is_tc_port)
- intel_tc_port_unlock(dig_port);
+ intel_digital_port_unlock(encoder);
return ret;
}
#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_hdcp.h"
if (drm_connector_is_unregistered(connector))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(i915))
+ return connector->status;
+
return drm_dp_mst_detect_port(connector, ctx, &intel_dp->mst_mgr,
intel_connector->port);
}
if (!HAS_DSB(i915))
return NULL;
+ /* TODO: DSB is broken in Xe KMD, so disabling it until fixed */
+ if (!IS_ENABLED(I915))
+ return NULL;
+
dsb = kzalloc(sizeof(*dsb), GFP_KERNEL);
if (!dsb)
goto out;
#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_dvo.h"
#include "intel_dvo_dev.h"
if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(i915))
+ return connector->base.status;
+
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
}
if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS)
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
+ connector->base.polled = connector->polled;
drm_connector_init_with_ddc(&i915->drm, &connector->base,
&intel_dvo_connector_funcs,
const struct gmbus_pin *pins;
size_t size;
- if (INTEL_PCH_TYPE(i915) >= PCH_LNL) {
+ if (INTEL_PCH_TYPE(i915) >= PCH_MTL) {
pins = gmbus_pins_mtp;
size = ARRAY_SIZE(gmbus_pins_mtp);
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
pins = gmbus_pins_dg1;
size = ARRAY_SIZE(gmbus_pins_dg1);
- } else if (INTEL_PCH_TYPE(i915) >= PCH_MTP) {
- pins = gmbus_pins_mtp;
- size = ARRAY_SIZE(gmbus_pins_mtp);
} else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) {
pins = gmbus_pins_icp;
size = ARRAY_SIZE(gmbus_pins_icp);
default:
drm_err(&i915->drm, "Unknown transcoder %d\n",
cpu_transcoder);
- return -EINVAL;
+ return 0;
}
}
return HDCP_DDIE_REP_PRESENT | HDCP_DDIE_SHA1_M0;
default:
drm_err(&i915->drm, "Unknown port %d\n", port);
- return -EINVAL;
+ return 0;
}
}
if (shim->stream_encryption) {
ret = shim->stream_encryption(connector, true);
if (ret) {
- drm_err(&i915->drm, "[%s:%d] Failed to enable HDCP 1.4 stream enc\n",
- connector->base.name, connector->base.base.id);
+ drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to enable HDCP 1.4 stream enc\n",
+ connector->base.base.id, connector->base.name);
return ret;
}
drm_dbg_kms(&i915->drm, "HDCP 1.4 transcoder: %s stream encrypted\n",
u32 repeater_ctl;
int ret;
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP is being disabled...\n",
- connector->base.name, connector->base.base.id);
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP is being disabled...\n",
+ connector->base.base.id, connector->base.name);
if (hdcp->shim->stream_encryption) {
ret = hdcp->shim->stream_encryption(connector, false);
if (ret) {
- drm_err(&i915->drm, "[%s:%d] Failed to disable HDCP 1.4 stream enc\n",
- connector->base.name, connector->base.base.id);
+ drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to disable HDCP 1.4 stream enc\n",
+ connector->base.base.id, connector->base.name);
return ret;
}
drm_dbg_kms(&i915->drm, "HDCP 1.4 transcoder: %s stream encryption disabled\n",
struct intel_hdcp *hdcp = &connector->hdcp;
int i, ret, tries = 3;
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP is being enabled...\n",
- connector->base.name, connector->base.base.id);
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP is being enabled...\n",
+ connector->base.base.id, connector->base.name);
if (!hdcp_key_loadable(i915)) {
drm_err(&i915->drm, "HDCP key Load is not possible\n");
if (drm_WARN_ON(&i915->drm,
!intel_hdcp_in_use(i915, cpu_transcoder, port))) {
drm_err(&i915->drm,
- "%s:%d HDCP link stopped encryption,%x\n",
- connector->base.name, connector->base.base.id,
+ "[CONNECTOR:%d:%s] HDCP link stopped encryption,%x\n",
+ connector->base.base.id, connector->base.name,
intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)));
ret = -ENXIO;
intel_hdcp_update_value(connector,
}
drm_dbg_kms(&i915->drm,
- "[%s:%d] HDCP link failed, retrying authentication\n",
- connector->base.name, connector->base.base.id);
+ "[CONNECTOR:%d:%s] HDCP link failed, retrying authentication\n",
+ connector->base.base.id, connector->base.name);
ret = _intel_hdcp_disable(connector);
if (ret) {
!HDCP_2_2_HDCP1_DEVICE_CONNECTED(rx_info[1]) &&
!HDCP_2_2_HDCP_2_0_REP_CONNECTED(rx_info[1]);
+ if (!dig_port->hdcp_mst_type1_capable && hdcp->content_type) {
+ drm_dbg_kms(&i915->drm,
+ "HDCP1.x or 2.0 Legacy Device Downstream\n");
+ return -EINVAL;
+ }
+
/* Converting and Storing the seq_num_v to local variable as DWORD */
seq_num_v =
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v);
if (!(intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)) &
LINK_ENCRYPTION_STATUS)) {
- drm_err(&i915->drm, "[%s:%d] HDCP 2.2 Link is not encrypted\n",
- connector->base.name, connector->base.base.id);
+ drm_err(&i915->drm, "[CONNECTOR:%d:%s] HDCP 2.2 Link is not encrypted\n",
+ connector->base.base.id, connector->base.name);
ret = -EPERM;
goto link_recover;
}
if (hdcp->shim->stream_2_2_encryption) {
ret = hdcp->shim->stream_2_2_encryption(connector, true);
if (ret) {
- drm_err(&i915->drm, "[%s:%d] Failed to enable HDCP 2.2 stream enc\n",
- connector->base.name, connector->base.base.id);
+ drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to enable HDCP 2.2 stream enc\n",
+ connector->base.base.id, connector->base.name);
return ret;
}
drm_dbg_kms(&i915->drm, "HDCP 2.2 transcoder: %s stream encrypted\n",
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
- connector->base.name, connector->base.base.id,
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP2.2 is being enabled. Type: %d\n",
+ connector->base.base.id, connector->base.name,
hdcp->content_type);
ret = hdcp2_authenticate_and_encrypt(connector);
return ret;
}
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n",
- connector->base.name, connector->base.base.id,
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP2.2 is enabled. Type %d\n",
+ connector->base.base.id, connector->base.name,
hdcp->content_type);
hdcp->hdcp2_encrypted = true;
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being Disabled\n",
- connector->base.name, connector->base.base.id);
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP2.2 is being Disabled\n",
+ connector->base.base.id, connector->base.name);
if (hdcp->shim->stream_2_2_encryption) {
ret = hdcp->shim->stream_2_2_encryption(connector, false);
if (ret) {
- drm_err(&i915->drm, "[%s:%d] Failed to disable HDCP 2.2 stream enc\n",
- connector->base.name, connector->base.base.id);
+ drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to disable HDCP 2.2 stream enc\n",
+ connector->base.base.id, connector->base.name);
return ret;
}
drm_dbg_kms(&i915->drm, "HDCP 2.2 transcoder: %s stream encryption disabled\n",
goto out;
}
drm_dbg_kms(&i915->drm,
- "[%s:%d] Repeater topology auth failed.(%d)\n",
- connector->base.name, connector->base.base.id,
+ "[CONNECTOR:%d:%s] Repeater topology auth failed.(%d)\n",
+ connector->base.base.id, connector->base.name,
ret);
} else {
drm_dbg_kms(&i915->drm,
- "[%s:%d] HDCP2.2 link failed, retrying auth\n",
- connector->base.name, connector->base.base.id);
+ "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n",
+ connector->base.base.id, connector->base.name);
}
ret = _intel_hdcp2_disable(connector, true);
if (ret) {
drm_err(&i915->drm,
- "[%s:%d] Failed to disable hdcp2.2 (%d)\n",
- connector->base.name, connector->base.base.id, ret);
+ "[CONNECTOR:%d:%s] Failed to disable hdcp2.2 (%d)\n",
+ connector->base.base.id, connector->base.name, ret);
intel_hdcp_update_value(connector,
DRM_MODE_CONTENT_PROTECTION_DESIRED, true);
goto out;
ret = _intel_hdcp2_enable(connector);
if (ret) {
drm_dbg_kms(&i915->drm,
- "[%s:%d] Failed to enable hdcp2.2 (%d)\n",
- connector->base.name, connector->base.base.id,
+ "[CONNECTOR:%d:%s] Failed to enable hdcp2.2 (%d)\n",
+ connector->base.base.id, connector->base.name,
ret);
intel_hdcp_update_value(connector,
DRM_MODE_CONTENT_PROTECTION_DESIRED,
return -ENOENT;
if (!connector->encoder) {
- drm_err(&i915->drm, "[%s:%d] encoder is not initialized\n",
- connector->base.name, connector->base.base.id);
+ drm_err(&i915->drm, "[CONNECTOR:%d:%s] encoder is not initialized\n",
+ connector->base.base.id, connector->base.name);
return -ENODEV;
}
#include "intel_display_reg_defs.h"
+#define TRANS_HDCP(__i915) (DISPLAY_VER(__i915) >= 12)
+
/* HDCP Key Registers */
#define HDCP_KEY_CONF _MMIO(0x66c00)
#define HDCP_AKSV_SEND_TRIGGER REG_BIT(31)
#define TRANS_HDCP_CONF(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_CONF, \
_TRANSB_HDCP_CONF)
#define HDCP_CONF(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_CONF(trans) : \
PORT_HDCP_CONF(port))
_TRANSA_HDCP_ANINIT, \
_TRANSB_HDCP_ANINIT)
#define HDCP_ANINIT(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_ANINIT(trans) : \
PORT_HDCP_ANINIT(port))
#define TRANS_HDCP_ANLO(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANLO, \
_TRANSB_HDCP_ANLO)
#define HDCP_ANLO(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_ANLO(trans) : \
PORT_HDCP_ANLO(port))
#define TRANS_HDCP_ANHI(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANHI, \
_TRANSB_HDCP_ANHI)
#define HDCP_ANHI(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_ANHI(trans) : \
PORT_HDCP_ANHI(port))
_TRANSA_HDCP_BKSVLO, \
_TRANSB_HDCP_BKSVLO)
#define HDCP_BKSVLO(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_BKSVLO(trans) : \
PORT_HDCP_BKSVLO(port))
_TRANSA_HDCP_BKSVHI, \
_TRANSB_HDCP_BKSVHI)
#define HDCP_BKSVHI(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_BKSVHI(trans) : \
PORT_HDCP_BKSVHI(port))
_TRANSA_HDCP_RPRIME, \
_TRANSB_HDCP_RPRIME)
#define HDCP_RPRIME(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_RPRIME(trans) : \
PORT_HDCP_RPRIME(port))
_TRANSA_HDCP_STATUS, \
_TRANSB_HDCP_STATUS)
#define HDCP_STATUS(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP_STATUS(trans) : \
PORT_HDCP_STATUS(port))
#define AUTH_FORCE_CLR_INPUTCTR REG_BIT(19)
#define AUTH_CLR_KEYS REG_BIT(18)
#define HDCP2_AUTH(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP2_AUTH(trans) : \
PORT_HDCP2_AUTH(port))
_TRANSB_HDCP2_CTL)
#define CTL_LINK_ENCRYPTION_REQ REG_BIT(31)
#define HDCP2_CTL(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP2_CTL(trans) : \
PORT_HDCP2_CTL(port))
#define LINK_AUTH_STATUS REG_BIT(21)
#define LINK_ENCRYPTION_STATUS REG_BIT(20)
#define HDCP2_STATUS(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP2_STATUS(trans) : \
PORT_HDCP2_STATUS(port))
#define STREAM_ENCRYPTION_STATUS REG_BIT(31)
#define STREAM_TYPE_STATUS REG_BIT(30)
#define HDCP2_STREAM_STATUS(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP2_STREAM_STATUS(trans) : \
PIPE_HDCP2_STREAM_STATUS(pipe))
_TRANSB_HDCP2_AUTH_STREAM)
#define AUTH_STREAM_TYPE REG_BIT(31)
#define HDCP2_AUTH_STREAM(dev_priv, trans, port) \
- (GRAPHICS_VER(dev_priv) >= 12 ? \
+ (TRANS_HDCP(dev_priv) ? \
TRANS_HDCP2_AUTH_STREAM(trans) : \
PORT_HDCP2_AUTH_STREAM(port))
#include "intel_cx0_phy.h"
#include "intel_ddi.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_gmbus.h"
0);
/* Wa_14013475917 */
- if (IS_DISPLAY_VER(dev_priv, 13, 14) && crtc_state->has_psr && type == DP_SDP_VSC)
- return;
+ if (!(IS_DISPLAY_VER(dev_priv, 13, 14) && crtc_state->has_psr && type == DP_SDP_VSC))
+ val |= hsw_infoframe_enable(type);
+
+ if (type == DP_SDP_VSC)
+ val |= VSC_DIP_HW_DATA_SW_HEA;
- val |= hsw_infoframe_enable(type);
intel_de_write(dev_priv, ctl_reg, val);
intel_de_posting_read(dev_priv, ctl_reg);
}
if (!intel_display_device_enabled(dev_priv))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(dev_priv))
+ return connector->status;
+
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
if (DISPLAY_VER(dev_priv) >= 11 &&
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
+ if (!intel_display_driver_check_access(i915))
+ return;
+
intel_hdmi_unset_edid(connector);
if (connector->status != connector_status_connected)
connector->ycbcr_420_allowed = true;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
+ intel_connector->base.polled = intel_connector->polled;
if (HAS_DDI(dev_priv))
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
return storm;
}
+static bool detection_work_enabled(struct drm_i915_private *i915)
+{
+ lockdep_assert_held(&i915->irq_lock);
+
+ return i915->display.hotplug.detection_work_enabled;
+}
+
+static bool
+mod_delayed_detection_work(struct drm_i915_private *i915, struct delayed_work *work, int delay)
+{
+ lockdep_assert_held(&i915->irq_lock);
+
+ if (!detection_work_enabled(i915))
+ return false;
+
+ return mod_delayed_work(i915->unordered_wq, work, delay);
+}
+
+static bool
+queue_delayed_detection_work(struct drm_i915_private *i915, struct delayed_work *work, int delay)
+{
+ lockdep_assert_held(&i915->irq_lock);
+
+ if (!detection_work_enabled(i915))
+ return false;
+
+ return queue_delayed_work(i915->unordered_wq, work, delay);
+}
+
+static bool
+queue_detection_work(struct drm_i915_private *i915, struct work_struct *work)
+{
+ lockdep_assert_held(&i915->irq_lock);
+
+ if (!detection_work_enabled(i915))
+ return false;
+
+ return queue_work(i915->unordered_wq, work);
+}
+
static void
intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
{
/* Enable polling and queue hotplug re-enabling. */
if (hpd_disabled) {
drm_kms_helper_poll_reschedule(&dev_priv->drm);
- mod_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.reenable_work,
- msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
+ mod_delayed_detection_work(dev_priv,
+ &dev_priv->display.hotplug.reenable_work,
+ msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
}
}
if (old_bits) {
spin_lock_irq(&dev_priv->irq_lock);
dev_priv->display.hotplug.event_bits |= old_bits;
+ queue_delayed_detection_work(dev_priv,
+ &dev_priv->display.hotplug.hotplug_work, 0);
spin_unlock_irq(&dev_priv->irq_lock);
- queue_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.hotplug_work, 0);
}
}
if (retry) {
spin_lock_irq(&dev_priv->irq_lock);
dev_priv->display.hotplug.retry_bits |= retry;
- spin_unlock_irq(&dev_priv->irq_lock);
- mod_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.hotplug_work,
- msecs_to_jiffies(HPD_RETRY_DELAY));
+ mod_delayed_detection_work(dev_priv,
+ &dev_priv->display.hotplug.hotplug_work,
+ msecs_to_jiffies(HPD_RETRY_DELAY));
+ spin_unlock_irq(&dev_priv->irq_lock);
}
}
*/
if (storm_detected)
intel_hpd_irq_setup(dev_priv);
- spin_unlock(&dev_priv->irq_lock);
/*
* Our hotplug handler can grab modeset locks (by calling down into the
if (queue_dig)
queue_work(dev_priv->display.hotplug.dp_wq, &dev_priv->display.hotplug.dig_port_work);
if (queue_hp)
- queue_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.hotplug_work, 0);
+ queue_delayed_detection_work(dev_priv,
+ &dev_priv->display.hotplug.hotplug_work, 0);
+
+ spin_unlock(&dev_priv->irq_lock);
}
/**
cancel_work(&dev_priv->display.hotplug.poll_init_work);
}
+ spin_lock_irq(&dev_priv->irq_lock);
+
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
enum hpd_pin pin;
if (pin == HPD_NONE)
continue;
+ if (dev_priv->display.hotplug.stats[pin].state == HPD_DISABLED)
+ continue;
+
connector->base.polled = connector->polled;
if (enabled && connector->base.polled == DRM_CONNECTOR_POLL_HPD)
}
drm_connector_list_iter_end(&conn_iter);
+ spin_unlock_irq(&dev_priv->irq_lock);
+
if (enabled)
drm_kms_helper_poll_reschedule(&dev_priv->drm);
* As well, there's no issue if we race here since we always reschedule
* this worker anyway
*/
- queue_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.poll_init_work);
+ spin_lock_irq(&dev_priv->irq_lock);
+ queue_detection_work(dev_priv,
+ &dev_priv->display.hotplug.poll_init_work);
+ spin_unlock_irq(&dev_priv->irq_lock);
}
/**
return;
WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, false);
- queue_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.poll_init_work);
+
+ spin_lock_irq(&dev_priv->irq_lock);
+ queue_detection_work(dev_priv,
+ &dev_priv->display.hotplug.poll_init_work);
+ spin_unlock_irq(&dev_priv->irq_lock);
}
void intel_hpd_init_early(struct drm_i915_private *i915)
i915->display.hotplug.hpd_short_storm_enabled = !HAS_DP_MST(i915);
}
+static bool cancel_all_detection_work(struct drm_i915_private *i915)
+{
+ bool was_pending = false;
+
+ if (cancel_delayed_work_sync(&i915->display.hotplug.hotplug_work))
+ was_pending = true;
+ if (cancel_work_sync(&i915->display.hotplug.poll_init_work))
+ was_pending = true;
+ if (cancel_delayed_work_sync(&i915->display.hotplug.reenable_work))
+ was_pending = true;
+
+ return was_pending;
+}
+
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
{
if (!HAS_DISPLAY(dev_priv))
spin_unlock_irq(&dev_priv->irq_lock);
cancel_work_sync(&dev_priv->display.hotplug.dig_port_work);
- cancel_delayed_work_sync(&dev_priv->display.hotplug.hotplug_work);
- cancel_work_sync(&dev_priv->display.hotplug.poll_init_work);
- cancel_delayed_work_sync(&dev_priv->display.hotplug.reenable_work);
+
+ /*
+ * All other work triggered by hotplug events should be canceled by
+ * now.
+ */
+ if (cancel_all_detection_work(dev_priv))
+ drm_dbg_kms(&dev_priv->drm, "Hotplug detection work still active\n");
}
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
spin_unlock_irq(&dev_priv->irq_lock);
}
+static void queue_work_for_missed_irqs(struct drm_i915_private *i915)
+{
+ bool queue_work = false;
+ enum hpd_pin pin;
+
+ lockdep_assert_held(&i915->irq_lock);
+
+ if (i915->display.hotplug.event_bits ||
+ i915->display.hotplug.retry_bits)
+ queue_work = true;
+
+ for_each_hpd_pin(pin) {
+ switch (i915->display.hotplug.stats[pin].state) {
+ case HPD_MARK_DISABLED:
+ queue_work = true;
+ break;
+ case HPD_ENABLED:
+ break;
+ default:
+ MISSING_CASE(i915->display.hotplug.stats[pin].state);
+ }
+ }
+
+ if (queue_work)
+ queue_delayed_detection_work(i915, &i915->display.hotplug.hotplug_work, 0);
+}
+
+void intel_hpd_enable_detection_work(struct drm_i915_private *i915)
+{
+ spin_lock_irq(&i915->irq_lock);
+ i915->display.hotplug.detection_work_enabled = true;
+ queue_work_for_missed_irqs(i915);
+ spin_unlock_irq(&i915->irq_lock);
+}
+
+void intel_hpd_disable_detection_work(struct drm_i915_private *i915)
+{
+ spin_lock_irq(&i915->irq_lock);
+ i915->display.hotplug.detection_work_enabled = false;
+ spin_unlock_irq(&i915->irq_lock);
+
+ cancel_all_detection_work(i915);
+}
+
+bool intel_hpd_schedule_detection(struct drm_i915_private *i915)
+{
+ unsigned long flags;
+ bool ret;
+
+ spin_lock_irqsave(&i915->irq_lock, flags);
+ ret = queue_delayed_detection_work(i915, &i915->display.hotplug.hotplug_work, 0);
+ spin_unlock_irqrestore(&i915->irq_lock, flags);
+
+ return ret;
+}
+
static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
void intel_hpd_debugfs_register(struct drm_i915_private *i915);
+void intel_hpd_enable_detection_work(struct drm_i915_private *i915);
+void intel_hpd_disable_detection_work(struct drm_i915_private *i915);
+bool intel_hpd_schedule_detection(struct drm_i915_private *i915);
+
#endif /* __INTEL_HOTPLUG_H__ */
(!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
return;
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_LNL)
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTL)
hpd->pch_hpd = hpd_mtp;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
hpd->pch_hpd = hpd_sde_dg1;
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
- hpd->pch_hpd = hpd_mtp;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
hpd->pch_hpd = hpd_icp;
else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
if (INTEL_PCH_TYPE(i915) >= PCH_LNL)
xe2lpd_sde_hpd_irq_setup(i915);
- else if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
+ else if (INTEL_PCH_TYPE(i915) >= PCH_MTL)
mtp_hpd_irq_setup(i915);
}
#include "intel_backlight.h"
#include "intel_connector.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_drrs.h"
#include "intel_lvds_regs.h"
if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(i915))
+ return connector->status;
+
return connector_status_connected;
}
if (intel_dp->pps.pps_idx == 1 &&
INTEL_PCH_TYPE(i915) >= PCH_ICP &&
- INTEL_PCH_TYPE(i915) < PCH_MTP)
+ INTEL_PCH_TYPE(i915) <= PCH_ADP)
return intel_de_read(i915, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT;
return true;
* irrelevant for normal operation.
*/
+#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
+ (intel_dp)->psr.source_support)
+
+#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support && \
+ (intel_dp)->psr.source_panel_replay_support)
+
bool intel_encoder_can_psr(struct intel_encoder *encoder)
{
if (intel_encoder_is_dp(encoder) || encoder->type == INTEL_OUTPUT_DP_MST)
intel_dp_get_sink_sync_latency(intel_dp);
if (DISPLAY_VER(i915) >= 9 &&
- intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
+ intel_dp->psr_dpcd[0] >= DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
bool y_req = intel_dp->psr_dpcd[1] &
DP_PSR2_SU_Y_COORDINATE_REQUIRED;
bool alpm = intel_dp_get_alpm_status(intel_dp);
if (intel_dp->psr_dpcd[0])
_psr_init_dpcd(intel_dp);
- if (intel_dp->psr.sink_psr2_support) {
- intel_dp->psr.colorimetry_support =
- intel_dp_get_colorimetry_status(intel_dp);
+ if (intel_dp->psr.sink_psr2_support)
intel_dp_get_su_granularity(intel_dp);
- }
}
static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
aux_ctl);
}
+static bool psr2_su_region_et_valid(struct intel_dp *intel_dp)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ if (DISPLAY_VER(i915) >= 20 &&
+ intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED &&
+ !(intel_dp->psr.debug & I915_PSR_DEBUG_SU_REGION_ET_DISABLE))
+ return true;
+
+ return false;
+}
+
static void intel_psr_enable_sink(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS;
+ if (psr2_su_region_et_valid(intel_dp))
+ dpcd_val |= DP_PSR_ENABLE_SU_REGION_ET;
} else {
if (intel_dp->psr.link_standby)
dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE;
intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), 0);
}
+ if (psr2_su_region_et_valid(intel_dp))
+ val |= LNL_EDP_PSR2_SU_REGION_ET_ENABLE;
+
/*
* PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is
* recommending keep this bit unset while PSR2 is enabled.
return false;
}
+ if (psr2_su_region_et_valid(intel_dp))
+ crtc_state->enable_psr2_su_region_et = true;
+
return crtc_state->enable_psr2_sel_fetch = true;
}
return;
crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
-
- crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC);
- intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state,
- &crtc_state->psr_vsc);
}
void intel_psr_get_config(struct intel_encoder *encoder,
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
- struct intel_encoder *encoder = &dig_port->base;
u32 val;
drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled);
drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n",
intel_dp->psr.psr2_enabled ? "2" : "1");
- intel_write_dp_vsc_sdp(encoder, crtc_state, &crtc_state->psr_vsc);
intel_snps_phy_update_psr_power_state(dev_priv, phy, true);
intel_psr_enable_sink(intel_dp);
intel_psr_enable_source(intel_dp, crtc_state);
}
static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
- struct drm_rect *clip, bool full_update)
+ bool full_update)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
goto exit;
}
- if (clip->y1 == -1)
+ if (crtc_state->psr2_su_area.y1 == -1)
goto exit;
if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) {
- val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1);
- val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 - 1);
+ val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(crtc_state->psr2_su_area.y1);
+ val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(crtc_state->psr2_su_area.y2 - 1);
} else {
- drm_WARN_ON(crtc_state->uapi.crtc->dev, clip->y1 % 4 || clip->y2 % 4);
+ drm_WARN_ON(crtc_state->uapi.crtc->dev,
+ crtc_state->psr2_su_area.y1 % 4 ||
+ crtc_state->psr2_su_area.y2 % 4);
- val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1 / 4 + 1);
- val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 / 4 + 1);
+ val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(
+ crtc_state->psr2_su_area.y1 / 4 + 1);
+ val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(
+ crtc_state->psr2_su_area.y2 / 4 + 1);
}
exit:
crtc_state->psr2_man_track_ctl = val;
overlap_damage_area->y2 = damage_area->y2;
}
-static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *crtc_state,
- struct drm_rect *pipe_clip)
+static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
else
y_alignment = crtc_state->su_y_granularity;
- pipe_clip->y1 -= pipe_clip->y1 % y_alignment;
- if (pipe_clip->y2 % y_alignment)
- pipe_clip->y2 = ((pipe_clip->y2 / y_alignment) + 1) * y_alignment;
+ crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment;
+ if (crtc_state->psr2_su_area.y2 % y_alignment)
+ crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 /
+ y_alignment) + 1) * y_alignment;
+}
+
+/*
+ * When early transport is in use we need to extend SU area to cover
+ * cursor fully when cursor is in SU area.
+ */
+static void
+intel_psr2_sel_fetch_et_alignment(struct intel_crtc_state *crtc_state,
+ struct intel_plane_state *cursor_state)
+{
+ struct drm_rect inter;
+
+ if (!crtc_state->enable_psr2_su_region_et ||
+ !cursor_state->uapi.visible)
+ return;
+
+ inter = crtc_state->psr2_su_area;
+ if (!drm_rect_intersect(&inter, &cursor_state->uapi.dst))
+ return;
+
+ clip_area_update(&crtc_state->psr2_su_area, &cursor_state->uapi.dst,
+ &crtc_state->pipe_src);
}
/*
{
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 drm_rect pipe_clip = { .x1 = 0, .y1 = -1, .x2 = INT_MAX, .y2 = -1 };
- struct intel_plane_state *new_plane_state, *old_plane_state;
+ struct intel_plane_state *new_plane_state, *old_plane_state,
+ *cursor_plane_state = NULL;
struct intel_plane *plane;
bool full_update = false;
int i, ret;
goto skip_sel_fetch_set_loop;
}
+ crtc_state->psr2_su_area.x1 = 0;
+ crtc_state->psr2_su_area.y1 = -1;
+ crtc_state->psr2_su_area.x2 = INT_MAX;
+ crtc_state->psr2_su_area.y2 = -1;
+
/*
* Calculate minimal selective fetch area of each plane and calculate
* the pipe damaged area.
if (old_plane_state->uapi.visible) {
damaged_area.y1 = old_plane_state->uapi.dst.y1;
damaged_area.y2 = old_plane_state->uapi.dst.y2;
- clip_area_update(&pipe_clip, &damaged_area,
+ clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
&crtc_state->pipe_src);
}
if (new_plane_state->uapi.visible) {
damaged_area.y1 = new_plane_state->uapi.dst.y1;
damaged_area.y2 = new_plane_state->uapi.dst.y2;
- clip_area_update(&pipe_clip, &damaged_area,
+ clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
&crtc_state->pipe_src);
}
continue;
/* If alpha changed mark the whole plane area as damaged */
damaged_area.y1 = new_plane_state->uapi.dst.y1;
damaged_area.y2 = new_plane_state->uapi.dst.y2;
- clip_area_update(&pipe_clip, &damaged_area,
+ clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
&crtc_state->pipe_src);
continue;
}
damaged_area.x1 += new_plane_state->uapi.dst.x1 - src.x1;
damaged_area.x2 += new_plane_state->uapi.dst.x1 - src.x1;
- clip_area_update(&pipe_clip, &damaged_area, &crtc_state->pipe_src);
+ clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &crtc_state->pipe_src);
+
+ /*
+ * Cursor plane new state is stored to adjust su area to cover
+ * cursor are fully.
+ */
+ if (plane->id == PLANE_CURSOR)
+ cursor_plane_state = new_plane_state;
}
/*
* should identify cases where this happens and fix the area
* calculation for those.
*/
- if (pipe_clip.y1 == -1) {
+ if (crtc_state->psr2_su_area.y1 == -1) {
drm_info_once(&dev_priv->drm,
"Selective fetch area calculation failed in pipe %c\n",
pipe_name(crtc->pipe));
if ((IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
crtc_state->splitter.enable)
- pipe_clip.y1 = 0;
+ crtc_state->psr2_su_area.y1 = 0;
ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
if (ret)
return ret;
- intel_psr2_sel_fetch_pipe_alignment(crtc_state, &pipe_clip);
+ /* Adjust su area to cover cursor fully as necessary */
+ if (cursor_plane_state)
+ intel_psr2_sel_fetch_et_alignment(crtc_state, cursor_plane_state);
+
+ intel_psr2_sel_fetch_pipe_alignment(crtc_state);
/*
* Now that we have the pipe damaged area check if it intersect with
!new_plane_state->uapi.visible)
continue;
- inter = pipe_clip;
+ inter = crtc_state->psr2_su_area;
sel_fetch_area = &new_plane_state->psr2_sel_fetch_area;
if (!drm_rect_intersect(&inter, &new_plane_state->uapi.dst)) {
sel_fetch_area->y1 = -1;
}
skip_sel_fetch_set_loop:
- psr2_man_trk_ctl_calc(crtc_state, &pipe_clip, full_update);
+ psr2_man_trk_ctl_calc(crtc_state, full_update);
return 0;
}
else
intel_dp->psr.source_support = true;
+ /* Disable early transport for now */
+ intel_dp->psr.debug |= I915_PSR_DEBUG_SU_REGION_ET_DISABLE;
+
/* Set link_standby x link_off defaults */
if (DISPLAY_VER(dev_priv) < 12)
/* For new platforms up to TGL let's respect VBT back again */
struct intel_plane;
struct intel_plane_state;
-#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
- (intel_dp)->psr.source_support)
-
-#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support && \
- (intel_dp)->psr.source_panel_replay_support)
-
bool intel_encoder_can_psr(struct intel_encoder *encoder);
void intel_psr_init_dpcd(struct intel_dp *intel_dp);
void intel_psr_pre_plane_update(struct intel_atomic_state *state,
#define TGL_EDP_PSR2_BLOCK_COUNT_MASK REG_BIT(28)
#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_2 REG_FIELD_PREP(TGL_EDP_PSR2_BLOCK_COUNT_MASK, 0)
#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_3 REG_FIELD_PREP(TGL_EDP_PSR2_BLOCK_COUNT_MASK, 1)
+#define LNL_EDP_PSR2_SU_REGION_ET_ENABLE REG_BIT(27)
#define EDP_Y_COORDINATE_ENABLE REG_BIT(25) /* display 10, 11 and 12 */
#define EDP_PSR2_SU_SDP_SCANLINE REG_BIT(25) /* display 13+ */
#define EDP_MAX_SU_DISABLE_TIME_MASK REG_GENMASK(24, 20)
#define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14)
#define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13)
+/* PSR2 Early transport */
+#define _PIPE_SRCSZ_ERLY_TPT_A 0x70074
+
+#define PIPE_SRCSZ_ERLY_TPT(trans) _MMIO_TRANS2(trans, _PIPE_SRCSZ_ERLY_TPT_A)
+
#define _SEL_FETCH_PLANE_BASE_1_A 0x70890
#define _SEL_FETCH_PLANE_BASE_2_A 0x708B0
#define _SEL_FETCH_PLANE_BASE_3_A 0x708D0
#include "intel_connector.h"
#include "intel_crtc.h"
#include "intel_de.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(i915))
+ return connector->status;
+
if (!intel_sdvo_set_target_output(intel_sdvo,
intel_sdvo_connector->output_flag))
return connector_status_unknown;
} else {
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
}
+ intel_connector->base.polled = intel_connector->polled;
encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
intel_connector = &intel_sdvo_connector->base;
connector = &intel_connector->base;
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+ intel_connector->base.polled = intel_connector->polled;
encoder->encoder_type = DRM_MODE_ENCODER_DAC;
connector->connector_type = DRM_MODE_CONNECTOR_VGA;
return intel_tc_port_in_mode(dig_port, TC_PORT_LEGACY);
}
+bool intel_tc_port_handles_hpd_glitches(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+ struct intel_tc_port *tc = to_tc_port(dig_port);
+
+ return intel_phy_is_tc(i915, phy) && !tc->legacy_port;
+}
+
/*
* The display power domains used for TC ports depending on the
* platform and TC mode (legacy, DP-alt, TBT):
* connected ports are usable, and avoids exposing to the users objects they
* can't really use.
*/
-bool intel_tc_port_connected_locked(struct intel_encoder *encoder)
+bool intel_tc_port_connected(struct intel_encoder *encoder)
{
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
return tc_phy_hpd_live_status(tc) & mask;
}
-bool intel_tc_port_connected(struct intel_encoder *encoder)
-{
- struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
- struct intel_tc_port *tc = to_tc_port(dig_port);
- bool is_connected;
-
- mutex_lock(&tc->lock);
- is_connected = intel_tc_port_connected_locked(encoder);
- mutex_unlock(&tc->lock);
-
- return is_connected;
-}
-
static bool __intel_tc_port_link_needs_reset(struct intel_tc_port *tc)
{
bool ret;
bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port);
bool intel_tc_port_in_dp_alt_mode(struct intel_digital_port *dig_port);
bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port);
+bool intel_tc_port_handles_hpd_glitches(struct intel_digital_port *dig_port);
bool intel_tc_port_connected(struct intel_encoder *encoder);
-bool intel_tc_port_connected_locked(struct intel_encoder *encoder);
u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port);
int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port);
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_irq.h"
+#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_dpll.h"
#include "intel_hotplug.h"
* the active portion. Hence following this formula seems
* more trouble that it's worth.
*
- * if (GRAPHICS_VER(dev_priv) == 4) {
+ * if (DISPLAY_VER(dev_priv) == 4) {
* num = cdclk * (tv_mode->oversample >> !tv_mode->progressive);
* den = tv_mode->clock;
* } else {
if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
+ if (!intel_display_driver_check_access(i915))
+ return connector->status;
+
if (force) {
struct drm_atomic_state *state;
* More recent chipsets favour HDMI rather than integrated S-Video.
*/
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+ intel_connector->base.polled = intel_connector->polled;
drm_connector_init(&dev_priv->drm, connector, &intel_tv_connector_funcs,
DRM_MODE_CONNECTOR_SVIDEO);
}
if (err) {
- drm_dbg(dev, "Unable to make resource CPU accessible(err = %pe)\n",
- ERR_PTR(err));
+ drm_dbg_ratelimited(dev,
+ "Unable to make resource CPU accessible(err = %pe)\n",
+ ERR_PTR(err));
dma_resv_unlock(bo->base.resv);
ret = VM_FAULT_SIGBUS;
goto out_rpm;
intel_runtime_pm_disable(&i915->runtime_pm);
intel_power_domains_disable(i915);
+ intel_fbdev_set_suspend(&i915->drm, FBINFO_STATE_SUSPENDED, true);
if (HAS_DISPLAY(i915)) {
drm_kms_helper_poll_disable(&i915->drm);
+ intel_display_driver_disable_user_access(i915);
drm_atomic_helper_shutdown(&i915->drm);
}
intel_runtime_pm_disable_interrupts(i915);
intel_hpd_cancel_work(i915);
+ if (HAS_DISPLAY(i915))
+ intel_display_driver_suspend_access(i915);
+
intel_suspend_encoders(i915);
intel_shutdown_encoders(i915);
/* We do a lot of poking in a lot of registers, make sure they work
* properly. */
intel_power_domains_disable(dev_priv);
- if (HAS_DISPLAY(dev_priv))
+ intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
+ if (HAS_DISPLAY(dev_priv)) {
drm_kms_helper_poll_disable(dev);
+ intel_display_driver_disable_user_access(dev_priv);
+ }
pci_save_state(pdev);
intel_runtime_pm_disable_interrupts(dev_priv);
intel_hpd_cancel_work(dev_priv);
+ if (HAS_DISPLAY(dev_priv))
+ intel_display_driver_suspend_access(dev_priv);
+
intel_suspend_encoders(dev_priv);
/* Must be called before GGTT is suspended. */
opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
intel_opregion_suspend(dev_priv, opregion_target_state);
- intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
-
dev_priv->suspend_count++;
intel_dmc_suspend(dev_priv);
intel_display_driver_init_hw(dev_priv);
intel_clock_gating_init(dev_priv);
+
+ if (HAS_DISPLAY(dev_priv))
+ intel_display_driver_resume_access(dev_priv);
+
intel_hpd_init(dev_priv);
/* MST sideband requires HPD interrupts enabled */
intel_dp_mst_resume(dev_priv);
intel_display_driver_resume(dev_priv);
- intel_hpd_poll_disable(dev_priv);
- if (HAS_DISPLAY(dev_priv))
+ if (HAS_DISPLAY(dev_priv)) {
+ intel_display_driver_enable_user_access(dev_priv);
drm_kms_helper_poll_enable(dev);
+ }
+ intel_hpd_poll_disable(dev_priv);
intel_opregion_resume(dev_priv);
#define MCURSOR_MODE_64_ARGB_AX (0x20 | MCURSOR_MODE_64_32B_AX)
#define _CURABASE 0x70084
#define _CURAPOS 0x70088
+#define _CURAPOS_ERLY_TPT 0x7008c
#define CURSOR_POS_Y_SIGN REG_BIT(31)
#define CURSOR_POS_Y_MASK REG_GENMASK(30, 16)
#define CURSOR_POS_Y(y) REG_FIELD_PREP(CURSOR_POS_Y_MASK, (y))
#define CURCNTR(pipe) _MMIO_CURSOR2(pipe, _CURACNTR)
#define CURBASE(pipe) _MMIO_CURSOR2(pipe, _CURABASE)
#define CURPOS(pipe) _MMIO_CURSOR2(pipe, _CURAPOS)
+#define CURPOS_ERLY_TPT(pipe) _MMIO_CURSOR2(pipe, _CURAPOS_ERLY_TPT)
#define CURSIZE(pipe) _MMIO_CURSOR2(pipe, _CURASIZE)
#define CUR_FBC_CTL(pipe) _MMIO_CURSOR2(pipe, _CUR_FBC_CTL_A)
#define CUR_CHICKEN(pipe) _MMIO_CURSOR2(pipe, _CUR_CHICKEN_A)
#define DP_TP_CTL_MODE_SST (0 << 27)
#define DP_TP_CTL_MODE_MST (1 << 27)
#define DP_TP_CTL_FORCE_ACT (1 << 25)
+#define DP_TP_CTL_TRAIN_PAT4_SEL_MASK (3 << 19)
+#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4A (0 << 19)
+#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4B (1 << 19)
+#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4C (2 << 19)
#define DP_TP_CTL_ENHANCED_FRAME_ENABLE (1 << 18)
#define DP_TP_CTL_FDI_AUTOTRAIN (1 << 15)
#define DP_TP_CTL_LINK_TRAIN_MASK (7 << 8)
drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) &&
!IS_ALDERLAKE_P(dev_priv));
return PCH_ADP;
- case INTEL_PCH_MTP_DEVICE_ID_TYPE:
- case INTEL_PCH_MTP2_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Meteor Lake PCH\n");
- drm_WARN_ON(&dev_priv->drm, !IS_METEORLAKE(dev_priv));
- return PCH_MTP;
default:
return PCH_NONE;
}
* make an educated guess as to which PCH is really there.
*/
- if (IS_METEORLAKE(dev_priv))
- id = INTEL_PCH_MTP_DEVICE_ID_TYPE;
- else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
+ if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
id = INTEL_PCH_ADP_DEVICE_ID_TYPE;
else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv))
id = INTEL_PCH_TGP_DEVICE_ID_TYPE;
if (DISPLAY_VER(dev_priv) >= 20) {
dev_priv->pch_type = PCH_LNL;
return;
+ } else if (IS_METEORLAKE(dev_priv)) {
+ /*
+ * Both north display and south display are on the SoC die.
+ * The real PCH is uninvolved in display.
+ */
+ dev_priv->pch_type = PCH_MTL;
+ return;
} else if (IS_DG2(dev_priv)) {
dev_priv->pch_type = PCH_DG2;
return;
PCH_ICP, /* Ice Lake/Jasper Lake PCH */
PCH_TGP, /* Tiger Lake/Mule Creek Canyon PCH */
PCH_ADP, /* Alder Lake PCH */
- PCH_MTP, /* Meteor Lake PCH */
/* Fake PCHs, functionality handled on the same PCI dev */
PCH_DG1 = 1024,
PCH_DG2,
+ PCH_MTL,
PCH_LNL,
};
#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180
#define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00
#define INTEL_PCH_ADP4_DEVICE_ID_TYPE 0x5480
-#define INTEL_PCH_MTP_DEVICE_ID_TYPE 0x7E00
-#define INTEL_PCH_MTP2_DEVICE_ID_TYPE 0xAE00
#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000
#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */
#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type)
#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id)
-#define HAS_PCH_LNL(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LNL)
-#define HAS_PCH_MTP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_MTP)
#define HAS_PCH_DG2(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG2)
#define HAS_PCH_ADP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ADP)
#define HAS_PCH_DG1(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG1)
# define DP_PSR_SU_REGION_SCANLINE_CAPTURE BIT(4) /* eDP 1.4a */
# define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS BIT(5) /* eDP 1.4a */
# define DP_PSR_ENABLE_PSR2 BIT(6) /* eDP 1.4a */
+# define DP_PSR_ENABLE_SU_REGION_ET BIT(7) /* eDP 1.5 */
#define DP_ADAPTER_CTRL 0x1a0
# define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0)
drm_dev_printk(drm_ ? drm_->dev : NULL, KERN_DEBUG, fmt, ## __VA_ARGS__); \
})
+#define drm_dbg_ratelimited(drm, fmt, ...) \
+ __DRM_DEFINE_DBG_RATELIMITED(DRIVER, drm, fmt, ## __VA_ARGS__)
+
#define drm_dbg_kms_ratelimited(drm, fmt, ...) \
__DRM_DEFINE_DBG_RATELIMITED(KMS, drm, fmt, ## __VA_ARGS__)