May fix display issues with non-HDMI displays.
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 48 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index fb187c7..c96d1d5 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -864,14 +864,16 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; - switch (bpc) { - case 8: - default: - args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; - break; - case 10: - args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; - break; + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + switch (bpc) { + case 8: + default: + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; + break; + case 10: + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; + break; + } } args.v5.ucTransmitterID = encoder_id; args.v5.ucEncoderMode = encoder_mode; @@ -886,20 +888,22 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; - switch (bpc) { - case 8: - default: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; - break; - case 10: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; - break; - case 12: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; - break; - case 16: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; - break; + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + switch (bpc) { + case 8: + default: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; + break; + case 10: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; + break; + case 12: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; + break; + case 16: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; + break; + } } args.v6.ucTransmitterID = encoder_id; args.v6.ucEncoderMode = encoder_mode;
I'm not really sure how these should be calculated for deep color. The hw generated values seem to work.
Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 05b0c95..8579721 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -293,10 +293,12 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame; uint32_t offset; ssize_t err; + int bpc = 8;
if (!dig || !dig->afmt) return; @@ -306,6 +308,12 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode return; offset = dig->afmt->offset;
+ /* hdmi deep color mode general control packets setup, if bpc > 8 */ + if (encoder->crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + bpc = radeon_crtc->bpc; + } + /* disable audio prior to setting up hw */ if (ASIC_IS_DCE6(rdev)) { dig->afmt->pin = dce6_audio_get_pin(rdev); @@ -348,9 +356,13 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
/* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */
- WREG32(HDMI_ACR_PACKET_CONTROL + offset, - HDMI_ACR_SOURCE | /* select SW CTS value */ - HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + if (bpc > 8) + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + else + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_SOURCE | /* select SW CTS value */ + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
evergreen_hdmi_update_ACR(encoder, mode->clock);
Need to adjust the pll up for deep color modes. Additionally, the atom bpc defines were wrong in certain cases.
v2: set the adjusted clock to the pll clock for hdmi deep color. This fixes display and audio issues with deep color as reported by Andy Furniss adf.lists@gmail.com
v3: set crtc_clock as well
v4: setcrtcinfo on the adjusted mode
v5: just use the adjusted clock for setting the pll
Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/atombios_crtc.c | 43 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c96d1d5..998435d 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -559,6 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, u32 adjusted_clock = mode->clock; int encoder_mode = atombios_get_encoder_mode(encoder); u32 dp_clock = mode->clock; + u32 clock = mode->clock; int bpc = radeon_crtc->bpc; bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
@@ -634,6 +635,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; }
+ /* adjust pll for deep color modes */ + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + switch (bpc) { + case 8: + default: + break; + case 10: + clock = (clock * 5) / 4; + break; + case 12: + clock = (clock * 3) / 2; + break; + case 16: + clock = clock * 2; + break; + } + } + /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock * accordingly based on the encoder/transmitter to work around * special hw requirements. @@ -655,7 +674,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, switch (crev) { case 1: case 2: - args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v1.usPixelClock = cpu_to_le16(clock / 10); args.v1.ucTransmitterID = radeon_encoder->encoder_id; args.v1.ucEncodeMode = encoder_mode; if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) @@ -667,7 +686,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; break; case 3: - args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10); args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; args.v3.sInput.ucEncodeMode = encoder_mode; args.v3.sInput.ucDispPllConfig = 0; @@ -681,10 +700,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - if (encoder_mode == ATOM_ENCODER_MODE_HDMI) - /* deep color support */ - args.v3.sInput.usPixelClock = - cpu_to_le16((mode->clock * bpc / 8) / 10); if (dig->coherent_mode) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; @@ -871,6 +886,11 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; break; case 10: + /* yes this is correct, the atom define is wrong */ + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP; + break; + case 12: + /* yes this is correct, the atom define is wrong */ args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; break; } @@ -895,10 +915,10 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; break; case 10: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6; break; case 12: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6; break; case 16: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; @@ -1025,10 +1045,15 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode struct radeon_encoder *radeon_encoder = to_radeon_encoder(radeon_crtc->encoder); u32 pll_clock = mode->clock; + u32 clock = mode->clock; u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; struct radeon_pll *pll; int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);
+ /* pass the actual clock to atombios_crtc_program_pll for DCE5+ */ + if (ASIC_IS_DCE5(rdev)) + clock = radeon_crtc->adjusted_clock; + switch (radeon_crtc->pll_id) { case ATOM_PPLL1: pll = &rdev->clock.p1pll; @@ -1063,7 +1088,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_crtc->crtc_id, &radeon_crtc->ss);
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, - encoder_mode, radeon_encoder->encoder_id, mode->clock, + encoder_mode, radeon_encoder->encoder_id, clock, ref_div, fb_div, frac_fb_div, post_div, radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss);
Program HDMI_CONTROL to send general control packets for hdmi deep color mode signalling at every video frame if bpc > 8.
This is only supported on evergreen / DCE-4 and later.
v2: rebase
Signed-off-by: Mario Kleiner mario.kleiner.de@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/evergreend.h | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 8579721..b760ef5 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -298,6 +298,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode struct hdmi_avi_infoframe frame; uint32_t offset; ssize_t err; + uint32_t val; int bpc = 8;
if (!dig || !dig->afmt) @@ -330,6 +331,35 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000);
+ val = RREG32(HDMI_CONTROL + offset); + val &= ~HDMI_DEEP_COLOR_ENABLE; + val &= ~HDMI_DEEP_COLOR_DEPTH_MASK; + + switch (bpc) { + case 0: + case 6: + case 8: + case 16: + default: + DRM_DEBUG("%s: Disabling hdmi deep color for %d bpc.\n", + drm_get_connector_name(connector), bpc); + break; + case 10: + val |= HDMI_DEEP_COLOR_ENABLE; + val |= HDMI_DEEP_COLOR_DEPTH(HDMI_30BIT_DEEP_COLOR); + DRM_DEBUG("%s: Enabling hdmi deep color 30 for 10 bpc.\n", + drm_get_connector_name(connector)); + break; + case 12: + val |= HDMI_DEEP_COLOR_ENABLE; + val |= HDMI_DEEP_COLOR_DEPTH(HDMI_36BIT_DEEP_COLOR); + DRM_DEBUG("%s: Enabling hdmi deep color 36 for 12 bpc.\n", + drm_get_connector_name(connector)); + break; + } + + WREG32(HDMI_CONTROL + offset, val); + WREG32(HDMI_VBI_PACKET_CONTROL + offset, HDMI_NULL_SEND | /* send null packets when required */ HDMI_GC_SEND | /* send general control packets */ diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index f9c7963..b066d67 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -517,10 +517,11 @@ # define HDMI_ERROR_ACK (1 << 8) # define HDMI_ERROR_MASK (1 << 9) # define HDMI_DEEP_COLOR_ENABLE (1 << 24) -# define HDMI_DEEP_COLOR_DEPTH (((x) & 3) << 28) +# define HDMI_DEEP_COLOR_DEPTH(x) (((x) & 3) << 28) # define HDMI_24BIT_DEEP_COLOR 0 # define HDMI_30BIT_DEEP_COLOR 1 # define HDMI_36BIT_DEEP_COLOR 2 +# define HDMI_DEEP_COLOR_DEPTH_MASK (3 << 28) #define HDMI_STATUS 0x7034 # define HDMI_ACTIVE_AVMUTE (1 << 0) # define HDMI_AUDIO_PACKET_ERROR (1 << 16)
From: Mario Kleiner mario.kleiner.de@gmail.com
DCE-4/5/6 can't support more than 12 bpc deep color over hdmi, so clamp to 12 bpc when a hdmi deep color capable display is connected. This even makes sense on DCE-8+, which could do up to 16 bpc, as driving with more than 12 bpc would only waste video bandwidth as long as we don't support framebuffers with more than 12 bpc depth.
On pre-DCE4 we clamp hdmi bit depth to 8 bpc, as those asics don't support hdmi deep color.
Signed-off-by: Mario Kleiner mario.kleiner.de@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/radeon_connectors.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index bf73a04..0dc61dd 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -145,6 +145,31 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) } break; } + + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + /* hdmi deep color only implemented on DCE4+ */ + if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) { + DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n", + drm_get_connector_name(connector), bpc); + bpc = 8; + } + + /* + * Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make + * much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at + * 12 bpc is always supported on hdmi deep color sinks, as this is + * required by the HDMI-1.3 spec. Clamp to a safe 12 bpc maximum. + */ + if (bpc > 12) { + DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 12 bpc.\n", + drm_get_connector_name(connector), bpc); + bpc = 12; + } + } + + DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n", + drm_get_connector_name(connector), connector->display_info.bpc, bpc); + return bpc; }
From: Mario Kleiner mario.kleiner.de@gmail.com
Check the HDMI cea block for deep color mode bits. If available, assign the highest supported bpc for a hdmi display, corresponding to the given deep color modes.
Signed-off-by: Mario Kleiner mario.kleiner.de@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/drm_edid.c | 110 ++++++++++++++++++++++++++++++++++++++++++++- include/drm/drm_edid.h | 5 +++ 2 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index d74239f..3989c18 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3423,16 +3423,116 @@ bool drm_rgb_quant_range_selectable(struct edid *edid) EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
/** + * drm_assign_hdmi_deep_color_info - detect whether monitor supports + * hdmi deep color modes and update drm_display_info if so. + * + * @edid: monitor EDID information + * @info: Updated with maximum supported deep color bpc and color format + * if deep color supported. + * + * Parse the CEA extension according to CEA-861-B. + * Return true if HDMI deep color supported, false if not or unknown. + */ +static bool drm_assign_hdmi_deep_color_info(struct edid *edid, + struct drm_display_info *info, + struct drm_connector *connector) +{ + u8 *edid_ext, *hdmi; + int i; + int start_offset, end_offset; + unsigned int dc_bpc = 0; + + edid_ext = drm_find_cea_extension(edid); + if (!edid_ext) + return false; + + if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) + return false; + + /* + * Because HDMI identifier is in Vendor Specific Block, + * search it from all data blocks of CEA extension. + */ + for_each_cea_db(edid_ext, i, start_offset, end_offset) { + if (cea_db_is_hdmi_vsdb(&edid_ext[i])) { + /* HDMI supports at least 8 bpc */ + info->bpc = 8; + + hdmi = &edid_ext[i]; + if (cea_db_payload_len(hdmi) < 6) + return false; + + if (hdmi[6] & DRM_EDID_HDMI_DC_30) { + dc_bpc = 10; + DRM_DEBUG("%s: HDMI sink does deep color 30.\n", + drm_get_connector_name(connector)); + } + + if (hdmi[6] & DRM_EDID_HDMI_DC_36) { + dc_bpc = 12; + DRM_DEBUG("%s: HDMI sink does deep color 36.\n", + drm_get_connector_name(connector)); + } + + if (hdmi[6] & DRM_EDID_HDMI_DC_48) { + dc_bpc = 16; + DRM_DEBUG("%s: HDMI sink does deep color 48.\n", + drm_get_connector_name(connector)); + } + + if (dc_bpc > 0) { + DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n", + drm_get_connector_name(connector), dc_bpc); + info->bpc = dc_bpc; + + /* + * Deep color support mandates RGB444 support for all video + * modes and forbids YCRCB422 support for all video modes per + * HDMI 1.3 spec. + */ + info->color_formats = DRM_COLOR_FORMAT_RGB444; + + /* YCRCB444 is optional according to spec. */ + if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) { + info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n", + drm_get_connector_name(connector)); + } + + /* + * Spec says that if any deep color mode is supported at all, + * then deep color 36 bit must be supported. + */ + if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) { + DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n", + drm_get_connector_name(connector)); + } + + return true; + } + else { + DRM_DEBUG("%s: No deep color support on this HDMI sink.\n", + drm_get_connector_name(connector)); + } + } + } + + return false; +} + +/** * drm_add_display_info - pull display info out if present * @edid: EDID data * @info: display info (attached to connector) + * @connector: connector whose edid is used to build display info * * Grab any available display info and stuff it into the drm_display_info * structure that's part of the connector. Useful for tracking bpp and * color spaces. */ static void drm_add_display_info(struct edid *edid, - struct drm_display_info *info) + struct drm_display_info *info, + struct drm_connector *connector) { u8 *edid_ext;
@@ -3462,6 +3562,9 @@ static void drm_add_display_info(struct edid *edid, info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; }
+ /* HDMI deep color modes supported? Assign to info, if so */ + drm_assign_hdmi_deep_color_info(edid, info, connector); + /* Only defined for 1.4 with digital displays */ if (edid->revision < 4) return; @@ -3491,6 +3594,9 @@ static void drm_add_display_info(struct edid *edid, break; }
+ DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n", + drm_get_connector_name(connector), info->bpc); + info->color_formats |= DRM_COLOR_FORMAT_RGB444; if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; @@ -3549,7 +3655,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) edid_fixup_preferred(connector, quirks);
- drm_add_display_info(edid, &connector->display_info); + drm_add_display_info(edid, &connector->display_info, connector);
if (quirks & EDID_QUIRK_FORCE_8BPC) connector->display_info.bpc = 8; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index a1441c5..b96031d 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -202,6 +202,11 @@ struct detailed_timing { #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6) #define DRM_EDID_FEATURE_PM_STANDBY (1 << 7)
+#define DRM_EDID_HDMI_DC_48 (1 << 6) +#define DRM_EDID_HDMI_DC_36 (1 << 5) +#define DRM_EDID_HDMI_DC_30 (1 << 4) +#define DRM_EDID_HDMI_DC_Y444 (1 << 3) + struct edid { u8 header[8]; /* Vendor & product info */
From: Mario Kleiner mario.kleiner.de@gmail.com
The Sony PVM-2541A OLED high precision color display supports both 10 bpc and 12 bpc hdmi deep color input, but its edid does not signal any deep color support.
Add a quirk to force it being treated as a 12 bpc panel.
Signed-off-by: Mario Kleiner mario.kleiner.de@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/drm_edid.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3989c18..643f830 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -70,6 +70,8 @@ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) /* Force 8bpc */ #define EDID_QUIRK_FORCE_8BPC (1 << 8) +/* Force 12bpc */ +#define EDID_QUIRK_FORCE_12BPC (1 << 9)
struct detailed_mode_closure { struct drm_connector *connector; @@ -125,6 +127,9 @@ static struct edid_quirk { { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
+ /* Sony PVM-2541A does up to 12 bpc, but only reports max 8 bpc */ + { "SNY", 0x2541, EDID_QUIRK_FORCE_12BPC }, + /* ViewSonic VA2026w */ { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },
@@ -3660,6 +3665,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) if (quirks & EDID_QUIRK_FORCE_8BPC) connector->display_info.bpc = 8;
+ if (quirks & EDID_QUIRK_FORCE_12BPC) + connector->display_info.bpc = 12; + return num_modes; } EXPORT_SYMBOL(drm_add_edid_modes);
dri-devel@lists.freedesktop.org