Skip to content

Commit fddbe6c

Browse files
alexdeuchersashalevin
authored andcommitted
drm/radeon: fix dp link rate selection (v2)
[ Upstream commit 092c96a ] 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 <[email protected]> Signed-off-by: Alex Deucher <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 7dac6e4 commit fddbe6c

File tree

3 files changed

+49
-77
lines changed

3 files changed

+49
-77
lines changed

drivers/gpu/drm/radeon/atombios_dp.c

Lines changed: 36 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -301,77 +301,31 @@ static int convert_bpc_to_bpp(int bpc)
301301
return bpc * 3;
302302
}
303303

304-
/* get the max pix clock supported by the link rate and lane num */
305-
static int dp_get_max_dp_pix_clock(int link_rate,
306-
int lane_num,
307-
int bpp)
308-
{
309-
return (link_rate * lane_num * 8) / bpp;
310-
}
311-
312304
/***** radeon specific DP functions *****/
313305

314-
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
315-
const u8 dpcd[DP_DPCD_SIZE])
316-
{
317-
int max_link_rate;
318-
319-
if (radeon_connector_is_dp12_capable(connector))
320-
max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000);
321-
else
322-
max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000);
323-
324-
return max_link_rate;
325-
}
326-
327-
/* First get the min lane# when low rate is used according to pixel clock
328-
* (prefer low rate), second check max lane# supported by DP panel,
329-
* if the max lane# < low rate lane# then use max lane# instead.
330-
*/
331-
static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
332-
const u8 dpcd[DP_DPCD_SIZE],
333-
int pix_clock)
334-
{
335-
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
336-
int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd);
337-
int max_lane_num = drm_dp_max_lane_count(dpcd);
338-
int lane_num;
339-
int max_dp_pix_clock;
340-
341-
for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
342-
max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
343-
if (pix_clock <= max_dp_pix_clock)
344-
break;
345-
}
346-
347-
return lane_num;
348-
}
349-
350-
static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
351-
const u8 dpcd[DP_DPCD_SIZE],
352-
int pix_clock)
306+
int radeon_dp_get_dp_link_config(struct drm_connector *connector,
307+
const u8 dpcd[DP_DPCD_SIZE],
308+
unsigned pix_clock,
309+
unsigned *dp_lanes, unsigned *dp_rate)
353310
{
354311
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
355-
int lane_num, max_pix_clock;
356-
357-
if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
358-
ENCODER_OBJECT_ID_NUTMEG)
359-
return 270000;
360-
361-
lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
362-
max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp);
363-
if (pix_clock <= max_pix_clock)
364-
return 162000;
365-
max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp);
366-
if (pix_clock <= max_pix_clock)
367-
return 270000;
368-
if (radeon_connector_is_dp12_capable(connector)) {
369-
max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp);
370-
if (pix_clock <= max_pix_clock)
371-
return 540000;
312+
static const unsigned link_rates[3] = { 162000, 270000, 540000 };
313+
unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
314+
unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
315+
unsigned lane_num, i, max_pix_clock;
316+
317+
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
318+
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
319+
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
320+
if (max_pix_clock >= pix_clock) {
321+
*dp_lanes = lane_num;
322+
*dp_rate = link_rates[i];
323+
return 0;
324+
}
325+
}
372326
}
373327

374-
return radeon_dp_get_max_link_rate(connector, dpcd);
328+
return -EINVAL;
375329
}
376330

377331
static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
@@ -490,17 +444,22 @@ void radeon_dp_set_link_config(struct drm_connector *connector,
490444
{
491445
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
492446
struct radeon_connector_atom_dig *dig_connector;
447+
int ret;
493448

494449
if (!radeon_connector->con_priv)
495450
return;
496451
dig_connector = radeon_connector->con_priv;
497452

498453
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
499454
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
500-
dig_connector->dp_clock =
501-
radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
502-
dig_connector->dp_lane_count =
503-
radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock);
455+
ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd,
456+
mode->clock,
457+
&dig_connector->dp_lane_count,
458+
&dig_connector->dp_clock);
459+
if (ret) {
460+
dig_connector->dp_clock = 0;
461+
dig_connector->dp_lane_count = 0;
462+
}
504463
}
505464
}
506465

@@ -509,7 +468,8 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector,
509468
{
510469
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
511470
struct radeon_connector_atom_dig *dig_connector;
512-
int dp_clock;
471+
unsigned dp_clock, dp_lanes;
472+
int ret;
513473

514474
if ((mode->clock > 340000) &&
515475
(!radeon_connector_is_dp12_capable(connector)))
@@ -519,8 +479,12 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector,
519479
return MODE_CLOCK_HIGH;
520480
dig_connector = radeon_connector->con_priv;
521481

522-
dp_clock =
523-
radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
482+
ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd,
483+
mode->clock,
484+
&dp_lanes,
485+
&dp_clock);
486+
if (ret)
487+
return MODE_CLOCK_HIGH;
524488

525489
if ((dp_clock == 540000) &&
526490
(!radeon_connector_is_dp12_capable(connector)))

drivers/gpu/drm/radeon/radeon_dp_mst.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,11 +520,17 @@ static bool radeon_mst_mode_fixup(struct drm_encoder *encoder,
520520
drm_mode_set_crtcinfo(adjusted_mode, 0);
521521
{
522522
struct radeon_connector_atom_dig *dig_connector;
523+
int ret;
523524

524525
dig_connector = mst_enc->connector->con_priv;
525-
dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd);
526-
dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base,
527-
dig_connector->dpcd);
526+
ret = radeon_dp_get_dp_link_config(&mst_enc->connector->base,
527+
dig_connector->dpcd, adjusted_mode->clock,
528+
&dig_connector->dp_lane_count,
529+
&dig_connector->dp_clock);
530+
if (ret) {
531+
dig_connector->dp_lane_count = 0;
532+
dig_connector->dp_clock = 0;
533+
}
528534
DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector,
529535
dig_connector->dp_lane_count, dig_connector->dp_clock);
530536
}

drivers/gpu/drm/radeon/radeon_mode.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,10 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
752752
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
753753
extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
754754
struct drm_connector *connector);
755-
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
756-
const u8 *dpcd);
755+
extern int radeon_dp_get_dp_link_config(struct drm_connector *connector,
756+
const u8 *dpcd,
757+
unsigned pix_clock,
758+
unsigned *dp_lanes, unsigned *dp_rate);
757759
extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
758760
u8 power_state);
759761
extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);

0 commit comments

Comments
 (0)