Merge tag 'v4.15-rc1' into drm-misc-fixes
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / intel_hdmi.c
index 3fed1d3ecdedfdd5b51d13d42924a21d2299fde3..4dea833f9d1b78c17239eeade593a72c88fbc166 100644 (file)
@@ -70,7 +70,7 @@ static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
        return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
 }
 
-static u32 g4x_infoframe_index(enum hdmi_infoframe_type type)
+static u32 g4x_infoframe_index(unsigned int type)
 {
        switch (type) {
        case HDMI_INFOFRAME_TYPE_AVI:
@@ -85,7 +85,7 @@ static u32 g4x_infoframe_index(enum hdmi_infoframe_type type)
        }
 }
 
-static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type)
+static u32 g4x_infoframe_enable(unsigned int type)
 {
        switch (type) {
        case HDMI_INFOFRAME_TYPE_AVI:
@@ -100,9 +100,11 @@ static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type)
        }
 }
 
-static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
+static u32 hsw_infoframe_enable(unsigned int type)
 {
        switch (type) {
+       case DP_SDP_VSC:
+               return VIDEO_DIP_ENABLE_VSC_HSW;
        case HDMI_INFOFRAME_TYPE_AVI:
                return VIDEO_DIP_ENABLE_AVI_HSW;
        case HDMI_INFOFRAME_TYPE_SPD:
@@ -118,10 +120,12 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
 static i915_reg_t
 hsw_dip_data_reg(struct drm_i915_private *dev_priv,
                 enum transcoder cpu_transcoder,
-                enum hdmi_infoframe_type type,
+                unsigned int type,
                 int i)
 {
        switch (type) {
+       case DP_SDP_VSC:
+               return HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i);
        case HDMI_INFOFRAME_TYPE_AVI:
                return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i);
        case HDMI_INFOFRAME_TYPE_SPD:
@@ -136,7 +140,7 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv,
 
 static void g4x_write_infoframe(struct drm_encoder *encoder,
                                const struct intel_crtc_state *crtc_state,
-                               enum hdmi_infoframe_type type,
+                               unsigned int type,
                                const void *frame, ssize_t len)
 {
        const uint32_t *data = frame;
@@ -191,7 +195,7 @@ static bool g4x_infoframe_enabled(struct drm_encoder *encoder,
 
 static void ibx_write_infoframe(struct drm_encoder *encoder,
                                const struct intel_crtc_state *crtc_state,
-                               enum hdmi_infoframe_type type,
+                               unsigned int type,
                                const void *frame, ssize_t len)
 {
        const uint32_t *data = frame;
@@ -251,7 +255,7 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder,
 
 static void cpt_write_infoframe(struct drm_encoder *encoder,
                                const struct intel_crtc_state *crtc_state,
-                               enum hdmi_infoframe_type type,
+                               unsigned int type,
                                const void *frame, ssize_t len)
 {
        const uint32_t *data = frame;
@@ -309,7 +313,7 @@ static bool cpt_infoframe_enabled(struct drm_encoder *encoder,
 
 static void vlv_write_infoframe(struct drm_encoder *encoder,
                                const struct intel_crtc_state *crtc_state,
-                               enum hdmi_infoframe_type type,
+                               unsigned int type,
                                const void *frame, ssize_t len)
 {
        const uint32_t *data = frame;
@@ -368,7 +372,7 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder,
 
 static void hsw_write_infoframe(struct drm_encoder *encoder,
                                const struct intel_crtc_state *crtc_state,
-                               enum hdmi_infoframe_type type,
+                               unsigned int type,
                                const void *frame, ssize_t len)
 {
        const uint32_t *data = frame;
@@ -377,6 +381,8 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
        i915_reg_t data_reg;
+       int data_size = type == DP_SDP_VSC ?
+               VIDEO_DIP_VSC_DATA_SIZE : VIDEO_DIP_DATA_SIZE;
        int i;
        u32 val = I915_READ(ctl_reg);
 
@@ -392,7 +398,7 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
                data++;
        }
        /* Write every possible data byte to force correct ECC calculation. */
-       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+       for (; i < data_size; i += 4)
                I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
                                            type, i >> 2), 0);
        mmiowb();
@@ -434,7 +440,7 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
                                  const struct intel_crtc_state *crtc_state,
                                  union hdmi_infoframe *frame)
 {
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
        uint8_t buffer[VIDEO_DIP_DATA_SIZE];
        ssize_t len;
 
@@ -450,7 +456,7 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
        buffer[3] = 0;
        len++;
 
-       intel_hdmi->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
+       intel_dig_port->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
 }
 
 static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
@@ -946,6 +952,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
                                  struct intel_crtc_state *pipe_config)
 {
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+       struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi);
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        u32 tmp, flags = 0;
@@ -966,7 +973,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
        if (tmp & HDMI_MODE_SELECT_HDMI)
                pipe_config->has_hdmi_sink = true;
 
-       if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config))
+       if (intel_dig_port->infoframe_enabled(&encoder->base, pipe_config))
                pipe_config->has_infoframe = true;
 
        if (tmp & SDVO_AUDIO_ENABLE)
@@ -992,8 +999,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
 }
 
 static void intel_enable_hdmi_audio(struct intel_encoder *encoder,
-                                   struct intel_crtc_state *pipe_config,
-                                   struct drm_connector_state *conn_state)
+                                   const struct intel_crtc_state *pipe_config,
+                                   const struct drm_connector_state *conn_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
 
@@ -1004,8 +1011,8 @@ static void intel_enable_hdmi_audio(struct intel_encoder *encoder,
 }
 
 static void g4x_enable_hdmi(struct intel_encoder *encoder,
-                           struct intel_crtc_state *pipe_config,
-                           struct drm_connector_state *conn_state)
+                           const struct intel_crtc_state *pipe_config,
+                           const struct drm_connector_state *conn_state)
 {
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1026,8 +1033,8 @@ static void g4x_enable_hdmi(struct intel_encoder *encoder,
 }
 
 static void ibx_enable_hdmi(struct intel_encoder *encoder,
-                           struct intel_crtc_state *pipe_config,
-                           struct drm_connector_state *conn_state)
+                           const struct intel_crtc_state *pipe_config,
+                           const struct drm_connector_state *conn_state)
 {
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1076,8 +1083,8 @@ static void ibx_enable_hdmi(struct intel_encoder *encoder,
 }
 
 static void cpt_enable_hdmi(struct intel_encoder *encoder,
-                           struct intel_crtc_state *pipe_config,
-                           struct drm_connector_state *conn_state)
+                           const struct intel_crtc_state *pipe_config,
+                           const struct drm_connector_state *conn_state)
 {
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1131,18 +1138,20 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder,
 }
 
 static void vlv_enable_hdmi(struct intel_encoder *encoder,
-                           struct intel_crtc_state *pipe_config,
-                           struct drm_connector_state *conn_state)
+                           const struct intel_crtc_state *pipe_config,
+                           const struct drm_connector_state *conn_state)
 {
 }
 
 static void intel_disable_hdmi(struct intel_encoder *encoder,
-                              struct intel_crtc_state *old_crtc_state,
-                              struct drm_connector_state *old_conn_state)
+                              const struct intel_crtc_state *old_crtc_state,
+                              const struct drm_connector_state *old_conn_state)
 {
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+       struct intel_digital_port *intel_dig_port =
+               hdmi_to_dig_port(intel_hdmi);
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
        u32 temp;
 
@@ -1185,14 +1194,15 @@ static void intel_disable_hdmi(struct intel_encoder *encoder,
                intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
        }
 
-       intel_hdmi->set_infoframes(&encoder->base, false, old_crtc_state, old_conn_state);
+       intel_dig_port->set_infoframes(&encoder->base, false,
+                                      old_crtc_state, old_conn_state);
 
        intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
 }
 
 static void g4x_disable_hdmi(struct intel_encoder *encoder,
-                            struct intel_crtc_state *old_crtc_state,
-                            struct drm_connector_state *old_conn_state)
+                            const struct intel_crtc_state *old_crtc_state,
+                            const struct drm_connector_state *old_conn_state)
 {
        if (old_crtc_state->has_audio)
                intel_audio_codec_disable(encoder);
@@ -1201,16 +1211,16 @@ static void g4x_disable_hdmi(struct intel_encoder *encoder,
 }
 
 static void pch_disable_hdmi(struct intel_encoder *encoder,
-                            struct intel_crtc_state *old_crtc_state,
-                            struct drm_connector_state *old_conn_state)
+                            const struct intel_crtc_state *old_crtc_state,
+                            const struct drm_connector_state *old_conn_state)
 {
        if (old_crtc_state->has_audio)
                intel_audio_codec_disable(encoder);
 }
 
 static void pch_post_disable_hdmi(struct intel_encoder *encoder,
-                                 struct intel_crtc_state *old_crtc_state,
-                                 struct drm_connector_state *old_conn_state)
+                                 const struct intel_crtc_state *old_crtc_state,
+                                 const struct drm_connector_state *old_conn_state)
 {
        intel_disable_hdmi(encoder, old_crtc_state, old_conn_state);
 }
@@ -1315,7 +1325,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
        return status;
 }
 
-static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
+static bool hdmi_12bpc_possible(const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv =
                to_i915(crtc_state->base.crtc->dev);
@@ -1643,24 +1653,24 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)
 }
 
 static void intel_hdmi_pre_enable(struct intel_encoder *encoder,
-                                 struct intel_crtc_state *pipe_config,
-                                 struct drm_connector_state *conn_state)
+                                 const struct intel_crtc_state *pipe_config,
+                                 const struct drm_connector_state *conn_state)
 {
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+       struct intel_digital_port *intel_dig_port =
+               enc_to_dig_port(&encoder->base);
 
        intel_hdmi_prepare(encoder, pipe_config);
 
-       intel_hdmi->set_infoframes(&encoder->base,
-                                  pipe_config->has_hdmi_sink,
-                                  pipe_config, conn_state);
+       intel_dig_port->set_infoframes(&encoder->base,
+                                      pipe_config->has_infoframe,
+                                      pipe_config, conn_state);
 }
 
 static void vlv_hdmi_pre_enable(struct intel_encoder *encoder,
-                               struct intel_crtc_state *pipe_config,
-                               struct drm_connector_state *conn_state)
+                               const struct intel_crtc_state *pipe_config,
+                               const struct drm_connector_state *conn_state)
 {
        struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
-       struct intel_hdmi *intel_hdmi = &dport->hdmi;
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
@@ -1670,9 +1680,9 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder,
        vlv_set_phy_signal_level(encoder, 0x2b245f5f, 0x00002000, 0x5578b83a,
                                 0x2b247878);
 
-       intel_hdmi->set_infoframes(&encoder->base,
-                                  pipe_config->has_hdmi_sink,
-                                  pipe_config, conn_state);
+       dport->set_infoframes(&encoder->base,
+                             pipe_config->has_infoframe,
+                             pipe_config, conn_state);
 
        g4x_enable_hdmi(encoder, pipe_config, conn_state);
 
@@ -1680,8 +1690,8 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder,
 }
 
 static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder,
-                                   struct intel_crtc_state *pipe_config,
-                                   struct drm_connector_state *conn_state)
+                                   const struct intel_crtc_state *pipe_config,
+                                   const struct drm_connector_state *conn_state)
 {
        intel_hdmi_prepare(encoder, pipe_config);
 
@@ -1689,8 +1699,8 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder,
 }
 
 static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder,
-                                   struct intel_crtc_state *pipe_config,
-                                   struct drm_connector_state *conn_state)
+                                   const struct intel_crtc_state *pipe_config,
+                                   const struct drm_connector_state *conn_state)
 {
        intel_hdmi_prepare(encoder, pipe_config);
 
@@ -1698,23 +1708,23 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder,
 }
 
 static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder,
-                                     struct intel_crtc_state *old_crtc_state,
-                                     struct drm_connector_state *old_conn_state)
+                                     const struct intel_crtc_state *old_crtc_state,
+                                     const struct drm_connector_state *old_conn_state)
 {
        chv_phy_post_pll_disable(encoder);
 }
 
 static void vlv_hdmi_post_disable(struct intel_encoder *encoder,
-                                 struct intel_crtc_state *old_crtc_state,
-                                 struct drm_connector_state *old_conn_state)
+                                 const struct intel_crtc_state *old_crtc_state,
+                                 const struct drm_connector_state *old_conn_state)
 {
        /* Reset lanes to avoid HDMI flicker (VLV w/a) */
        vlv_phy_reset_lanes(encoder);
 }
 
 static void chv_hdmi_post_disable(struct intel_encoder *encoder,
-                                 struct intel_crtc_state *old_crtc_state,
-                                 struct drm_connector_state *old_conn_state)
+                                 const struct intel_crtc_state *old_crtc_state,
+                                 const struct drm_connector_state *old_conn_state)
 {
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1728,11 +1738,10 @@ static void chv_hdmi_post_disable(struct intel_encoder *encoder,
 }
 
 static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
-                               struct intel_crtc_state *pipe_config,
-                               struct drm_connector_state *conn_state)
+                               const struct intel_crtc_state *pipe_config,
+                               const struct drm_connector_state *conn_state)
 {
        struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
-       struct intel_hdmi *intel_hdmi = &dport->hdmi;
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
@@ -1742,9 +1751,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
        /* Use 800mV-0dB */
        chv_set_phy_signal_level(encoder, 128, 102, false);
 
-       intel_hdmi->set_infoframes(&encoder->base,
-                                  pipe_config->has_hdmi_sink,
-                                  pipe_config, conn_state);
+       dport->set_infoframes(&encoder->base,
+                             pipe_config->has_infoframe,
+                             pipe_config, conn_state);
 
        g4x_enable_hdmi(encoder, pipe_config, conn_state);
 
@@ -1959,6 +1968,34 @@ static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv,
        return ddc_pin;
 }
 
+void intel_infoframe_init(struct intel_digital_port *intel_dig_port)
+{
+       struct drm_i915_private *dev_priv =
+               to_i915(intel_dig_port->base.base.dev);
+
+       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+               intel_dig_port->write_infoframe = vlv_write_infoframe;
+               intel_dig_port->set_infoframes = vlv_set_infoframes;
+               intel_dig_port->infoframe_enabled = vlv_infoframe_enabled;
+       } else if (IS_G4X(dev_priv)) {
+               intel_dig_port->write_infoframe = g4x_write_infoframe;
+               intel_dig_port->set_infoframes = g4x_set_infoframes;
+               intel_dig_port->infoframe_enabled = g4x_infoframe_enabled;
+       } else if (HAS_DDI(dev_priv)) {
+               intel_dig_port->write_infoframe = hsw_write_infoframe;
+               intel_dig_port->set_infoframes = hsw_set_infoframes;
+               intel_dig_port->infoframe_enabled = hsw_infoframe_enabled;
+       } else if (HAS_PCH_IBX(dev_priv)) {
+               intel_dig_port->write_infoframe = ibx_write_infoframe;
+               intel_dig_port->set_infoframes = ibx_set_infoframes;
+               intel_dig_port->infoframe_enabled = ibx_infoframe_enabled;
+       } else {
+               intel_dig_port->write_infoframe = cpt_write_infoframe;
+               intel_dig_port->set_infoframes = cpt_set_infoframes;
+               intel_dig_port->infoframe_enabled = cpt_infoframe_enabled;
+       }
+}
+
 void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                               struct intel_connector *intel_connector)
 {
@@ -1994,28 +2031,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                return;
        intel_encoder->hpd_pin = intel_hpd_pin(port);
 
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               intel_hdmi->write_infoframe = vlv_write_infoframe;
-               intel_hdmi->set_infoframes = vlv_set_infoframes;
-               intel_hdmi->infoframe_enabled = vlv_infoframe_enabled;
-       } else if (IS_G4X(dev_priv)) {
-               intel_hdmi->write_infoframe = g4x_write_infoframe;
-               intel_hdmi->set_infoframes = g4x_set_infoframes;
-               intel_hdmi->infoframe_enabled = g4x_infoframe_enabled;
-       } else if (HAS_DDI(dev_priv)) {
-               intel_hdmi->write_infoframe = hsw_write_infoframe;
-               intel_hdmi->set_infoframes = hsw_set_infoframes;
-               intel_hdmi->infoframe_enabled = hsw_infoframe_enabled;
-       } else if (HAS_PCH_IBX(dev_priv)) {
-               intel_hdmi->write_infoframe = ibx_write_infoframe;
-               intel_hdmi->set_infoframes = ibx_set_infoframes;
-               intel_hdmi->infoframe_enabled = ibx_infoframe_enabled;
-       } else {
-               intel_hdmi->write_infoframe = cpt_write_infoframe;
-               intel_hdmi->set_infoframes = cpt_set_infoframes;
-               intel_hdmi->infoframe_enabled = cpt_infoframe_enabled;
-       }
-
        if (HAS_DDI(dev_priv))
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
        else
@@ -2114,5 +2129,7 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv,
        intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
        intel_dig_port->max_lanes = 4;
 
+       intel_infoframe_init(intel_dig_port);
+
        intel_hdmi_init_connector(intel_dig_port, intel_connector);
 }