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 at 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