diff mbox

[v4,3/3] drm/i915: Haswell HDMI audio enable

Message ID 1344249840-14700-4-git-send-email-xingchao.wang@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Wang Xingchao Aug. 6, 2012, 10:44 a.m. UTC
Configure the related HDMI audio register to generate an unsolicited
response to the audio controller driver to indicate that the controller
sequence should start.

Use "pipe" way to get correct register definitions for IBX/CPT/HSW.

Signed-off-by: Wang Xingchao <xingchao.wang@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |   32 +++++++++++++++++++--
 drivers/gpu/drm/i915/intel_display.c |   52 +++++++++++++++++++++++++++-------
 2 files changed, 72 insertions(+), 12 deletions(-)

Comments

Paulo Zanoni Aug. 7, 2012, 1 p.m. UTC | #1
Hi

2012/8/6 Wang Xingchao <xingchao.wang@intel.com>:
> Configure the related HDMI audio register to generate an unsolicited
> response to the audio controller driver to indicate that the controller
> sequence should start.
>
> Use "pipe" way to get correct register definitions for IBX/CPT/HSW.

Please split this patch in 2: one that just converts the IBX/CPT into
the PIPE macro, and another that adds the HSW regs.

Thanks,
Paulo

>
> Signed-off-by: Wang Xingchao <xingchao.wang@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h      |   32 +++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_display.c |   52 +++++++++++++++++++++++++++-------
>  2 files changed, 72 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index ed87de9..9588dd4 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4247,7 +4247,15 @@
>  #define G4X_HDMIW_HDMIEDID             0x6210C
>
>  #define IBX_HDMIW_HDMIEDID_A           0xE2050
> +#define IBX_HDMIW_HDMIEDID_B           0xE2150
> +#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
> +                                       IBX_HDMIW_HDMIEDID_A, \
> +                                       IBX_HDMIW_HDMIEDID_B)
>  #define IBX_AUD_CNTL_ST_A              0xE20B4
> +#define IBX_AUD_CNTL_ST_B              0xE21B4
> +#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \
> +                                       IBX_AUD_CNTL_ST_A, \
> +                                       IBX_AUD_CNTL_ST_B)
>  #define IBX_ELD_BUFFER_SIZE            (0x1f << 10)
>  #define IBX_ELD_ADDRESS                        (0x1f << 5)
>  #define IBX_ELD_ACK                    (1 << 4)
> @@ -4256,7 +4264,15 @@
>  #define IBX_CP_READYB                  (1 << 1)
>
>  #define CPT_HDMIW_HDMIEDID_A           0xE5050
> +#define CPT_HDMIW_HDMIEDID_B           0xE5150
> +#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
> +                                       CPT_HDMIW_HDMIEDID_A, \
> +                                       CPT_HDMIW_HDMIEDID_B)
>  #define CPT_AUD_CNTL_ST_A              0xE50B4
> +#define CPT_AUD_CNTL_ST_B              0xE51B4
> +#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \
> +                                       CPT_AUD_CNTL_ST_A, \
> +                                       CPT_AUD_CNTL_ST_B)
>  #define CPT_AUD_CNTRL_ST2              0xE50C0
>
>  /* These are the 4 32-bit write offset registers for each stream
> @@ -4266,7 +4282,15 @@
>  #define GEN7_SO_WRITE_OFFSET(n)                (0x5280 + (n) * 4)
>
>  #define IBX_AUD_CONFIG_A                       0xe2000
> +#define IBX_AUD_CONFIG_B                       0xe2100
> +#define IBX_AUD_CFG(pipe) _PIPE(pipe, \
> +                                       IBX_AUD_CONFIG_A, \
> +                                       IBX_AUD_CONFIG_B)
>  #define CPT_AUD_CONFIG_A                       0xe5000
> +#define CPT_AUD_CONFIG_B                       0xe5100
> +#define CPT_AUD_CFG(pipe) _PIPE(pipe, \
> +                                       CPT_AUD_CONFIG_A, \
> +                                       CPT_AUD_CONFIG_B)
>  #define   AUD_CONFIG_N_VALUE_INDEX             (1 << 29)
>  #define   AUD_CONFIG_N_PROG_ENABLE             (1 << 28)
>  #define   AUD_CONFIG_UPPER_N_SHIFT             20
> @@ -4296,7 +4320,7 @@
>                                         HSW_AUD_DIP_ELD_CTRL_ST_B)
>
>  #define   HSW_AUD_PIPE_CONV_CFG                0x6507c /*Audio pipe and converter configs*/
> -#define   HSW_AUD_PIN_ELD_CP_VL                0x650c0 /*Audio ELD and CP Ready Status*/
> +#define   HSW_AUD_PIN_ELD_CP_VLD       0x650c0 /*Audio ELD and CP Ready Status*/
>  #define   AUDIO_INACTIVE_C             (1<<11)
>  #define   AUDIO_INACTIVE_B             (1<<7)
>  #define   AUDIO_INACTIVE_A             (1<<3)
> @@ -4317,7 +4341,11 @@
>                                         HSW_AUD_DIG_CNVT_1, \
>                                         HSW_AUD_DIG_CNVT_2)
>
> -#define   HSW_AUD_EDID_DATA            0x65050
> +#define   HSW_AUD_EDID_DATA_A          0x65050
> +#define   HSW_AUD_EDID_DATA_B          0x65150
> +#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \
> +                                       HSW_AUD_EDID_DATA_A, \
> +                                       HSW_AUD_EDID_DATA_B)
>
>  #define   TRANS_CONF_A                 0xf0008
>  #define   AUD_PB_UNSL_DEV_CP           0x65fb0
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 17020cd..103de56 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5071,6 +5071,7 @@ static void ironlake_write_eld(struct drm_connector *connector,
>                                      struct drm_crtc *crtc)
>  {
>         struct drm_i915_private *dev_priv = connector->dev->dev_private;
> +       struct drm_device *dev = crtc->dev;
>         uint8_t *eld = connector->eld;
>         uint32_t eldv;
>         uint32_t i;
> @@ -5079,23 +5080,52 @@ static void ironlake_write_eld(struct drm_connector *connector,
>         int aud_config;
>         int aud_cntl_st;
>         int aud_cntrl_st2;
> +       int pipe = to_intel_crtc(crtc)->pipe;
>
>         if (HAS_PCH_IBX(connector->dev)) {
> -               hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
> -               aud_config = IBX_AUD_CONFIG_A;
> -               aud_cntl_st = IBX_AUD_CNTL_ST_A;
> +               hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
> +               aud_config = IBX_AUD_CFG(pipe);
> +               aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
>                 aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
> +       } else if (IS_HASWELL(dev)) {
> +               hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe);
> +               aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe);
> +               aud_config = HSW_AUD_CFG(pipe);
> +               aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD;
>         } else {
> -               hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
> -               aud_config = CPT_AUD_CONFIG_A;
> -               aud_cntl_st = CPT_AUD_CNTL_ST_A;
> +               hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
> +               aud_config = CPT_AUD_CFG(pipe);
> +               aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
>                 aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
>         }
>
> -       i = to_intel_crtc(crtc)->pipe;
> -       hdmiw_hdmiedid += i * 0x100;
> -       aud_cntl_st += i * 0x100;
> -       aud_config += i * 0x100;
> +       if (IS_HASWELL(dev)) {
> +               int tmp;
> +               int aud_vld = HSW_AUD_PIN_ELD_CP_VLD;
> +
> +               DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n");
> +
> +               /* Audio output enable */
> +               DRM_DEBUG_DRIVER("HDMI audio: enable codec\n");
> +               tmp = I915_READ(aud_vld);
> +               tmp |= (AUDIO_OUTPUT_ENABLE_A | AUDIO_OUTPUT_ENABLE_B | AUDIO_OUTPUT_ENABLE_C);
> +               I915_WRITE(aud_vld, tmp);
> +
> +               /* Set ELD valid state */
> +               tmp = I915_READ(aud_vld);
> +               DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp);
> +               tmp |= (AUDIO_ELD_VALID_A | AUDIO_ELD_VALID_B | AUDIO_ELD_VALID_C);
> +               I915_WRITE(aud_vld, tmp);
> +               tmp = I915_READ(aud_vld);
> +               DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp);
> +
> +               /* Enable HDMI mode */
> +               tmp = I915_READ(aud_config);
> +               DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp);
> +               /* clear N_programing_enable and N_value_index */
> +               tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE);
> +               I915_WRITE(aud_config, tmp);
> +       }
>
>         DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
>
> @@ -5135,6 +5165,8 @@ static void ironlake_write_eld(struct drm_connector *connector,
>         i = I915_READ(aud_cntl_st);
>         i &= ~IBX_ELD_ADDRESS;
>         I915_WRITE(aud_cntl_st, i);
> +       i = (i >> 29) & 0x3;            /* DIP_Port_Select, 0x1 = PortB */
> +       DRM_DEBUG_DRIVER("port num:%d\n", i);
>
>         len = min_t(uint8_t, eld[2], 21);       /* 84 bytes of hw ELD buffer */
>         DRM_DEBUG_DRIVER("ELD size %d\n", len);
> --
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ed87de9..9588dd4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4247,7 +4247,15 @@ 
 #define G4X_HDMIW_HDMIEDID		0x6210C
 
 #define IBX_HDMIW_HDMIEDID_A		0xE2050
+#define IBX_HDMIW_HDMIEDID_B		0xE2150
+#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
+					IBX_HDMIW_HDMIEDID_A, \
+					IBX_HDMIW_HDMIEDID_B)
 #define IBX_AUD_CNTL_ST_A		0xE20B4
+#define IBX_AUD_CNTL_ST_B		0xE21B4
+#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \
+					IBX_AUD_CNTL_ST_A, \
+					IBX_AUD_CNTL_ST_B)
 #define IBX_ELD_BUFFER_SIZE		(0x1f << 10)
 #define IBX_ELD_ADDRESS			(0x1f << 5)
 #define IBX_ELD_ACK			(1 << 4)
@@ -4256,7 +4264,15 @@ 
 #define IBX_CP_READYB			(1 << 1)
 
 #define CPT_HDMIW_HDMIEDID_A		0xE5050
+#define CPT_HDMIW_HDMIEDID_B		0xE5150
+#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
+					CPT_HDMIW_HDMIEDID_A, \
+					CPT_HDMIW_HDMIEDID_B)
 #define CPT_AUD_CNTL_ST_A		0xE50B4
+#define CPT_AUD_CNTL_ST_B		0xE51B4
+#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \
+					CPT_AUD_CNTL_ST_A, \
+					CPT_AUD_CNTL_ST_B)
 #define CPT_AUD_CNTRL_ST2		0xE50C0
 
 /* These are the 4 32-bit write offset registers for each stream
@@ -4266,7 +4282,15 @@ 
 #define GEN7_SO_WRITE_OFFSET(n)		(0x5280 + (n) * 4)
 
 #define IBX_AUD_CONFIG_A			0xe2000
+#define IBX_AUD_CONFIG_B			0xe2100
+#define IBX_AUD_CFG(pipe) _PIPE(pipe, \
+					IBX_AUD_CONFIG_A, \
+					IBX_AUD_CONFIG_B)
 #define CPT_AUD_CONFIG_A			0xe5000
+#define CPT_AUD_CONFIG_B			0xe5100
+#define CPT_AUD_CFG(pipe) _PIPE(pipe, \
+					CPT_AUD_CONFIG_A, \
+					CPT_AUD_CONFIG_B)
 #define   AUD_CONFIG_N_VALUE_INDEX		(1 << 29)
 #define   AUD_CONFIG_N_PROG_ENABLE		(1 << 28)
 #define   AUD_CONFIG_UPPER_N_SHIFT		20
@@ -4296,7 +4320,7 @@ 
 					HSW_AUD_DIP_ELD_CTRL_ST_B)
 
 #define   HSW_AUD_PIPE_CONV_CFG		0x6507c /*Audio pipe and converter configs*/
-#define   HSW_AUD_PIN_ELD_CP_VL		0x650c0 /*Audio ELD and CP Ready Status*/
+#define   HSW_AUD_PIN_ELD_CP_VLD	0x650c0 /*Audio ELD and CP Ready Status*/
 #define   AUDIO_INACTIVE_C		(1<<11)
 #define   AUDIO_INACTIVE_B		(1<<7)
 #define   AUDIO_INACTIVE_A		(1<<3)
@@ -4317,7 +4341,11 @@ 
 					HSW_AUD_DIG_CNVT_1, \
 					HSW_AUD_DIG_CNVT_2)
 
-#define   HSW_AUD_EDID_DATA		0x65050
+#define   HSW_AUD_EDID_DATA_A		0x65050
+#define   HSW_AUD_EDID_DATA_B		0x65150
+#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \
+					HSW_AUD_EDID_DATA_A, \
+					HSW_AUD_EDID_DATA_B)
 
 #define   TRANS_CONF_A			0xf0008
 #define   AUD_PB_UNSL_DEV_CP		0x65fb0
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 17020cd..103de56 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5071,6 +5071,7 @@  static void ironlake_write_eld(struct drm_connector *connector,
 				     struct drm_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	struct drm_device *dev = crtc->dev;
 	uint8_t *eld = connector->eld;
 	uint32_t eldv;
 	uint32_t i;
@@ -5079,23 +5080,52 @@  static void ironlake_write_eld(struct drm_connector *connector,
 	int aud_config;
 	int aud_cntl_st;
 	int aud_cntrl_st2;
+	int pipe = to_intel_crtc(crtc)->pipe;
 
 	if (HAS_PCH_IBX(connector->dev)) {
-		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
-		aud_config = IBX_AUD_CONFIG_A;
-		aud_cntl_st = IBX_AUD_CNTL_ST_A;
+		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
+		aud_config = IBX_AUD_CFG(pipe);
+		aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
+	} else if (IS_HASWELL(dev)) {
+		hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe);
+		aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe);
+		aud_config = HSW_AUD_CFG(pipe);
+		aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD;
 	} else {
-		hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
-		aud_config = CPT_AUD_CONFIG_A;
-		aud_cntl_st = CPT_AUD_CNTL_ST_A;
+		hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
+		aud_config = CPT_AUD_CFG(pipe);
+		aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
 		aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
 	}
 
-	i = to_intel_crtc(crtc)->pipe;
-	hdmiw_hdmiedid += i * 0x100;
-	aud_cntl_st += i * 0x100;
-	aud_config += i * 0x100;
+	if (IS_HASWELL(dev)) {
+		int tmp;
+		int aud_vld = HSW_AUD_PIN_ELD_CP_VLD;
+
+		DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n");
+
+		/* Audio output enable */
+		DRM_DEBUG_DRIVER("HDMI audio: enable codec\n");
+		tmp = I915_READ(aud_vld);
+		tmp |= (AUDIO_OUTPUT_ENABLE_A | AUDIO_OUTPUT_ENABLE_B | AUDIO_OUTPUT_ENABLE_C);
+		I915_WRITE(aud_vld, tmp);
+
+		/* Set ELD valid state */
+		tmp = I915_READ(aud_vld);
+		DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp);
+		tmp |= (AUDIO_ELD_VALID_A | AUDIO_ELD_VALID_B | AUDIO_ELD_VALID_C);
+		I915_WRITE(aud_vld, tmp);
+		tmp = I915_READ(aud_vld);
+		DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp);
+
+		/* Enable HDMI mode */
+		tmp = I915_READ(aud_config);
+		DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp);
+		/* clear N_programing_enable and N_value_index */
+		tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE);
+		I915_WRITE(aud_config, tmp);
+	}
 
 	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
 
@@ -5135,6 +5165,8 @@  static void ironlake_write_eld(struct drm_connector *connector,
 	i = I915_READ(aud_cntl_st);
 	i &= ~IBX_ELD_ADDRESS;
 	I915_WRITE(aud_cntl_st, i);
+	i = (i >> 29) & 0x3;		/* DIP_Port_Select, 0x1 = PortB */
+	DRM_DEBUG_DRIVER("port num:%d\n", i);
 
 	len = min_t(uint8_t, eld[2], 21);	/* 84 bytes of hw ELD buffer */
 	DRM_DEBUG_DRIVER("ELD size %d\n", len);