|
@@ -1613,6 +1613,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
|
|
/* Conveniently, the link BW constants become indices with a shift...*/
|
|
|
int min_clock = 0;
|
|
|
int max_clock;
|
|
|
+ int link_rate_index;
|
|
|
int bpp, mode_rate;
|
|
|
int link_avail, link_clock;
|
|
|
int common_rates[DP_MAX_SUPPORTED_RATES] = {};
|
|
@@ -1654,6 +1655,15 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
|
|
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
|
|
|
return false;
|
|
|
|
|
|
+ /* Use values requested by Compliance Test Request */
|
|
|
+ if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
|
|
|
+ link_rate_index = intel_dp_link_rate_index(intel_dp,
|
|
|
+ common_rates,
|
|
|
+ intel_dp->compliance.test_link_rate);
|
|
|
+ if (link_rate_index >= 0)
|
|
|
+ min_clock = max_clock = link_rate_index;
|
|
|
+ min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
|
|
|
+ }
|
|
|
DRM_DEBUG_KMS("DP link computation with max lane count %i "
|
|
|
"max bw %d pixel clock %iKHz\n",
|
|
|
max_lane_count, common_rates[max_clock],
|
|
@@ -3919,8 +3929,46 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
|
|
|
|
|
|
static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
|
|
|
{
|
|
|
- uint8_t test_result = DP_TEST_ACK;
|
|
|
- return test_result;
|
|
|
+ int status = 0;
|
|
|
+ int min_lane_count = 1;
|
|
|
+ int common_rates[DP_MAX_SUPPORTED_RATES] = {};
|
|
|
+ int link_rate_index, test_link_rate;
|
|
|
+ uint8_t test_lane_count, test_link_bw;
|
|
|
+ /* (DP CTS 1.2)
|
|
|
+ * 4.3.1.11
|
|
|
+ */
|
|
|
+ /* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */
|
|
|
+ status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT,
|
|
|
+ &test_lane_count);
|
|
|
+
|
|
|
+ if (status <= 0) {
|
|
|
+ DRM_DEBUG_KMS("Lane count read failed\n");
|
|
|
+ return DP_TEST_NAK;
|
|
|
+ }
|
|
|
+ test_lane_count &= DP_MAX_LANE_COUNT_MASK;
|
|
|
+ /* Validate the requested lane count */
|
|
|
+ if (test_lane_count < min_lane_count ||
|
|
|
+ test_lane_count > intel_dp->max_sink_lane_count)
|
|
|
+ return DP_TEST_NAK;
|
|
|
+
|
|
|
+ status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE,
|
|
|
+ &test_link_bw);
|
|
|
+ if (status <= 0) {
|
|
|
+ DRM_DEBUG_KMS("Link Rate read failed\n");
|
|
|
+ return DP_TEST_NAK;
|
|
|
+ }
|
|
|
+ /* Validate the requested link rate */
|
|
|
+ test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
|
|
|
+ link_rate_index = intel_dp_link_rate_index(intel_dp,
|
|
|
+ common_rates,
|
|
|
+ test_link_rate);
|
|
|
+ if (link_rate_index < 0)
|
|
|
+ return DP_TEST_NAK;
|
|
|
+
|
|
|
+ intel_dp->compliance.test_lane_count = test_lane_count;
|
|
|
+ intel_dp->compliance.test_link_rate = test_link_rate;
|
|
|
+
|
|
|
+ return DP_TEST_ACK;
|
|
|
}
|
|
|
|
|
|
static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
|
|
@@ -4131,9 +4179,8 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
|
|
|
if (!intel_dp->lane_count)
|
|
|
return;
|
|
|
|
|
|
- /* if link training is requested we should perform it always */
|
|
|
- if ((intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) ||
|
|
|
- (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
|
|
|
+ /* Retrain if Channel EQ or CR not ok */
|
|
|
+ if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) {
|
|
|
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
|
|
|
intel_encoder->base.name);
|
|
|
|
|
@@ -4158,6 +4205,7 @@ static bool
|
|
|
intel_dp_short_pulse(struct intel_dp *intel_dp)
|
|
|
{
|
|
|
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
|
|
+ struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
|
|
|
u8 sink_irq_vector = 0;
|
|
|
u8 old_sink_count = intel_dp->sink_count;
|
|
|
bool ret;
|
|
@@ -4191,7 +4239,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
|
|
|
sink_irq_vector);
|
|
|
|
|
|
if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
|
|
|
- DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");
|
|
|
+ intel_dp_handle_test_request(intel_dp);
|
|
|
if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
|
|
|
DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
|
|
|
}
|
|
@@ -4199,6 +4247,11 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
|
|
|
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
|
|
intel_dp_check_link_status(intel_dp);
|
|
|
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
|
|
+ if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
|
|
|
+ DRM_DEBUG_KMS("Link Training Compliance Test requested\n");
|
|
|
+ /* Send a Hotplug Uevent to userspace to start modeset */
|
|
|
+ drm_kms_helper_hotplug_event(intel_encoder->base.dev);
|
|
|
+ }
|
|
|
|
|
|
return true;
|
|
|
}
|