Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: Wrong colorimetry workaround

[Why]
For FreeSync HDR, native color space flag in AMD VSIF(BT.709) should be
used when intepreting content and color space flag in VSC or AVI
infoFrame should be ignored. However, it turned out some userspace
application still use color flag in VSC or AVI infoFrame which is
incorrect.

[How]
Transfer function is used when building the VSC and AVI infoFrame. Set
colorimetry to BT.709 when all the following match:

1. Pixel format is YCbCr;
2. In FreeSync 2 HDR, color is COLOR_SPACE_2020_YCBCR;
3. Transfer function is TRANSFER_FUNC_GAMMA_22;

Tested-by: Mark Broadworth <mark.broadworth@amd.com>
Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Ma Hanghong <hanghong.ma@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Ma Hanghong and committed by
Alex Deucher
b1a98cf8 1e8fd864

+17 -3
+4 -1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 5697 5697 bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false; 5698 5698 int mode_refresh; 5699 5699 int preferred_refresh = 0; 5700 + enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN; 5700 5701 #if defined(CONFIG_DRM_AMD_DC_DCN) 5701 5702 struct dsc_dec_dpcd_caps dsc_caps; 5702 5703 #endif ··· 5821 5820 if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) 5822 5821 stream->use_vsc_sdp_for_colorimetry = true; 5823 5822 } 5824 - mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space); 5823 + if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) 5824 + tf = TRANSFER_FUNC_GAMMA_22; 5825 + mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf); 5825 5826 aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; 5826 5827 5827 5828 }
+6
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 3015 3015 hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 3016 3016 } 3017 3017 3018 + if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR && 3019 + stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { 3020 + hdmi_info.bits.EC0_EC2 = 0; 3021 + hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 3022 + } 3023 + 3018 3024 /* TODO: un-hardcode aspect ratio */ 3019 3025 aspect = stream->timing.aspect_ratio; 3020 3026
+2 -1
drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
··· 35 35 36 36 void mod_build_vsc_infopacket(const struct dc_stream_state *stream, 37 37 struct dc_info_packet *info_packet, 38 - enum dc_color_space cs); 38 + enum dc_color_space cs, 39 + enum color_transfer_func tf); 39 40 40 41 void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, 41 42 struct dc_info_packet *info_packet);
+5 -1
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
··· 132 132 133 133 void mod_build_vsc_infopacket(const struct dc_stream_state *stream, 134 134 struct dc_info_packet *info_packet, 135 - enum dc_color_space cs) 135 + enum dc_color_space cs, 136 + enum color_transfer_func tf) 136 137 { 137 138 unsigned int vsc_packet_revision = vsc_packet_undefined; 138 139 unsigned int i; ··· 383 382 colorimetryFormat = ColorimetryYCC_DP_AdobeYCC; 384 383 else if (cs == COLOR_SPACE_2020_YCBCR) 385 384 colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr; 385 + 386 + if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22) 387 + colorimetryFormat = ColorimetryYCC_DP_ITU709; 386 388 break; 387 389 388 390 default: