On Thu, 18 Sep 2014, Daniel Vetter <daniel@xxxxxxxx> wrote: > lgtm, but I think to make code extraction into new files really worth > it this should be followed up with a small patch to add an overview > DOC section and kerneldoc for the non-static functions. Plus pulling > it all in at a neat place into our driver docs. Can do; the main point of the patch was to get feedback and decide whether to do some cleanups on the code within intel_display.c or to move it elsewhere first. J. > -Daniel > > On Wed, Sep 17, 2014 at 7:26 PM, Jani Nikula <jani.nikula@xxxxxxxxx> wrote: >> No functional changes. >> >> Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> >> >> --- >> >> I was looking at the audio stuff in connection with some bugs, and >> thought the eld functions could use some love. But before proceeding, I >> started wondering whether the audio functions would be better off in a >> file of their own for starters, before embarging on further cleanup. >> --- >> drivers/gpu/drm/i915/Makefile | 3 +- >> drivers/gpu/drm/i915/intel_audio.c | 350 +++++++++++++++++++++++++++++++++++ >> drivers/gpu/drm/i915/intel_display.c | 320 +------------------------------- >> drivers/gpu/drm/i915/intel_drv.h | 8 +- >> 4 files changed, 361 insertions(+), 320 deletions(-) >> create mode 100644 drivers/gpu/drm/i915/intel_audio.c >> >> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile >> index c1dd485aeb6c..1ca4075df605 100644 >> --- a/drivers/gpu/drm/i915/Makefile >> +++ b/drivers/gpu/drm/i915/Makefile >> @@ -41,7 +41,8 @@ i915-y += intel_renderstate_gen6.o \ >> intel_renderstate_gen8.o >> >> # modesetting core code >> -i915-y += intel_bios.o \ >> +i915-y += intel_audio.o \ >> + intel_bios.o \ >> intel_display.o \ >> intel_modes.o \ >> intel_overlay.o \ >> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c >> new file mode 100644 >> index 000000000000..ffffceef90dc >> --- /dev/null >> +++ b/drivers/gpu/drm/i915/intel_audio.c >> @@ -0,0 +1,350 @@ >> +/* >> + * Copyright © 2014 Intel Corporation >> + * >> + * Permission is hereby granted, free of charge, to any person obtaining a >> + * copy of this software and associated documentation files (the "Software"), >> + * to deal in the Software without restriction, including without limitation >> + * the rights to use, copy, modify, merge, publish, distribute, sublicense, >> + * and/or sell copies of the Software, and to permit persons to whom the >> + * Software is furnished to do so, subject to the following conditions: >> + * >> + * The above copyright notice and this permission notice (including the next >> + * paragraph) shall be included in all copies or substantial portions of the >> + * Software. >> + * >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER >> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING >> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >> + * DEALINGS IN THE SOFTWARE. >> + */ >> + >> +#include <linux/kernel.h> >> + >> +#include <drm/drmP.h> >> +#include <drm/drm_edid.h> >> +#include "intel_drv.h" >> +#include "i915_drv.h" >> + >> +static struct { >> + int clock; >> + u32 config; >> +} hdmi_audio_clock[] = { >> + { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, >> + { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ >> + { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, >> + { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, >> + { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, >> + { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, >> + { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, >> + { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, >> + { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, >> + { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, >> +}; >> + >> +/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ >> +static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) >> +{ >> + int i; >> + >> + for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { >> + if (mode->clock == hdmi_audio_clock[i].clock) >> + break; >> + } >> + >> + if (i == ARRAY_SIZE(hdmi_audio_clock)) { >> + DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); >> + i = 1; >> + } >> + >> + DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n", >> + hdmi_audio_clock[i].clock, >> + hdmi_audio_clock[i].config); >> + >> + return hdmi_audio_clock[i].config; >> +} >> + >> +static bool intel_eld_uptodate(struct drm_connector *connector, >> + int reg_eldv, uint32_t bits_eldv, >> + int reg_elda, uint32_t bits_elda, >> + int reg_edid) >> +{ >> + struct drm_i915_private *dev_priv = connector->dev->dev_private; >> + uint8_t *eld = connector->eld; >> + uint32_t i; >> + >> + i = I915_READ(reg_eldv); >> + i &= bits_eldv; >> + >> + if (!eld[0]) >> + return !i; >> + >> + if (!i) >> + return false; >> + >> + i = I915_READ(reg_elda); >> + i &= ~bits_elda; >> + I915_WRITE(reg_elda, i); >> + >> + for (i = 0; i < eld[2]; i++) >> + if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) >> + return false; >> + >> + return true; >> +} >> + >> +static void g4x_write_eld(struct drm_connector *connector, >> + struct drm_crtc *crtc, >> + struct drm_display_mode *mode) >> +{ >> + struct drm_i915_private *dev_priv = connector->dev->dev_private; >> + uint8_t *eld = connector->eld; >> + uint32_t eldv; >> + uint32_t len; >> + uint32_t i; >> + >> + i = I915_READ(G4X_AUD_VID_DID); >> + >> + if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL) >> + eldv = G4X_ELDV_DEVCL_DEVBLC; >> + else >> + eldv = G4X_ELDV_DEVCTG; >> + >> + if (intel_eld_uptodate(connector, >> + G4X_AUD_CNTL_ST, eldv, >> + G4X_AUD_CNTL_ST, G4X_ELD_ADDR, >> + G4X_HDMIW_HDMIEDID)) >> + return; >> + >> + i = I915_READ(G4X_AUD_CNTL_ST); >> + i &= ~(eldv | G4X_ELD_ADDR); >> + len = (i >> 9) & 0x1f; /* ELD buffer size */ >> + I915_WRITE(G4X_AUD_CNTL_ST, i); >> + >> + if (!eld[0]) >> + return; >> + >> + len = min_t(uint8_t, eld[2], len); >> + DRM_DEBUG_DRIVER("ELD size %d\n", len); >> + for (i = 0; i < len; i++) >> + I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i)); >> + >> + i = I915_READ(G4X_AUD_CNTL_ST); >> + i |= eldv; >> + I915_WRITE(G4X_AUD_CNTL_ST, i); >> +} >> + >> +static void haswell_write_eld(struct drm_connector *connector, >> + struct drm_crtc *crtc, >> + struct drm_display_mode *mode) >> +{ >> + struct drm_i915_private *dev_priv = connector->dev->dev_private; >> + uint8_t *eld = connector->eld; >> + uint32_t eldv; >> + uint32_t i; >> + int len; >> + int pipe = to_intel_crtc(crtc)->pipe; >> + int tmp; >> + >> + int hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe); >> + int aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe); >> + int aud_config = HSW_AUD_CFG(pipe); >> + int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD; >> + >> + /* Audio output enable */ >> + DRM_DEBUG_DRIVER("HDMI audio: enable codec\n"); >> + tmp = I915_READ(aud_cntrl_st2); >> + tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4)); >> + I915_WRITE(aud_cntrl_st2, tmp); >> + POSTING_READ(aud_cntrl_st2); >> + >> + assert_pipe_disabled(dev_priv, to_intel_crtc(crtc)->pipe); >> + >> + /* Set ELD valid state */ >> + tmp = I915_READ(aud_cntrl_st2); >> + DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%08x\n", tmp); >> + tmp |= (AUDIO_ELD_VALID_A << (pipe * 4)); >> + I915_WRITE(aud_cntrl_st2, tmp); >> + tmp = I915_READ(aud_cntrl_st2); >> + DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%08x\n", tmp); >> + >> + /* Enable HDMI mode */ >> + tmp = I915_READ(aud_config); >> + DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%08x\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(pipe)); >> + >> + eldv = AUDIO_ELD_VALID_A << (pipe * 4); >> + >> + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { >> + DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); >> + eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ >> + I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ >> + } else { >> + I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); >> + } >> + >> + if (intel_eld_uptodate(connector, >> + aud_cntrl_st2, eldv, >> + aud_cntl_st, IBX_ELD_ADDRESS, >> + hdmiw_hdmiedid)) >> + return; >> + >> + i = I915_READ(aud_cntrl_st2); >> + i &= ~eldv; >> + I915_WRITE(aud_cntrl_st2, i); >> + >> + if (!eld[0]) >> + return; >> + >> + i = I915_READ(aud_cntl_st); >> + i &= ~IBX_ELD_ADDRESS; >> + I915_WRITE(aud_cntl_st, i); >> + i = (i >> 29) & DIP_PORT_SEL_MASK; /* 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); >> + for (i = 0; i < len; i++) >> + I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); >> + >> + i = I915_READ(aud_cntrl_st2); >> + i |= eldv; >> + I915_WRITE(aud_cntrl_st2, i); >> + >> +} >> + >> +static void ironlake_write_eld(struct drm_connector *connector, >> + struct drm_crtc *crtc, >> + struct drm_display_mode *mode) >> +{ >> + struct drm_i915_private *dev_priv = connector->dev->dev_private; >> + uint8_t *eld = connector->eld; >> + uint32_t eldv; >> + uint32_t i; >> + int len; >> + int hdmiw_hdmiedid; >> + 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(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_VALLEYVIEW(connector->dev)) { >> + hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); >> + aud_config = VLV_AUD_CFG(pipe); >> + aud_cntl_st = VLV_AUD_CNTL_ST(pipe); >> + aud_cntrl_st2 = VLV_AUD_CNTL_ST2; >> + } else { >> + 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; >> + } >> + >> + DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); >> + >> + if (IS_VALLEYVIEW(connector->dev)) { >> + struct intel_encoder *intel_encoder; >> + struct intel_digital_port *intel_dig_port; >> + >> + intel_encoder = intel_attached_encoder(connector); >> + intel_dig_port = enc_to_dig_port(&intel_encoder->base); >> + i = intel_dig_port->port; >> + } else { >> + i = I915_READ(aud_cntl_st); >> + i = (i >> 29) & DIP_PORT_SEL_MASK; >> + /* DIP_Port_Select, 0x1 = PortB */ >> + } >> + >> + if (!i) { >> + DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); >> + /* operate blindly on all ports */ >> + eldv = IBX_ELD_VALIDB; >> + eldv |= IBX_ELD_VALIDB << 4; >> + eldv |= IBX_ELD_VALIDB << 8; >> + } else { >> + DRM_DEBUG_DRIVER("ELD on port %c\n", port_name(i)); >> + eldv = IBX_ELD_VALIDB << ((i - 1) * 4); >> + } >> + >> + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { >> + DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); >> + eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ >> + I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ >> + } else { >> + I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); >> + } >> + >> + if (intel_eld_uptodate(connector, >> + aud_cntrl_st2, eldv, >> + aud_cntl_st, IBX_ELD_ADDRESS, >> + hdmiw_hdmiedid)) >> + return; >> + >> + i = I915_READ(aud_cntrl_st2); >> + i &= ~eldv; >> + I915_WRITE(aud_cntrl_st2, i); >> + >> + if (!eld[0]) >> + return; >> + >> + i = I915_READ(aud_cntl_st); >> + i &= ~IBX_ELD_ADDRESS; >> + I915_WRITE(aud_cntl_st, i); >> + >> + len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ >> + DRM_DEBUG_DRIVER("ELD size %d\n", len); >> + for (i = 0; i < len; i++) >> + I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); >> + >> + i = I915_READ(aud_cntrl_st2); >> + i |= eldv; >> + I915_WRITE(aud_cntrl_st2, i); >> +} >> + >> +void intel_write_eld(struct drm_encoder *encoder, >> + struct drm_display_mode *mode) >> +{ >> + struct drm_crtc *crtc = encoder->crtc; >> + struct drm_connector *connector; >> + struct drm_device *dev = encoder->dev; >> + struct drm_i915_private *dev_priv = dev->dev_private; >> + >> + connector = drm_select_eld(encoder, mode); >> + if (!connector) >> + return; >> + >> + DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", >> + connector->base.id, >> + connector->name, >> + connector->encoder->base.id, >> + connector->encoder->name); >> + >> + connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; >> + >> + if (dev_priv->display.write_eld) >> + dev_priv->display.write_eld(connector, crtc, mode); >> +} >> + >> +/* Set up chip specific audio functions */ >> +void intel_init_audio(struct drm_device *dev) >> +{ >> + struct drm_i915_private *dev_priv = dev->dev_private; >> + >> + if (IS_G4X(dev)) >> + dev_priv->display.write_eld = g4x_write_eld; >> + else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) >> + dev_priv->display.write_eld = haswell_write_eld; >> + else >> + dev_priv->display.write_eld = ironlake_write_eld; >> +} >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c >> index cf517045fc0e..13bab0f13ecb 100644 >> --- a/drivers/gpu/drm/i915/intel_display.c >> +++ b/drivers/gpu/drm/i915/intel_display.c >> @@ -411,7 +411,7 @@ static void vlv_clock(int refclk, intel_clock_t *clock) >> /** >> * Returns whether any output on the specified pipe is of the specified type >> */ >> -static bool intel_pipe_has_type(struct drm_crtc *crtc, int type) >> +bool intel_pipe_has_type(struct drm_crtc *crtc, int type) >> { >> struct drm_device *dev = crtc->dev; >> struct intel_encoder *encoder; >> @@ -7881,314 +7881,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, >> return true; >> } >> >> -static struct { >> - int clock; >> - u32 config; >> -} hdmi_audio_clock[] = { >> - { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, >> - { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ >> - { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, >> - { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, >> - { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, >> - { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, >> - { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, >> - { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, >> - { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, >> - { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, >> -}; >> - >> -/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ >> -static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) >> -{ >> - int i; >> - >> - for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { >> - if (mode->clock == hdmi_audio_clock[i].clock) >> - break; >> - } >> - >> - if (i == ARRAY_SIZE(hdmi_audio_clock)) { >> - DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); >> - i = 1; >> - } >> - >> - DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n", >> - hdmi_audio_clock[i].clock, >> - hdmi_audio_clock[i].config); >> - >> - return hdmi_audio_clock[i].config; >> -} >> - >> -static bool intel_eld_uptodate(struct drm_connector *connector, >> - int reg_eldv, uint32_t bits_eldv, >> - int reg_elda, uint32_t bits_elda, >> - int reg_edid) >> -{ >> - struct drm_i915_private *dev_priv = connector->dev->dev_private; >> - uint8_t *eld = connector->eld; >> - uint32_t i; >> - >> - i = I915_READ(reg_eldv); >> - i &= bits_eldv; >> - >> - if (!eld[0]) >> - return !i; >> - >> - if (!i) >> - return false; >> - >> - i = I915_READ(reg_elda); >> - i &= ~bits_elda; >> - I915_WRITE(reg_elda, i); >> - >> - for (i = 0; i < eld[2]; i++) >> - if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) >> - return false; >> - >> - return true; >> -} >> - >> -static void g4x_write_eld(struct drm_connector *connector, >> - struct drm_crtc *crtc, >> - struct drm_display_mode *mode) >> -{ >> - struct drm_i915_private *dev_priv = connector->dev->dev_private; >> - uint8_t *eld = connector->eld; >> - uint32_t eldv; >> - uint32_t len; >> - uint32_t i; >> - >> - i = I915_READ(G4X_AUD_VID_DID); >> - >> - if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL) >> - eldv = G4X_ELDV_DEVCL_DEVBLC; >> - else >> - eldv = G4X_ELDV_DEVCTG; >> - >> - if (intel_eld_uptodate(connector, >> - G4X_AUD_CNTL_ST, eldv, >> - G4X_AUD_CNTL_ST, G4X_ELD_ADDR, >> - G4X_HDMIW_HDMIEDID)) >> - return; >> - >> - i = I915_READ(G4X_AUD_CNTL_ST); >> - i &= ~(eldv | G4X_ELD_ADDR); >> - len = (i >> 9) & 0x1f; /* ELD buffer size */ >> - I915_WRITE(G4X_AUD_CNTL_ST, i); >> - >> - if (!eld[0]) >> - return; >> - >> - len = min_t(uint8_t, eld[2], len); >> - DRM_DEBUG_DRIVER("ELD size %d\n", len); >> - for (i = 0; i < len; i++) >> - I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i)); >> - >> - i = I915_READ(G4X_AUD_CNTL_ST); >> - i |= eldv; >> - I915_WRITE(G4X_AUD_CNTL_ST, i); >> -} >> - >> -static void haswell_write_eld(struct drm_connector *connector, >> - struct drm_crtc *crtc, >> - struct drm_display_mode *mode) >> -{ >> - struct drm_i915_private *dev_priv = connector->dev->dev_private; >> - uint8_t *eld = connector->eld; >> - uint32_t eldv; >> - uint32_t i; >> - int len; >> - int pipe = to_intel_crtc(crtc)->pipe; >> - int tmp; >> - >> - int hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe); >> - int aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe); >> - int aud_config = HSW_AUD_CFG(pipe); >> - int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD; >> - >> - /* Audio output enable */ >> - DRM_DEBUG_DRIVER("HDMI audio: enable codec\n"); >> - tmp = I915_READ(aud_cntrl_st2); >> - tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4)); >> - I915_WRITE(aud_cntrl_st2, tmp); >> - POSTING_READ(aud_cntrl_st2); >> - >> - assert_pipe_disabled(dev_priv, to_intel_crtc(crtc)->pipe); >> - >> - /* Set ELD valid state */ >> - tmp = I915_READ(aud_cntrl_st2); >> - DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%08x\n", tmp); >> - tmp |= (AUDIO_ELD_VALID_A << (pipe * 4)); >> - I915_WRITE(aud_cntrl_st2, tmp); >> - tmp = I915_READ(aud_cntrl_st2); >> - DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%08x\n", tmp); >> - >> - /* Enable HDMI mode */ >> - tmp = I915_READ(aud_config); >> - DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%08x\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(pipe)); >> - >> - eldv = AUDIO_ELD_VALID_A << (pipe * 4); >> - >> - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { >> - DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); >> - eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ >> - I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ >> - } else { >> - I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); >> - } >> - >> - if (intel_eld_uptodate(connector, >> - aud_cntrl_st2, eldv, >> - aud_cntl_st, IBX_ELD_ADDRESS, >> - hdmiw_hdmiedid)) >> - return; >> - >> - i = I915_READ(aud_cntrl_st2); >> - i &= ~eldv; >> - I915_WRITE(aud_cntrl_st2, i); >> - >> - if (!eld[0]) >> - return; >> - >> - i = I915_READ(aud_cntl_st); >> - i &= ~IBX_ELD_ADDRESS; >> - I915_WRITE(aud_cntl_st, i); >> - i = (i >> 29) & DIP_PORT_SEL_MASK; /* 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); >> - for (i = 0; i < len; i++) >> - I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); >> - >> - i = I915_READ(aud_cntrl_st2); >> - i |= eldv; >> - I915_WRITE(aud_cntrl_st2, i); >> - >> -} >> - >> -static void ironlake_write_eld(struct drm_connector *connector, >> - struct drm_crtc *crtc, >> - struct drm_display_mode *mode) >> -{ >> - struct drm_i915_private *dev_priv = connector->dev->dev_private; >> - uint8_t *eld = connector->eld; >> - uint32_t eldv; >> - uint32_t i; >> - int len; >> - int hdmiw_hdmiedid; >> - 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(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_VALLEYVIEW(connector->dev)) { >> - hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); >> - aud_config = VLV_AUD_CFG(pipe); >> - aud_cntl_st = VLV_AUD_CNTL_ST(pipe); >> - aud_cntrl_st2 = VLV_AUD_CNTL_ST2; >> - } else { >> - 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; >> - } >> - >> - DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); >> - >> - if (IS_VALLEYVIEW(connector->dev)) { >> - struct intel_encoder *intel_encoder; >> - struct intel_digital_port *intel_dig_port; >> - >> - intel_encoder = intel_attached_encoder(connector); >> - intel_dig_port = enc_to_dig_port(&intel_encoder->base); >> - i = intel_dig_port->port; >> - } else { >> - i = I915_READ(aud_cntl_st); >> - i = (i >> 29) & DIP_PORT_SEL_MASK; >> - /* DIP_Port_Select, 0x1 = PortB */ >> - } >> - >> - if (!i) { >> - DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); >> - /* operate blindly on all ports */ >> - eldv = IBX_ELD_VALIDB; >> - eldv |= IBX_ELD_VALIDB << 4; >> - eldv |= IBX_ELD_VALIDB << 8; >> - } else { >> - DRM_DEBUG_DRIVER("ELD on port %c\n", port_name(i)); >> - eldv = IBX_ELD_VALIDB << ((i - 1) * 4); >> - } >> - >> - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { >> - DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); >> - eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ >> - I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ >> - } else { >> - I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); >> - } >> - >> - if (intel_eld_uptodate(connector, >> - aud_cntrl_st2, eldv, >> - aud_cntl_st, IBX_ELD_ADDRESS, >> - hdmiw_hdmiedid)) >> - return; >> - >> - i = I915_READ(aud_cntrl_st2); >> - i &= ~eldv; >> - I915_WRITE(aud_cntrl_st2, i); >> - >> - if (!eld[0]) >> - return; >> - >> - i = I915_READ(aud_cntl_st); >> - i &= ~IBX_ELD_ADDRESS; >> - I915_WRITE(aud_cntl_st, i); >> - >> - len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ >> - DRM_DEBUG_DRIVER("ELD size %d\n", len); >> - for (i = 0; i < len; i++) >> - I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); >> - >> - i = I915_READ(aud_cntrl_st2); >> - i |= eldv; >> - I915_WRITE(aud_cntrl_st2, i); >> -} >> - >> -void intel_write_eld(struct drm_encoder *encoder, >> - struct drm_display_mode *mode) >> -{ >> - struct drm_crtc *crtc = encoder->crtc; >> - struct drm_connector *connector; >> - struct drm_device *dev = encoder->dev; >> - struct drm_i915_private *dev_priv = dev->dev_private; >> - >> - connector = drm_select_eld(encoder, mode); >> - if (!connector) >> - return; >> - >> - DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", >> - connector->base.id, >> - connector->name, >> - connector->encoder->base.id, >> - connector->encoder->name); >> - >> - connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; >> - >> - if (dev_priv->display.write_eld) >> - dev_priv->display.write_eld(connector, crtc, mode); >> -} >> - >> static void i845_update_cursor(struct drm_crtc *crtc, u32 base) >> { >> struct drm_device *dev = crtc->dev; >> @@ -12696,31 +12388,24 @@ static void intel_init_display(struct drm_device *dev) >> dev_priv->display.get_display_clock_speed = >> i830_get_display_clock_speed; >> >> - if (IS_G4X(dev)) { >> - dev_priv->display.write_eld = g4x_write_eld; >> - } else if (IS_GEN5(dev)) { >> + if (IS_GEN5(dev)) { >> dev_priv->display.fdi_link_train = ironlake_fdi_link_train; >> - dev_priv->display.write_eld = ironlake_write_eld; >> } else if (IS_GEN6(dev)) { >> dev_priv->display.fdi_link_train = gen6_fdi_link_train; >> - dev_priv->display.write_eld = ironlake_write_eld; >> dev_priv->display.modeset_global_resources = >> snb_modeset_global_resources; >> } else if (IS_IVYBRIDGE(dev)) { >> /* FIXME: detect B0+ stepping and use auto training */ >> dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; >> - dev_priv->display.write_eld = ironlake_write_eld; >> dev_priv->display.modeset_global_resources = >> ivb_modeset_global_resources; >> } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { >> dev_priv->display.fdi_link_train = hsw_fdi_link_train; >> - dev_priv->display.write_eld = haswell_write_eld; >> dev_priv->display.modeset_global_resources = >> haswell_modeset_global_resources; >> } else if (IS_VALLEYVIEW(dev)) { >> dev_priv->display.modeset_global_resources = >> valleyview_modeset_global_resources; >> - dev_priv->display.write_eld = ironlake_write_eld; >> } >> >> /* Default just returns -ENODEV to indicate unsupported */ >> @@ -12978,6 +12663,7 @@ void intel_modeset_init(struct drm_device *dev) >> return; >> >> intel_init_display(dev); >> + intel_init_audio(dev); >> >> if (IS_GEN2(dev)) { >> dev->mode_config.max_width = 2048; >> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h >> index ca0cfd21db96..b70921053805 100644 >> --- a/drivers/gpu/drm/i915/intel_drv.h >> +++ b/drivers/gpu/drm/i915/intel_drv.h >> @@ -801,6 +801,11 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, >> struct intel_crtc_config *pipe_config); >> void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); >> >> +/* intel_audio.c */ >> +void intel_init_audio(struct drm_device *dev); >> +void intel_write_eld(struct drm_encoder *encoder, >> + struct drm_display_mode *mode); >> + >> /* intel_display.c */ >> const char *intel_output_name(int output); >> bool intel_has_pending_fb_unpin(struct drm_device *dev); >> @@ -853,6 +858,7 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, >> struct drm_file *file_priv); >> enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, >> enum pipe pipe); >> +bool intel_pipe_has_type(struct drm_crtc *crtc, int type); >> static inline void >> intel_wait_for_vblank(struct drm_device *dev, int pipe) >> { >> @@ -902,8 +908,6 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, >> void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); >> #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) >> #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) >> -void intel_write_eld(struct drm_encoder *encoder, >> - struct drm_display_mode *mode); >> unsigned long intel_gen4_compute_page_offset(int *x, int *y, >> unsigned int tiling_mode, >> unsigned int bpp, >> -- >> 2.0.1 >> >> _______________________________________________ >> Intel-gfx mailing list >> Intel-gfx@xxxxxxxxxxxxxxxxxxxxx >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx > > > > -- > Daniel Vetter > Software Engineer, Intel Corporation > +41 (0) 79 365 57 48 - http://blog.ffwll.ch -- Jani Nikula, Intel Open Source Technology Center _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx