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. -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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx