Commit 0bdf5a05 authored by Takashi Iwai's avatar Takashi Iwai

drm/i915: Add reverse mapping between port and intel_encoder

This patch adds a reverse mapping from a digital port number to
intel_encoder object containing the corresponding intel_digital_port.
It simplifies the query of the encoder a lot.

Note that, even if it's a valid digital port, the dig_port_map[] might
point still to NULL -- usually it implies a DP MST port.  Due to this
fact, the NULL check in each place has no WARN_ON() and just skips the
port.  Once when the situation changes in future, we might introduce
WARN_ON() for a more strict check.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent cae666ce
...@@ -1944,6 +1944,8 @@ struct drm_i915_private { ...@@ -1944,6 +1944,8 @@ struct drm_i915_private {
/* perform PHY state sanity checks? */ /* perform PHY state sanity checks? */
bool chv_phy_assert[2]; bool chv_phy_assert[2];
struct intel_encoder *dig_port_map[I915_MAX_PORTS];
/* /*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place. * will be rejected. Instead look for a better place.
......
...@@ -636,15 +636,14 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -636,15 +636,14 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
int port, int rate) int port, int rate)
{ {
struct drm_i915_private *dev_priv = dev_to_i915(dev); struct drm_i915_private *dev_priv = dev_to_i915(dev);
struct drm_device *drm_dev = dev_priv->dev;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_digital_port *intel_dig_port;
struct intel_crtc *crtc; struct intel_crtc *crtc;
struct drm_display_mode *mode; struct drm_display_mode *mode;
struct i915_audio_component *acomp = dev_priv->audio_component; struct i915_audio_component *acomp = dev_priv->audio_component;
enum pipe pipe = -1; enum pipe pipe = INVALID_PIPE;
u32 tmp; u32 tmp;
int n; int n;
int err = 0;
/* HSW, BDW, SKL, KBL need this fix */ /* HSW, BDW, SKL, KBL need this fix */
if (!IS_SKYLAKE(dev_priv) && if (!IS_SKYLAKE(dev_priv) &&
...@@ -655,26 +654,22 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -655,26 +654,22 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
mutex_lock(&dev_priv->av_mutex); mutex_lock(&dev_priv->av_mutex);
/* 1. get the pipe */ /* 1. get the pipe */
for_each_intel_encoder(drm_dev, intel_encoder) { intel_encoder = dev_priv->dig_port_map[port];
if (intel_encoder->type != INTEL_OUTPUT_HDMI) /* intel_encoder might be NULL for DP MST */
continue; if (!intel_encoder || !intel_encoder->base.crtc ||
intel_dig_port = enc_to_dig_port(&intel_encoder->base); intel_encoder->type != INTEL_OUTPUT_HDMI) {
if (port == intel_dig_port->port) { DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
crtc = to_intel_crtc(intel_encoder->base.crtc); err = -ENODEV;
if (!crtc) { goto unlock;
DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__);
continue;
}
pipe = crtc->pipe;
break;
}
} }
crtc = to_intel_crtc(intel_encoder->base.crtc);
pipe = crtc->pipe;
if (pipe == INVALID_PIPE) { if (pipe == INVALID_PIPE) {
DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port)); DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
mutex_unlock(&dev_priv->av_mutex); err = -ENODEV;
return -ENODEV; goto unlock;
} }
DRM_DEBUG_KMS("pipe %c connects port %c\n", DRM_DEBUG_KMS("pipe %c connects port %c\n",
pipe_name(pipe), port_name(port)); pipe_name(pipe), port_name(port));
mode = &crtc->config->base.adjusted_mode; mode = &crtc->config->base.adjusted_mode;
...@@ -687,8 +682,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -687,8 +682,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
tmp = I915_READ(HSW_AUD_CFG(pipe)); tmp = I915_READ(HSW_AUD_CFG(pipe));
tmp &= ~AUD_CONFIG_N_PROG_ENABLE; tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
I915_WRITE(HSW_AUD_CFG(pipe), tmp); I915_WRITE(HSW_AUD_CFG(pipe), tmp);
mutex_unlock(&dev_priv->av_mutex); goto unlock;
return 0;
} }
n = audio_config_get_n(mode, rate); n = audio_config_get_n(mode, rate);
...@@ -698,8 +692,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -698,8 +692,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
tmp = I915_READ(HSW_AUD_CFG(pipe)); tmp = I915_READ(HSW_AUD_CFG(pipe));
tmp &= ~AUD_CONFIG_N_PROG_ENABLE; tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
I915_WRITE(HSW_AUD_CFG(pipe), tmp); I915_WRITE(HSW_AUD_CFG(pipe), tmp);
mutex_unlock(&dev_priv->av_mutex); goto unlock;
return 0;
} }
/* 3. set the N/CTS/M */ /* 3. set the N/CTS/M */
...@@ -707,8 +700,9 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -707,8 +700,9 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
tmp = audio_config_setup_n_reg(n, tmp); tmp = audio_config_setup_n_reg(n, tmp);
I915_WRITE(HSW_AUD_CFG(pipe), tmp); I915_WRITE(HSW_AUD_CFG(pipe), tmp);
unlock:
mutex_unlock(&dev_priv->av_mutex); mutex_unlock(&dev_priv->av_mutex);
return 0; return err;
} }
static int i915_audio_component_get_eld(struct device *dev, int port, static int i915_audio_component_get_eld(struct device *dev, int port,
...@@ -716,27 +710,22 @@ static int i915_audio_component_get_eld(struct device *dev, int port, ...@@ -716,27 +710,22 @@ static int i915_audio_component_get_eld(struct device *dev, int port,
unsigned char *buf, int max_bytes) unsigned char *buf, int max_bytes)
{ {
struct drm_i915_private *dev_priv = dev_to_i915(dev); struct drm_i915_private *dev_priv = dev_to_i915(dev);
struct drm_device *drm_dev = dev_priv->dev;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_digital_port *intel_dig_port; struct intel_digital_port *intel_dig_port;
const u8 *eld; const u8 *eld;
int ret = -EINVAL; int ret = -EINVAL;
mutex_lock(&dev_priv->av_mutex); mutex_lock(&dev_priv->av_mutex);
for_each_intel_encoder(drm_dev, intel_encoder) { intel_encoder = dev_priv->dig_port_map[port];
if (intel_encoder->type != INTEL_OUTPUT_DISPLAYPORT && /* intel_encoder might be NULL for DP MST */
intel_encoder->type != INTEL_OUTPUT_HDMI) if (intel_encoder) {
continue; ret = 0;
intel_dig_port = enc_to_dig_port(&intel_encoder->base); intel_dig_port = enc_to_dig_port(&intel_encoder->base);
if (port == intel_dig_port->port) { *enabled = intel_dig_port->audio_connector != NULL;
ret = 0; if (*enabled) {
*enabled = intel_dig_port->audio_connector != NULL;
if (!*enabled)
break;
eld = intel_dig_port->audio_connector->eld; eld = intel_dig_port->audio_connector->eld;
ret = drm_eld_size(eld); ret = drm_eld_size(eld);
memcpy(buf, eld, min(max_bytes, ret)); memcpy(buf, eld, min(max_bytes, ret));
break;
} }
} }
......
...@@ -3295,6 +3295,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) ...@@ -3295,6 +3295,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->get_config = intel_ddi_get_config; intel_encoder->get_config = intel_ddi_get_config;
intel_dig_port->port = port; intel_dig_port->port = port;
dev_priv->dig_port_map[port] = intel_encoder;
intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
(DDI_BUF_PORT_REVERSAL | (DDI_BUF_PORT_REVERSAL |
DDI_A_4_LANES); DDI_A_4_LANES);
......
...@@ -6003,6 +6003,7 @@ intel_dp_init(struct drm_device *dev, ...@@ -6003,6 +6003,7 @@ intel_dp_init(struct drm_device *dev,
} }
intel_dig_port->port = port; intel_dig_port->port = port;
dev_priv->dig_port_map[port] = intel_encoder;
intel_dig_port->dp.output_reg = output_reg; intel_dig_port->dp.output_reg = output_reg;
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
......
...@@ -2148,6 +2148,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -2148,6 +2148,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
void intel_hdmi_init(struct drm_device *dev, void intel_hdmi_init(struct drm_device *dev,
i915_reg_t hdmi_reg, enum port port) i915_reg_t hdmi_reg, enum port port)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port; struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
...@@ -2216,6 +2217,7 @@ void intel_hdmi_init(struct drm_device *dev, ...@@ -2216,6 +2217,7 @@ void intel_hdmi_init(struct drm_device *dev,
intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
intel_dig_port->port = port; intel_dig_port->port = port;
dev_priv->dig_port_map[port] = intel_encoder;
intel_dig_port->hdmi.hdmi_reg = hdmi_reg; intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
intel_dig_port->dp.output_reg = INVALID_MMIO_REG; intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment