aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0033-drm-amdgpu-fix-dp-link-rate-selection-v2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0033-drm-amdgpu-fix-dp-link-rate-selection-v2.patch')
-rw-r--r--common/recipes-kernel/linux/files/0033-drm-amdgpu-fix-dp-link-rate-selection-v2.patch166
1 files changed, 166 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0033-drm-amdgpu-fix-dp-link-rate-selection-v2.patch b/common/recipes-kernel/linux/files/0033-drm-amdgpu-fix-dp-link-rate-selection-v2.patch
new file mode 100644
index 00000000..585ce1a5
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0033-drm-amdgpu-fix-dp-link-rate-selection-v2.patch
@@ -0,0 +1,166 @@
+From 9057e8ec3a72b7ffcd95ed553843265f4ef966d3 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 17 Dec 2015 09:57:49 -0500
+Subject: [PATCH 0033/1110] drm/amdgpu: fix dp link rate selection (v2)
+
+Need to properly handle the max link rate in the dpcd.
+This prevents some cases where 5.4 Ghz is selected when
+it shouldn't be.
+
+v2: simplify logic, add array bounds check
+
+Reviewed-by: Tom St Denis <tom.stdenis@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/atombios_dp.c | 96 ++++++++++++--------------------
+ 1 file changed, 36 insertions(+), 60 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
+index 92b6aca..21aacc1 100644
+--- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
++++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
+@@ -243,7 +243,7 @@ static void amdgpu_atombios_dp_get_adjust_train(const u8 link_status[DP_LINK_STA
+
+ /* convert bits per color to bits per pixel */
+ /* get bpc from the EDID */
+-static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
++static unsigned amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
+ {
+ if (bpc == 0)
+ return 24;
+@@ -251,64 +251,32 @@ static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
+ return bpc * 3;
+ }
+
+-/* get the max pix clock supported by the link rate and lane num */
+-static int amdgpu_atombios_dp_get_max_dp_pix_clock(int link_rate,
+- int lane_num,
+- int bpp)
+-{
+- return (link_rate * lane_num * 8) / bpp;
+-}
+-
+ /***** amdgpu specific DP functions *****/
+
+-/* First get the min lane# when low rate is used according to pixel clock
+- * (prefer low rate), second check max lane# supported by DP panel,
+- * if the max lane# < low rate lane# then use max lane# instead.
+- */
+-static int amdgpu_atombios_dp_get_dp_lane_number(struct drm_connector *connector,
++static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector,
+ const u8 dpcd[DP_DPCD_SIZE],
+- int pix_clock)
+-{
+- int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
+- int max_link_rate = drm_dp_max_link_rate(dpcd);
+- int max_lane_num = drm_dp_max_lane_count(dpcd);
+- int lane_num;
+- int max_dp_pix_clock;
+-
+- for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
+- max_dp_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
+- if (pix_clock <= max_dp_pix_clock)
+- break;
+- }
+-
+- return lane_num;
+-}
+-
+-static int amdgpu_atombios_dp_get_dp_link_clock(struct drm_connector *connector,
+- const u8 dpcd[DP_DPCD_SIZE],
+- int pix_clock)
++ unsigned pix_clock,
++ unsigned *dp_lanes, unsigned *dp_rate)
+ {
+- int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
+- int lane_num, max_pix_clock;
+-
+- if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+- ENCODER_OBJECT_ID_NUTMEG)
+- return 270000;
+-
+- lane_num = amdgpu_atombios_dp_get_dp_lane_number(connector, dpcd, pix_clock);
+- max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(162000, lane_num, bpp);
+- if (pix_clock <= max_pix_clock)
+- return 162000;
+- max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(270000, lane_num, bpp);
+- if (pix_clock <= max_pix_clock)
+- return 270000;
+- if (amdgpu_connector_is_dp12_capable(connector)) {
+- max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(540000, lane_num, bpp);
+- if (pix_clock <= max_pix_clock)
+- return 540000;
++ unsigned bpp =
++ amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
++ static const unsigned link_rates[3] = { 162000, 270000, 540000 };
++ unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
++ unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
++ unsigned lane_num, i, max_pix_clock;
++
++ for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
++ for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
++ max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
++ if (max_pix_clock >= pix_clock) {
++ *dp_lanes = lane_num;
++ *dp_rate = link_rates[i];
++ return 0;
++ }
++ }
+ }
+
+- return drm_dp_max_link_rate(dpcd);
++ return -EINVAL;
+ }
+
+ static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev,
+@@ -422,6 +390,7 @@ void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector,
+ {
+ struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+ struct amdgpu_connector_atom_dig *dig_connector;
++ int ret;
+
+ if (!amdgpu_connector->con_priv)
+ return;
+@@ -429,10 +398,14 @@ void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector,
+
+ if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+ (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
+- dig_connector->dp_clock =
+- amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
+- dig_connector->dp_lane_count =
+- amdgpu_atombios_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock);
++ ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
++ mode->clock,
++ &dig_connector->dp_lane_count,
++ &dig_connector->dp_clock);
++ if (ret) {
++ dig_connector->dp_clock = 0;
++ dig_connector->dp_lane_count = 0;
++ }
+ }
+ }
+
+@@ -441,14 +414,17 @@ int amdgpu_atombios_dp_mode_valid_helper(struct drm_connector *connector,
+ {
+ struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+ struct amdgpu_connector_atom_dig *dig_connector;
+- int dp_clock;
++ unsigned dp_lanes, dp_clock;
++ int ret;
+
+ if (!amdgpu_connector->con_priv)
+ return MODE_CLOCK_HIGH;
+ dig_connector = amdgpu_connector->con_priv;
+
+- dp_clock =
+- amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
++ ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
++ mode->clock, &dp_lanes, &dp_clock);
++ if (ret)
++ return MODE_CLOCK_HIGH;
+
+ if ((dp_clock == 540000) &&
+ (!amdgpu_connector_is_dp12_capable(connector)))
+--
+2.7.4
+