]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/gpu/drm/i915/intel_ddi.c
drm/i915: only disable DDI sound if intel_crtc->eld_vld
[linux-imx.git] / drivers / gpu / drm / i915 / intel_ddi.c
index 8d0bac3c35d7df012225ea47e922c60b353a0915..3e946d3cd196b2a6c70165bcca4cb2eb317ef60f 100644 (file)
@@ -181,7 +181,8 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 
        /* Enable the PCH Receiver FDI PLL */
        rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
-                    FDI_RX_PLL_ENABLE | ((intel_crtc->fdi_lanes - 1) << 19);
+                    FDI_RX_PLL_ENABLE |
+                    FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
        I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
        POSTING_READ(_FDI_RXA_CTL);
        udelay(220);
@@ -209,7 +210,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
                 * port reversal bit */
                I915_WRITE(DDI_BUF_CTL(PORT_E),
                           DDI_BUF_CTL_ENABLE |
-                          ((intel_crtc->fdi_lanes - 1) << 1) |
+                          ((intel_crtc->config.fdi_lanes - 1) << 1) |
                           hsw_ddi_buf_ctl_values[i / 2]);
                POSTING_READ(DDI_BUF_CTL(PORT_E));
 
@@ -675,7 +676,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
        int pipe = intel_crtc->pipe;
        int type = intel_encoder->type;
 
-       DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
+       DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
                      port_name(port), pipe_name(pipe));
 
        intel_crtc->eld_vld = false;
@@ -686,22 +687,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
 
                intel_dp->DP = intel_dig_port->port_reversal |
                               DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
-               switch (intel_dp->lane_count) {
-               case 1:
-                       intel_dp->DP |= DDI_PORT_WIDTH_X1;
-                       break;
-               case 2:
-                       intel_dp->DP |= DDI_PORT_WIDTH_X2;
-                       break;
-               case 4:
-                       intel_dp->DP |= DDI_PORT_WIDTH_X4;
-                       break;
-               default:
-                       intel_dp->DP |= DDI_PORT_WIDTH_X4;
-                       WARN(1, "Unexpected DP lane count %d\n",
-                            intel_dp->lane_count);
-                       break;
-               }
+               intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
 
                if (intel_dp->has_audio) {
                        DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
@@ -748,8 +734,8 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
        }
 
        if (num_encoders != 1)
-               WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
-                    intel_crtc->pipe);
+               WARN(1, "%d encoders on crtc for pipe %c\n", num_encoders,
+                    pipe_name(intel_crtc->pipe));
 
        BUG_ON(ret == NULL);
        return ret;
@@ -898,6 +884,9 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
                        plls->spll_refcount++;
                        reg = SPLL_CTL;
                        intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+               } else {
+                       DRM_ERROR("SPLL already in use\n");
+                       return false;
                }
 
                WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
@@ -921,14 +910,14 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
-       enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
        int type = intel_encoder->type;
        uint32_t temp;
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 
                temp = TRANS_MSA_SYNC_CLK;
-               switch (intel_crtc->bpp) {
+               switch (intel_crtc->config.pipe_bpp) {
                case 18:
                        temp |= TRANS_MSA_6_BPC;
                        break;
@@ -942,22 +931,20 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
                        temp |= TRANS_MSA_12_BPC;
                        break;
                default:
-                       temp |= TRANS_MSA_8_BPC;
-                       WARN(1, "%d bpp unsupported by DDI function\n",
-                            intel_crtc->bpp);
+                       BUG();
                }
                I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp);
        }
 }
 
-void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
+void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
        struct drm_encoder *encoder = &intel_encoder->base;
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        enum pipe pipe = intel_crtc->pipe;
-       enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
        enum port port = intel_ddi_get_encoder_port(intel_encoder);
        int type = intel_encoder->type;
        uint32_t temp;
@@ -966,7 +953,7 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
        temp = TRANS_DDI_FUNC_ENABLE;
        temp |= TRANS_DDI_SELECT_PORT(port);
 
-       switch (intel_crtc->bpp) {
+       switch (intel_crtc->config.pipe_bpp) {
        case 18:
                temp |= TRANS_DDI_BPC_6;
                break;
@@ -980,8 +967,7 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
                temp |= TRANS_DDI_BPC_12;
                break;
        default:
-               WARN(1, "%d bpp unsupported by transcoder DDI function\n",
-                    intel_crtc->bpp);
+               BUG();
        }
 
        if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
@@ -995,7 +981,7 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
                        /* Can only use the always-on power well for eDP when
                         * not using the panel fitter, and when not using motion
                          * blur mitigation (which we don't support). */
-                       if (dev_priv->pch_pf_size)
+                       if (intel_crtc->config.pch_pfit.size)
                                temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
                        else
                                temp |= TRANS_DDI_EDP_INPUT_A_ON;
@@ -1022,7 +1008,7 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 
        } else if (type == INTEL_OUTPUT_ANALOG) {
                temp |= TRANS_DDI_MODE_SELECT_FDI;
-               temp |= (intel_crtc->fdi_lanes - 1) << 1;
+               temp |= (intel_crtc->config.fdi_lanes - 1) << 1;
 
        } else if (type == INTEL_OUTPUT_DISPLAYPORT ||
                   type == INTEL_OUTPUT_EDP) {
@@ -1030,25 +1016,10 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 
                temp |= TRANS_DDI_MODE_SELECT_DP_SST;
 
-               switch (intel_dp->lane_count) {
-               case 1:
-                       temp |= TRANS_DDI_PORT_WIDTH_X1;
-                       break;
-               case 2:
-                       temp |= TRANS_DDI_PORT_WIDTH_X2;
-                       break;
-               case 4:
-                       temp |= TRANS_DDI_PORT_WIDTH_X4;
-                       break;
-               default:
-                       temp |= TRANS_DDI_PORT_WIDTH_X4;
-                       WARN(1, "Unsupported lane count %d\n",
-                            intel_dp->lane_count);
-               }
-
+               temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
        } else {
-               WARN(1, "Invalid encoder type %d for pipe %d\n",
-                    intel_encoder->type, pipe);
+               WARN(1, "Invalid encoder type %d for pipe %c\n",
+                    intel_encoder->type, pipe_name(pipe));
        }
 
        I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
@@ -1148,16 +1119,16 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
                }
        }
 
-       DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port);
+       DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port));
 
-       return true;
+       return false;
 }
 
 static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
                                       enum pipe pipe)
 {
        uint32_t temp, ret;
-       enum port port;
+       enum port port = I915_MAX_PORTS;
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
        int i;
@@ -1173,10 +1144,16 @@ static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
                                port = i;
        }
 
-       ret = I915_READ(PORT_CLK_SEL(port));
-
-       DRM_DEBUG_KMS("Pipe %c connected to port %c using clock 0x%08x\n",
-                     pipe_name(pipe), port_name(port), ret);
+       if (port == I915_MAX_PORTS) {
+               WARN(1, "Pipe %c enabled on an unknown port\n",
+                    pipe_name(pipe));
+               ret = PORT_CLK_SEL_NONE;
+       } else {
+               ret = I915_READ(PORT_CLK_SEL(port));
+               DRM_DEBUG_KMS("Pipe %c connected to port %c using clock "
+                             "0x%08x\n", pipe_name(pipe), port_name(port),
+                             ret);
+       }
 
        return ret;
 }
@@ -1217,7 +1194,7 @@ void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
        enum port port = intel_ddi_get_encoder_port(intel_encoder);
-       enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
 
        if (cpu_transcoder != TRANSCODER_EDP)
                I915_WRITE(TRANS_CLK_SEL(cpu_transcoder),
@@ -1227,7 +1204,7 @@ void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
 void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
 {
        struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
-       enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
 
        if (cpu_transcoder != TRANSCODER_EDP)
                I915_WRITE(TRANS_CLK_SEL(cpu_transcoder),
@@ -1323,7 +1300,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
                ironlake_edp_backlight_on(intel_dp);
        }
 
-       if (intel_crtc->eld_vld) {
+       if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
                tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
                tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
                I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
@@ -1341,15 +1318,18 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
+       if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
+               tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+               tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) <<
+                        (pipe * 4));
+               I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+       }
+
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
                ironlake_edp_backlight_off(intel_dp);
        }
-
-       tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
-       tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
-       I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
 }
 
 int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
@@ -1467,19 +1447,17 @@ static void intel_ddi_destroy(struct drm_encoder *encoder)
        intel_dp_encoder_destroy(encoder);
 }
 
-static bool intel_ddi_mode_fixup(struct drm_encoder *encoder,
-                                const struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode)
+static bool intel_ddi_compute_config(struct intel_encoder *encoder,
+                                    struct intel_crtc_config *pipe_config)
 {
-       struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-       int type = intel_encoder->type;
+       int type = encoder->type;
 
-       WARN(type == INTEL_OUTPUT_UNKNOWN, "mode_fixup() on unknown output!\n");
+       WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n");
 
        if (type == INTEL_OUTPUT_HDMI)
-               return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode);
+               return intel_hdmi_compute_config(encoder, pipe_config);
        else
-               return intel_dp_mode_fixup(encoder, mode, adjusted_mode);
+               return intel_dp_compute_config(encoder, pipe_config);
 }
 
 static const struct drm_encoder_funcs intel_ddi_funcs = {
@@ -1487,7 +1465,6 @@ static const struct drm_encoder_funcs intel_ddi_funcs = {
 };
 
 static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
-       .mode_fixup = intel_ddi_mode_fixup,
        .mode_set = intel_ddi_mode_set,
 };
 
@@ -1510,16 +1487,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
                return;
        }
 
-       if (port != PORT_A) {
-               hdmi_connector = kzalloc(sizeof(struct intel_connector),
-                                        GFP_KERNEL);
-               if (!hdmi_connector) {
-                       kfree(dp_connector);
-                       kfree(intel_dig_port);
-                       return;
-               }
-       }
-
        intel_encoder = &intel_dig_port->base;
        encoder = &intel_encoder->base;
 
@@ -1527,6 +1494,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
                         DRM_MODE_ENCODER_TMDS);
        drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
 
+       intel_encoder->compute_config = intel_ddi_compute_config;
        intel_encoder->enable = intel_enable_ddi;
        intel_encoder->pre_enable = intel_ddi_pre_enable;
        intel_encoder->disable = intel_disable_ddi;
@@ -1536,10 +1504,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
        intel_dig_port->port = port;
        intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
                                        DDI_BUF_PORT_REVERSAL;
-       if (hdmi_connector)
-               intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
-       else
-               intel_dig_port->hdmi.sdvox_reg = 0;
        intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
 
        intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
@@ -1547,7 +1511,16 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
        intel_encoder->cloneable = false;
        intel_encoder->hot_plug = intel_ddi_hot_plug;
 
-       if (hdmi_connector)
-               intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
        intel_dp_init_connector(intel_dig_port, dp_connector);
+
+       if (intel_encoder->type != INTEL_OUTPUT_EDP) {
+               hdmi_connector = kzalloc(sizeof(struct intel_connector),
+                                        GFP_KERNEL);
+               if (!hdmi_connector) {
+                       return;
+               }
+
+               intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
+               intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
+       }
 }