{ DP_LINK_BW_5_4, /* m2_int = 27, m2_fraction = 0 */
{ .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }
};
+/* Skylake supports following rates */
+static const uint32_t gen9_rates[] = { 162000, 216000, 270000, 324000,
+ 432000, 540000 };
+
+static const uint32_t default_rates[] = { 162000, 270000, 540000 };
/**
* is_edp - is the given port attached to an eDP panel (either CPU or PCH)
return i;
}
+static int
+intel_read_source_rates(struct intel_dp *intel_dp, uint32_t *source_rates)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ int i;
+ int max_default_rate;
+
+ if (INTEL_INFO(dev)->gen >= 9 && intel_dp->supported_rates[0]) {
+ for (i = 0; i < ARRAY_SIZE(gen9_rates); ++i)
+ source_rates[i] = gen9_rates[i];
+ } else {
+ /* Index of the max_link_bw supported + 1 */
+ max_default_rate = (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
+ for (i = 0; i < max_default_rate; ++i)
+ source_rates[i] = default_rates[i];
+ }
+ return i;
+}
+
static void
intel_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config, int link_bw)
}
}
+static int intel_supported_rates(const uint32_t *source_rates, int source_len,
+const uint32_t *sink_rates, int sink_len, uint32_t *supported_rates)
+{
+ int i = 0, j = 0, k = 0;
+
+ /* For panels with edp version less than 1.4 */
+ if (sink_len == 0) {
+ for (i = 0; i < source_len; ++i)
+ supported_rates[i] = source_rates[i];
+ return source_len;
+ }
+
+ /* For edp1.4 panels, find the common rates between source and sink */
+ while (i < source_len && j < sink_len) {
+ if (source_rates[i] == sink_rates[j]) {
+ supported_rates[k] = source_rates[i];
+ ++k;
+ ++i;
+ ++j;
+ } else if (source_rates[i] < sink_rates[j]) {
+ ++i;
+ } else {
+ ++j;
+ }
+ }
+ return k;
+}
+
+static int rate_to_index(uint32_t find, const uint32_t *rates)
+{
+ int i = 0;
+
+ for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
+ if (find == rates[i])
+ break;
+
+ return i;
+}
+
bool
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
int max_lane_count = intel_dp_max_lane_count(intel_dp);
/* Conveniently, the link BW constants become indices with a shift...*/
int min_clock = 0;
- int max_clock = intel_dp_max_link_bw(intel_dp) >> 3;
+ int max_clock;
int bpp, mode_rate;
- static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 };
int link_avail, link_clock;
+ uint32_t sink_rates[8];
+ uint32_t supported_rates[8] = {0};
+ uint32_t source_rates[8];
+ int source_len, sink_len, supported_len;
+
+ sink_len = intel_read_sink_rates(intel_dp, sink_rates);
+
+ source_len = intel_read_source_rates(intel_dp, source_rates);
+
+ supported_len = intel_supported_rates(source_rates, source_len,
+ sink_rates, sink_len, supported_rates);
+
+ /* No common link rates between source and sink */
+ WARN_ON(supported_len <= 0);
+
+ max_clock = supported_len - 1;
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
pipe_config->has_pch_encoder = true;
return false;
DRM_DEBUG_KMS("DP link computation with max lane count %i "
- "max bw %02x pixel clock %iKHz\n",
- max_lane_count, bws[max_clock],
+ "max bw %d pixel clock %iKHz\n",
+ max_lane_count, supported_rates[max_clock],
adjusted_mode->crtc_clock);
/* Walk through all bpp values. Luckily they're all nicely spaced with 2
bpp);
for (clock = min_clock; clock <= max_clock; clock++) {
- for (lane_count = min_lane_count; lane_count <= max_lane_count; lane_count <<= 1) {
- link_clock = drm_dp_bw_code_to_link_rate(bws[clock]);
+ for (lane_count = min_lane_count;
+ lane_count <= max_lane_count;
+ lane_count <<= 1) {
+
+ link_clock = supported_rates[clock];
link_avail = intel_dp_max_data_rate(link_clock,
lane_count);
if (intel_dp->color_range)
pipe_config->limited_color_range = true;
- intel_dp->link_bw = bws[clock];
intel_dp->lane_count = lane_count;
+
+ intel_dp->link_bw =
+ drm_dp_link_rate_to_bw_code(supported_rates[clock]);
+
+ if (INTEL_INFO(dev)->gen >= 9 && intel_dp->supported_rates[0]) {
+ intel_dp->rate_select =
+ rate_to_index(supported_rates[clock], sink_rates);
+ intel_dp->link_bw = 0;
+ }
+
pipe_config->pipe_bpp = bpp;
- pipe_config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+ pipe_config->port_clock = supported_rates[clock];
DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
intel_dp->link_bw, intel_dp->lane_count,
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
+ if (INTEL_INFO(dev)->gen >= 9 && intel_dp->supported_rates[0])
+ drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
+ &intel_dp->rate_select, 1);
link_config[0] = 0;
link_config[1] = DP_SET_ANSI_8B10B;