From da00bdcfb25989afc025274fecbdcbfd9a24d3a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 11 Nov 2015 20:34:13 +0200 Subject: [PATCH] drm/i915: Remove the magic AUX_CTL is at DP + foo tricks MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Currently we determine the location of the AUX registers in a confusing way. First we assume the PCH registers are used always, but then we override it for everything but HSW/BDW to use DP+0x10. Very confusing. Let's just make it straightforward and simply add a few functions to pick the right AUX_CTL based on the DP port. To deal with VLV/CHV we'll include the display_mmio_offset into the AUX register defines. v2: Reorder patches (Chris) Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1447266856-30249-5-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_reg.h | 54 +++++++------- drivers/gpu/drm/i915/intel_dp.c | 127 ++++++++++++++++++++------------ 2 files changed, 105 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 81dd27a601f9..85d8878d043b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4228,33 +4228,33 @@ enum skl_disp_power_wells { * is 20 bytes in each direction, hence the 5 fixed * data registers */ -#define _DPA_AUX_CH_CTL 0x64010 -#define _DPA_AUX_CH_DATA1 0x64014 -#define _DPA_AUX_CH_DATA2 0x64018 -#define _DPA_AUX_CH_DATA3 0x6401c -#define _DPA_AUX_CH_DATA4 0x64020 -#define _DPA_AUX_CH_DATA5 0x64024 - -#define _DPB_AUX_CH_CTL 0x64110 -#define _DPB_AUX_CH_DATA1 0x64114 -#define _DPB_AUX_CH_DATA2 0x64118 -#define _DPB_AUX_CH_DATA3 0x6411c -#define _DPB_AUX_CH_DATA4 0x64120 -#define _DPB_AUX_CH_DATA5 0x64124 - -#define _DPC_AUX_CH_CTL 0x64210 -#define _DPC_AUX_CH_DATA1 0x64214 -#define _DPC_AUX_CH_DATA2 0x64218 -#define _DPC_AUX_CH_DATA3 0x6421c -#define _DPC_AUX_CH_DATA4 0x64220 -#define _DPC_AUX_CH_DATA5 0x64224 - -#define _DPD_AUX_CH_CTL 0x64310 -#define _DPD_AUX_CH_DATA1 0x64314 -#define _DPD_AUX_CH_DATA2 0x64318 -#define _DPD_AUX_CH_DATA3 0x6431c -#define _DPD_AUX_CH_DATA4 0x64320 -#define _DPD_AUX_CH_DATA5 0x64324 +#define _DPA_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64010) +#define _DPA_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64014) +#define _DPA_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64018) +#define _DPA_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6401c) +#define _DPA_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64020) +#define _DPA_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64024) + +#define _DPB_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64110) +#define _DPB_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64114) +#define _DPB_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64118) +#define _DPB_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6411c) +#define _DPB_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64120) +#define _DPB_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64124) + +#define _DPC_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64210) +#define _DPC_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64214) +#define _DPC_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64218) +#define _DPC_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6421c) +#define _DPC_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64220) +#define _DPC_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64224) + +#define _DPD_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64310) +#define _DPD_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64314) +#define _DPD_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64318) +#define _DPD_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6431c) +#define _DPD_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64320) +#define _DPD_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64324) #define DP_AUX_CH_CTL(port) _PORT(port, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL) #define DP_AUX_CH_DATA(port, i) (_PORT(port, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b07660cbbeff..555508457632 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1008,6 +1008,78 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return ret; } +static uint32_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ + switch (port) { + case PORT_B: + case PORT_C: + case PORT_D: + return DP_AUX_CH_CTL(port); + default: + MISSING_CASE(port); + return DP_AUX_CH_CTL(PORT_B); + } +} + +static uint32_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ + switch (port) { + case PORT_A: + return DP_AUX_CH_CTL(port); + case PORT_B: + case PORT_C: + case PORT_D: + return PCH_DP_AUX_CH_CTL(port); + default: + MISSING_CASE(port); + return DP_AUX_CH_CTL(PORT_A); + } +} + +/* + * On SKL we don't have Aux for port E so we rely + * on VBT to set a proper alternate aux channel. + */ +static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv) +{ + const struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[PORT_E]; + + switch (info->alternate_aux_channel) { + case DP_AUX_A: + return PORT_A; + case DP_AUX_B: + return PORT_B; + case DP_AUX_C: + return PORT_C; + case DP_AUX_D: + return PORT_D; + default: + MISSING_CASE(info->alternate_aux_channel); + return PORT_A; + } +} + +static uint32_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port == PORT_E) + port = skl_porte_aux_port(dev_priv); + + switch (port) { + case PORT_A: + case PORT_B: + case PORT_C: + case PORT_D: + return DP_AUX_CH_CTL(port); + default: + MISSING_CASE(port); + return DP_AUX_CH_CTL(PORT_A); + } +} + static void intel_dp_aux_fini(struct intel_dp *intel_dp) { @@ -1022,57 +1094,14 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; - struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; - uint32_t porte_aux_ctl_reg = DP_AUX_CH_CTL(PORT_A); int ret; - /* On SKL we don't have Aux for port E so we rely on VBT to set - * a proper alternate aux channel. - */ - if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && port == PORT_E) { - switch (info->alternate_aux_channel) { - case DP_AUX_B: - porte_aux_ctl_reg = DP_AUX_CH_CTL(PORT_B); - break; - case DP_AUX_C: - porte_aux_ctl_reg = DP_AUX_CH_CTL(PORT_C); - break; - case DP_AUX_D: - porte_aux_ctl_reg = DP_AUX_CH_CTL(PORT_D); - break; - case DP_AUX_A: - default: - porte_aux_ctl_reg = DP_AUX_CH_CTL(PORT_A); - } - } - - switch (port) { - case PORT_A: - intel_dp->aux_ch_ctl_reg = DP_AUX_CH_CTL(port); - break; - case PORT_B: - case PORT_C: - case PORT_D: - intel_dp->aux_ch_ctl_reg = PCH_DP_AUX_CH_CTL(port); - break; - case PORT_E: - intel_dp->aux_ch_ctl_reg = porte_aux_ctl_reg; - break; - default: - BUG(); - } - - /* - * The AUX_CTL register is usually DP_CTL + 0x10. - * - * On Haswell and Broadwell though: - * - Both port A DDI_BUF_CTL and DDI_AUX_CTL are on the CPU - * - Port B/C/D AUX channels are on the PCH, DDI_BUF_CTL on the CPU - * - * Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU. - */ - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev) && port != PORT_E) - intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; + if (INTEL_INFO(dev_priv)->gen >= 9) + intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg(dev_priv, port); + else if (HAS_PCH_SPLIT(dev_priv)) + intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg(dev_priv, port); + else + intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg(dev_priv, port); intel_dp->aux.name = kasprintf(GFP_KERNEL, "DPDDC-%c", port_name(port)); if (!intel_dp->aux.name) -- 2.20.1