OSDN Git Service

Merge tag 'drm-intel-next-2015-04-23-fixed' of git://anongit.freedesktop.org/drm...
[uclinux-h8/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index d023710..937ba31 100644 (file)
@@ -696,15 +696,13 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (index)
                return 0;
 
        if (intel_dig_port->port == PORT_A) {
-               if (IS_GEN6(dev) || IS_GEN7(dev))
-                       return 200; /* SNB & IVB eDP input clock at 400Mhz */
-               else
-                       return 225; /* eDP input clock at 450Mhz */
+               return DIV_ROUND_UP(dev_priv->display.get_display_clock_speed(dev), 2000);
        } else {
                return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
        }
@@ -719,7 +717,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        if (intel_dig_port->port == PORT_A) {
                if (index)
                        return 0;
-               return DIV_ROUND_CLOSEST(intel_ddi_get_cdclk_freq(dev_priv), 2000);
+               return DIV_ROUND_CLOSEST(dev_priv->display.get_display_clock_speed(dev), 2000);
        } else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
                /* Workaround for non-ULT HSW */
                switch (index) {
@@ -876,9 +874,18 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
                                   DP_AUX_CH_CTL_TIME_OUT_ERROR |
                                   DP_AUX_CH_CTL_RECEIVE_ERROR);
 
-                       if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
-                                     DP_AUX_CH_CTL_RECEIVE_ERROR))
+                       if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
+                               continue;
+
+                       /* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
+                        *   400us delay required for errors and timeouts
+                        *   Timeout errors from the HW already meet this
+                        *   requirement so skip to next iteration
+                        */
+                       if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+                               usleep_range(400, 500);
                                continue;
+                       }
                        if (status & DP_AUX_CH_CTL_DONE)
                                break;
                }
@@ -1353,6 +1360,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
                intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
                                       adjusted_mode);
+
+               if (INTEL_INFO(dev)->gen >= 9) {
+                       int ret;
+                       ret = skl_update_scaler_users(intel_crtc, pipe_config, NULL, NULL, 0);
+                       if (ret)
+                               return ret;
+               }
+
                if (!HAS_PCH_SPLIT(dev))
                        intel_gmch_panel_fitting(intel_crtc, pipe_config,
                                                 intel_connector->panel.fitting_mode);
@@ -1465,6 +1480,8 @@ found:
 
        if (IS_SKYLAKE(dev) && is_edp(intel_dp))
                skl_edp_set_pll_config(pipe_config, common_rates[clock]);
+       else if (IS_BROXTON(dev))
+               /* handled in ddi */;
        else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
        else
@@ -2874,7 +2891,9 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum port port = dp_to_dig_port(intel_dp)->port;
 
-       if (INTEL_INFO(dev)->gen >= 9) {
+       if (IS_BROXTON(dev))
+               return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+       else if (INTEL_INFO(dev)->gen >= 9) {
                if (dev_priv->vbt.edp_low_vswing && port == PORT_A)
                        return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
@@ -2956,7 +2975,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
        }
 }
 
-static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
+static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3056,7 +3075,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        return 0;
 }
 
-static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)
+static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3263,7 +3282,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp,
 }
 
 static uint32_t
-intel_gen4_signal_levels(uint8_t train_set)
+gen4_signal_levels(uint8_t train_set)
 {
        uint32_t        signal_levels = 0;
 
@@ -3302,7 +3321,7 @@ intel_gen4_signal_levels(uint8_t train_set)
 
 /* Gen6's DP voltage swing and pre-emphasis control */
 static uint32_t
-intel_gen6_edp_signal_levels(uint8_t train_set)
+gen6_edp_signal_levels(uint8_t train_set)
 {
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
@@ -3330,7 +3349,7 @@ intel_gen6_edp_signal_levels(uint8_t train_set)
 
 /* Gen7's DP voltage swing and pre-emphasis control */
 static uint32_t
-intel_gen7_edp_signal_levels(uint8_t train_set)
+gen7_edp_signal_levels(uint8_t train_set)
 {
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
@@ -3361,7 +3380,7 @@ intel_gen7_edp_signal_levels(uint8_t train_set)
 
 /* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
 static uint32_t
-intel_hsw_signal_levels(uint8_t train_set)
+hsw_signal_levels(uint8_t train_set)
 {
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
@@ -3396,6 +3415,55 @@ intel_hsw_signal_levels(uint8_t train_set)
        }
 }
 
+static void bxt_signal_levels(struct intel_dp *intel_dp)
+{
+       struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
+       enum port port = dport->port;
+       struct drm_device *dev = dport->base.base.dev;
+       struct intel_encoder *encoder = &dport->base;
+       uint8_t train_set = intel_dp->train_set[0];
+       uint32_t level = 0;
+
+       int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
+                                        DP_TRAIN_PRE_EMPHASIS_MASK);
+       switch (signal_levels) {
+       default:
+               DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n");
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               level = 0;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+               level = 1;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
+               level = 2;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3:
+               level = 3;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               level = 4;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+               level = 5;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2:
+               level = 6;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               level = 7;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+               level = 8;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               level = 9;
+               break;
+       }
+
+       bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
+}
+
 /* Properly updates "DP" with the correct signal levels. */
 static void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
@@ -3406,27 +3474,38 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
        uint32_t signal_levels, mask;
        uint8_t train_set = intel_dp->train_set[0];
 
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
-               signal_levels = intel_hsw_signal_levels(train_set);
+       if (IS_BROXTON(dev)) {
+               signal_levels = 0;
+               bxt_signal_levels(intel_dp);
+               mask = 0;
+       } else if (HAS_DDI(dev)) {
+               signal_levels = hsw_signal_levels(train_set);
                mask = DDI_BUF_EMP_MASK;
        } else if (IS_CHERRYVIEW(dev)) {
-               signal_levels = intel_chv_signal_levels(intel_dp);
+               signal_levels = chv_signal_levels(intel_dp);
                mask = 0;
        } else if (IS_VALLEYVIEW(dev)) {
-               signal_levels = intel_vlv_signal_levels(intel_dp);
+               signal_levels = vlv_signal_levels(intel_dp);
                mask = 0;
        } else if (IS_GEN7(dev) && port == PORT_A) {
-               signal_levels = intel_gen7_edp_signal_levels(train_set);
+               signal_levels = gen7_edp_signal_levels(train_set);
                mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
        } else if (IS_GEN6(dev) && port == PORT_A) {
-               signal_levels = intel_gen6_edp_signal_levels(train_set);
+               signal_levels = gen6_edp_signal_levels(train_set);
                mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;
        } else {
-               signal_levels = intel_gen4_signal_levels(train_set);
+               signal_levels = gen4_signal_levels(train_set);
                mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK;
        }
 
-       DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels);
+       if (mask)
+               DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels);
+
+       DRM_DEBUG_KMS("Using vswing level %d\n",
+               train_set & DP_TRAIN_VOLTAGE_SWING_MASK);
+       DRM_DEBUG_KMS("Using pre-emphasis level %d\n",
+               (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) >>
+                       DP_TRAIN_PRE_EMPHASIS_SHIFT);
 
        *DP = (*DP & ~mask) | signal_levels;
 }
@@ -3782,6 +3861,21 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
                        dev_priv->psr.sink_support = true;
                        DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
                }
+
+               if (INTEL_INFO(dev)->gen >= 9 &&
+                       (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
+                       uint8_t frame_sync_cap;
+
+                       dev_priv->psr.sink_support = true;
+                       intel_dp_dpcd_read_wake(&intel_dp->aux,
+                                       DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
+                                       &frame_sync_cap, 1);
+                       dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
+                       /* PSR2 needs frame sync as well */
+                       dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
+                       DRM_DEBUG_KMS("PSR2 %s on sink",
+                               dev_priv->psr.psr2_support ? "supported" : "not supported");
+               }
        }
 
        /* Training Pattern 3 support, both source and sink */
@@ -3949,11 +4043,78 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
        return true;
 }
 
-static void
-intel_dp_handle_test_request(struct intel_dp *intel_dp)
+static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
+{
+       uint8_t test_result = DP_TEST_ACK;
+       return test_result;
+}
+
+static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
+{
+       uint8_t test_result = DP_TEST_NAK;
+       return test_result;
+}
+
+static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)
 {
-       /* NAK by default */
-       drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, DP_TEST_NAK);
+       uint8_t test_result = DP_TEST_NAK;
+       return test_result;
+}
+
+static uint8_t intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
+{
+       uint8_t test_result = DP_TEST_NAK;
+       return test_result;
+}
+
+static void intel_dp_handle_test_request(struct intel_dp *intel_dp)
+{
+       uint8_t response = DP_TEST_NAK;
+       uint8_t rxdata = 0;
+       int status = 0;
+
+       intel_dp->compliance_test_type = 0;
+       intel_dp->aux.i2c_nack_count = 0;
+       intel_dp->aux.i2c_defer_count = 0;
+
+       status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_REQUEST, &rxdata, 1);
+       if (status <= 0) {
+               DRM_DEBUG_KMS("Could not read test request from sink\n");
+               goto update_status;
+       }
+
+       switch (rxdata) {
+       case DP_TEST_LINK_TRAINING:
+               DRM_DEBUG_KMS("LINK_TRAINING test requested\n");
+               intel_dp->compliance_test_type = DP_TEST_LINK_TRAINING;
+               response = intel_dp_autotest_link_training(intel_dp);
+               break;
+       case DP_TEST_LINK_VIDEO_PATTERN:
+               DRM_DEBUG_KMS("TEST_PATTERN test requested\n");
+               intel_dp->compliance_test_type = DP_TEST_LINK_VIDEO_PATTERN;
+               response = intel_dp_autotest_video_pattern(intel_dp);
+               break;
+       case DP_TEST_LINK_EDID_READ:
+               DRM_DEBUG_KMS("EDID test requested\n");
+               intel_dp->compliance_test_type = DP_TEST_LINK_EDID_READ;
+               response = intel_dp_autotest_edid(intel_dp);
+               break;
+       case DP_TEST_LINK_PHY_TEST_PATTERN:
+               DRM_DEBUG_KMS("PHY_PATTERN test requested\n");
+               intel_dp->compliance_test_type = DP_TEST_LINK_PHY_TEST_PATTERN;
+               response = intel_dp_autotest_phy_pattern(intel_dp);
+               break;
+       default:
+               DRM_DEBUG_KMS("Invalid test request '%02x'\n", rxdata);
+               break;
+       }
+
+update_status:
+       status = drm_dp_dpcd_write(&intel_dp->aux,
+                                  DP_TEST_RESPONSE,
+                                  &response, 1);
+       if (status <= 0)
+               DRM_DEBUG_KMS("Could not write test response to sink\n");
 }
 
 static int
@@ -5574,6 +5735,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
        }
 
+       i915_debugfs_connector_add(connector);
+
        return true;
 }