[PATCH 2/4] i915: add support for GPU side of MST audio

Dave Airlie
2015-06-17T04:02:10Z

From: Dave Airlie <airlied@redhat.com>

This just adds enables for the codecs and debugfs
support for mst connectors to print the audio info.

This relies on patches to the audio code to do anything
more useful.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 13 +++++++++++++
drivers/gpu/drm/i915/intel_audio.c | 7 ++++---
drivers/gpu/drm/i915/intel_dp_mst.c | 25 +++++++++++++++++++++++++
3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index dc55c51..a109a21 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2577,6 +2577,17 @@ static void intel_dp_info(struct seq_file *m,
intel_panel_info(m, &intel_connector->panel);
}

+static void intel_dp_mst_info(struct seq_file *m,
+ struct intel_connector *intel_connector)
+{
+ struct intel_encoder *intel_encoder = intel_connector->encoder;
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&intel_encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+ seq_printf(m, "\taudio support: %s\n", drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, intel_connector->port) ? "yes" : "no");
+}
+
static void intel_hdmi_info(struct seq_file *m,
struct intel_connector *intel_connector)
{
@@ -2621,6 +2632,8 @@ static void intel_connector_info(struct seq_file *m,
intel_hdmi_info(m, intel_connector);
else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
intel_lvds_info(m, intel_connector);
+ else if (intel_encoder->type == INTEL_OUTPUT_DP_MST)
+ intel_dp_mst_info(m, intel_connector);
}

seq_printf(m, "\tmodes:\n");
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 2396cc7..77d2a01 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -190,7 +190,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder)
tmp |= AUD_CONFIG_N_PROG_ENABLE;
tmp &= ~AUD_CONFIG_UPPER_N_MASK;
tmp &= ~AUD_CONFIG_LOWER_N_MASK;
- if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
+ if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
tmp |= AUD_CONFIG_N_VALUE_INDEX;
I915_WRITE(HSW_AUD_CFG(pipe), tmp);

@@ -231,6 +231,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
/* Reset ELD write address */
tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
tmp &= ~IBX_ELD_ADDRESS_MASK;
+ tmp |= ((pipe + 1) << 29);
I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);

/* Up to 84 bytes of hw ELD buffer */
@@ -248,7 +249,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
- if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
+ if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
tmp |= AUD_CONFIG_N_VALUE_INDEX;
else
tmp |= audio_config_hdmi_pixel_clock(mode);
@@ -417,7 +418,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)

/* ELD Conn_Type */
connector->eld[5] &= ~(3 << 2);
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
connector->eld[5] |= (1 << 2);

connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 5cb4748..8a39e99 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -85,6 +85,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
return false;
}

+ if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found->port))
+ pipe_config->has_audio = true;
mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);

pipe_config->pbn = mst_pbn;
@@ -105,6 +107,11 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
struct intel_digital_port *intel_dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc = encoder->base.crtc;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
int ret;

DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
@@ -115,6 +122,10 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
if (ret) {
DRM_ERROR("failed to update payload %d\n", ret);
}
+ if (intel_crtc->config->has_audio) {
+ intel_audio_codec_disable(encoder);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+ }
}

static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
@@ -209,6 +220,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
enum port port = intel_dig_port->port;
int ret;

@@ -221,6 +233,13 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
ret = drm_dp_check_act_status(&intel_dp->mst_mgr);

ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+
+ if (crtc->config->has_audio) {
+ DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
+ pipe_name(crtc->pipe));
+ intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
+ intel_audio_codec_enable(encoder);
+ }
}

static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
@@ -246,6 +265,12 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,

pipe_config->has_dp_encoder = true;

+ if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
+ temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+ if (temp & AUDIO_OUTPUT_ENABLE(crtc->pipe))
+ pipe_config->has_audio = true;
+ }
+
temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
if (temp & TRANS_DDI_PHSYNC)
flags |= DRM_MODE_FLAG_PHSYNC;
--
2.4.1