Skip to content

Commit

Permalink
drm/radeon: hdmi deep color modes must obey clock limit of sink.
Browse files Browse the repository at this point in the history
Make sure that a hdmi deep color mode can't exceed the max tmds
clock limit of a hdmi sink if such a limit is defined by edid.

If requested deep color bpc would exceed the limit given the mode
to be set, try to degrade gracefully to lower supported deep color
bpc or to standard 8 bpc if needed.

Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Mario Kleiner authored and Alex Deucher committed Jun 10, 2014
1 parent 5d02626 commit ea29286
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/radeon/atombios_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,9 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
struct radeon_connector_atom_dig *dig_connector =
radeon_connector->con_priv;
int dp_clock;

/* Assign mode clock for hdmi deep color max clock limit check */
radeon_connector->pixelclock_for_modeset = mode->clock;
radeon_crtc->bpc = radeon_get_monitor_bpc(connector);

switch (encoder_mode) {
Expand Down
31 changes: 31 additions & 0 deletions drivers/gpu/drm/radeon/radeon_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector;
int bpc = 8;
int mode_clock, max_tmds_clock;

switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
Expand Down Expand Up @@ -166,6 +167,36 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
connector->name, bpc);
bpc = 12;
}

/* Any defined maximum tmds clock limit we must not exceed? */
if (connector->max_tmds_clock > 0) {
/* mode_clock is clock in kHz for mode to be modeset on this connector */
mode_clock = radeon_connector->pixelclock_for_modeset;

/* Maximum allowable input clock in kHz */
max_tmds_clock = connector->max_tmds_clock * 1000;

DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
connector->name, mode_clock, max_tmds_clock);

/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
(mode_clock * 5/4 <= max_tmds_clock))
bpc = 10;
else
bpc = 8;

DRM_DEBUG("%s: HDMI deep color 12 bpc exceeds max tmds clock. Using %d bpc.\n",
connector->name, bpc);
}

if ((bpc == 10) && (mode_clock * 5/4 > max_tmds_clock)) {
bpc = 8;
DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
connector->name, bpc);
}
}
}

DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ struct radeon_connector {
struct radeon_i2c_chan *router_bus;
enum radeon_connector_audio audio;
enum radeon_connector_dither dither;
int pixelclock_for_modeset;
};

struct radeon_framebuffer {
Expand Down

0 comments on commit ea29286

Please sign in to comment.