From 9dfbffcf4ac0707097af9e6c1372192b9d03a357 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 24 Feb 2016 15:35:22 +0100
Subject: [PATCH] drm/i915: Fix bogus dig_port_map[] assignment for pre-HSW
Mime-version: 1.0
Content-type: text/plain; charset=UTF-8
Content-transfer-encoding: 8bit
Git-commit: 9dfbffcf4ac0707097af9e6c1372192b9d03a357
No-fix: 2f791908a70e95768596f5bb9e6de4f441d7bf13
Patch-mainline: 4.7-rc1
References: bsc#1033784

The recent commit [0bdf5a05647a: drm/i915: Add reverse mapping between
port and intel_encoder] introduced a reverse mapping to retrieve
intel_dig_port object from the port number.  The code assumed that the
port vs intel_dig_port are 1:1 mapping.  But in reality, this was a
too naive assumption.

As Martin reported about the missing HDMI audio on his SNB machine,
pre-HSW chips may have multiple intel_dig_port objects corresponding
to the same port.  Since we assign the mapping statically at the init
time and the multiple objects override the map, it may not match with
the actually enabled output.

This patch tries to address the regression above.  The reverse mapping
is provided basically only for the audio callbacks, so now we set /
clear the mapping dynamically at enabling and disabling HDMI/DP audio,
so that we can always track the latest and correct object
corresponding to the given port.

Fixes: 0bdf5a05647a ('drm/i915: Add reverse mapping between port and intel_encoder')
Reported-and-tested-by: Martin Kepplinger <martink@posteo.de>
Cc: drm-intel-fixes@lists.freedesktop.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1456324522-21591-1-git-send-email-tiwai@suse.de

---
 drivers/gpu/drm/i915/intel_audio.c |    3 +++
 drivers/gpu/drm/i915/intel_ddi.c   |    1 -
 drivers/gpu/drm/i915/intel_dp.c    |    1 -
 drivers/gpu/drm/i915/intel_hdmi.c  |    2 --
 4 files changed, 3 insertions(+), 4 deletions(-)

--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -527,6 +527,8 @@ void intel_audio_codec_enable(struct int
 
 	mutex_lock(&dev_priv->av_mutex);
 	intel_dig_port->audio_connector = connector;
+	/* referred in audio callbacks */
+	dev_priv->dig_port_map[port] = intel_encoder;
 	mutex_unlock(&dev_priv->av_mutex);
 
 	if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
@@ -554,6 +556,7 @@ void intel_audio_codec_disable(struct in
 
 	mutex_lock(&dev_priv->av_mutex);
 	intel_dig_port->audio_connector = NULL;
+	dev_priv->dig_port_map[port] = NULL;
 	mutex_unlock(&dev_priv->av_mutex);
 
 	if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3302,7 +3302,6 @@ void intel_ddi_init(struct drm_device *d
 	intel_encoder->suspend = intel_dp_encoder_suspend;
 
 	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)) &
 					  (DDI_BUF_PORT_REVERSAL |
 					   DDI_A_4_LANES);
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -6196,7 +6196,6 @@ bool intel_dp_init(struct drm_device *de
 	}
 
 	intel_dig_port->port = port;
-	dev_priv->dig_port_map[port] = intel_encoder;
 	intel_dig_port->dp.output_reg = output_reg;
 
 	intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2139,7 +2139,6 @@ void intel_hdmi_init_connector(struct in
 
 void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
@@ -2208,7 +2207,6 @@ void intel_hdmi_init(struct drm_device *
 		intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
 
 	intel_dig_port->port = port;
-	dev_priv->dig_port_map[port] = intel_encoder;
 	intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
 	intel_dig_port->dp.output_reg = 0;
 
