aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2015-12-17 09:57:49 -0500
committerAlex Deucher <alexander.deucher@amd.com>2015-12-21 16:38:51 -0500
commit41869c1c7fe583dec932eb3d87de2e010b30a737 (patch)
tree2fe4e2f7f046ab7db4d3b2b756f344185391d1ce /drivers/gpu/drm/amd/amdgpu/atombios_dp.c
parentb24c683af14bdc52b81899937ef2e52c15fe4768 (diff)
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>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/atombios_dp.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_dp.c96
1 files 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 92b6acadfc52..21aacc1f45c1 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
243 243
244/* convert bits per color to bits per pixel */ 244/* convert bits per color to bits per pixel */
245/* get bpc from the EDID */ 245/* get bpc from the EDID */
246static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc) 246static unsigned amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
247{ 247{
248 if (bpc == 0) 248 if (bpc == 0)
249 return 24; 249 return 24;
@@ -251,64 +251,32 @@ static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
251 return bpc * 3; 251 return bpc * 3;
252} 252}
253 253
254/* get the max pix clock supported by the link rate and lane num */
255static int amdgpu_atombios_dp_get_max_dp_pix_clock(int link_rate,
256 int lane_num,
257 int bpp)
258{
259 return (link_rate * lane_num * 8) / bpp;
260}
261
262/***** amdgpu specific DP functions *****/ 254/***** amdgpu specific DP functions *****/
263 255
264/* First get the min lane# when low rate is used according to pixel clock 256static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector,
265 * (prefer low rate), second check max lane# supported by DP panel,
266 * if the max lane# < low rate lane# then use max lane# instead.
267 */
268static int amdgpu_atombios_dp_get_dp_lane_number(struct drm_connector *connector,
269 const u8 dpcd[DP_DPCD_SIZE], 257 const u8 dpcd[DP_DPCD_SIZE],
270 int pix_clock) 258 unsigned pix_clock,
271{ 259 unsigned *dp_lanes, unsigned *dp_rate)
272 int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
273 int max_link_rate = drm_dp_max_link_rate(dpcd);
274 int max_lane_num = drm_dp_max_lane_count(dpcd);
275 int lane_num;
276 int max_dp_pix_clock;
277
278 for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
279 max_dp_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
280 if (pix_clock <= max_dp_pix_clock)
281 break;
282 }
283
284 return lane_num;
285}
286
287static int amdgpu_atombios_dp_get_dp_link_clock(struct drm_connector *connector,
288 const u8 dpcd[DP_DPCD_SIZE],
289 int pix_clock)
290{ 260{
291 int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector)); 261 unsigned bpp =
292 int lane_num, max_pix_clock; 262 amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
293 263 static const unsigned link_rates[3] = { 162000, 270000, 540000 };
294 if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) == 264 unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
295 ENCODER_OBJECT_ID_NUTMEG) 265 unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
296 return 270000; 266 unsigned lane_num, i, max_pix_clock;
297 267
298 lane_num = amdgpu_atombios_dp_get_dp_lane_number(connector, dpcd, pix_clock); 268 for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
299 max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(162000, lane_num, bpp); 269 for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
300 if (pix_clock <= max_pix_clock) 270 max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
301 return 162000; 271 if (max_pix_clock >= pix_clock) {
302 max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(270000, lane_num, bpp); 272 *dp_lanes = lane_num;
303 if (pix_clock <= max_pix_clock) 273 *dp_rate = link_rates[i];
304 return 270000; 274 return 0;
305 if (amdgpu_connector_is_dp12_capable(connector)) { 275 }
306 max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(540000, lane_num, bpp); 276 }
307 if (pix_clock <= max_pix_clock)
308 return 540000;
309 } 277 }
310 278
311 return drm_dp_max_link_rate(dpcd); 279 return -EINVAL;
312} 280}
313 281
314static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev, 282static 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,
422{ 390{
423 struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); 391 struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
424 struct amdgpu_connector_atom_dig *dig_connector; 392 struct amdgpu_connector_atom_dig *dig_connector;
393 int ret;
425 394
426 if (!amdgpu_connector->con_priv) 395 if (!amdgpu_connector->con_priv)
427 return; 396 return;
@@ -429,10 +398,14 @@ void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector,
429 398
430 if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 399 if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
431 (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { 400 (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
432 dig_connector->dp_clock = 401 ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
433 amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); 402 mode->clock,
434 dig_connector->dp_lane_count = 403 &dig_connector->dp_lane_count,
435 amdgpu_atombios_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); 404 &dig_connector->dp_clock);
405 if (ret) {
406 dig_connector->dp_clock = 0;
407 dig_connector->dp_lane_count = 0;
408 }
436 } 409 }
437} 410}
438 411
@@ -441,14 +414,17 @@ int amdgpu_atombios_dp_mode_valid_helper(struct drm_connector *connector,
441{ 414{
442 struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); 415 struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
443 struct amdgpu_connector_atom_dig *dig_connector; 416 struct amdgpu_connector_atom_dig *dig_connector;
444 int dp_clock; 417 unsigned dp_lanes, dp_clock;
418 int ret;
445 419
446 if (!amdgpu_connector->con_priv) 420 if (!amdgpu_connector->con_priv)
447 return MODE_CLOCK_HIGH; 421 return MODE_CLOCK_HIGH;
448 dig_connector = amdgpu_connector->con_priv; 422 dig_connector = amdgpu_connector->con_priv;
449 423
450 dp_clock = 424 ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
451 amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); 425 mode->clock, &dp_lanes, &dp_clock);
426 if (ret)
427 return MODE_CLOCK_HIGH;
452 428
453 if ((dp_clock == 540000) && 429 if ((dp_clock == 540000) &&
454 (!amdgpu_connector_is_dp12_capable(connector))) 430 (!amdgpu_connector_is_dp12_capable(connector)))