[PATCH v2] drm/amd/display: Add DP-HDMI FRL PCON Support in DC
Harry Wentland
harry.wentland at amd.com
Fri Nov 26 15:15:13 UTC 2021
On 2021-11-26 09:32, Fangzhi Zuo wrote:
> Change since v1: add brief description
> 1. Add hdmi frl pcon support to existing asic family.
> 2. Determine pcon frl capability based on pcon dpcd.
> 3. pcon frl is taken into consideration into mode validation.
>
> Signed-off-by: Fangzhi Zuo <Jerry.Zuo at amd.com>
Acked-by: Harry Wentland <harry.wentland at amd.com>
Harry
> ---
> drivers/gpu/drm/amd/display/dc/core/dc_link.c | 15 ++++
> .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 71 +++++++++++++++++++
> drivers/gpu/drm/amd/display/dc/dc.h | 6 ++
> drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 31 ++++++++
> drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 3 +
> drivers/gpu/drm/amd/display/dc/dc_link.h | 1 +
> drivers/gpu/drm/amd/display/dc/dc_types.h | 1 +
> .../drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +
> .../drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +
> .../drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +
> .../drm/amd/display/dc/dcn31/dcn31_resource.c | 1 +
> 11 files changed, 135 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
> index 3d08f8eba402..dad7a4fdc427 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
> @@ -2750,8 +2750,23 @@ static bool dp_active_dongle_validate_timing(
> return false;
> }
>
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter
> + struct dc_crtc_timing outputTiming = *timing;
> +
> + if (timing->flags.DSC && !timing->dsc_cfg.is_frl)
> + /* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */
> + outputTiming.flags.DSC = 0;
> + if (dc_bandwidth_in_kbps_from_timing(&outputTiming) > dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps)
> + return false;
> + } else { // DP to HDMI TMDS converter
> + if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
> + return false;
> + }
> +#else
> if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
> return false;
> +#endif
>
> #if defined(CONFIG_DRM_AMD_DC_DCN)
> }
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> index 84f3545c3032..da1532356c07 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> @@ -4313,6 +4313,56 @@ static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
> return -1;
> }
>
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> +uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
> +{
> + switch (bw) {
> + case 0b001:
> + return 9000000;
> + case 0b010:
> + return 18000000;
> + case 0b011:
> + return 24000000;
> + case 0b100:
> + return 32000000;
> + case 0b101:
> + return 40000000;
> + case 0b110:
> + return 48000000;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
> + */
> +static uint32_t intersect_frl_link_bw_support(
> + const uint32_t max_supported_frl_bw_in_kbps,
> + const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
> +{
> + uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
> +
> + // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
> + if (hdmi_encoded_link_bw.bits.FRL_MODE) {
> + if (hdmi_encoded_link_bw.bits.BW_48Gbps)
> + supported_bw_in_kbps = 48000000;
> + else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
> + supported_bw_in_kbps = 40000000;
> + else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
> + supported_bw_in_kbps = 32000000;
> + else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
> + supported_bw_in_kbps = 24000000;
> + else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
> + supported_bw_in_kbps = 18000000;
> + else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
> + supported_bw_in_kbps = 9000000;
> + }
> +
> + return supported_bw_in_kbps;
> +}
> +#endif
> +
> static void read_dp_device_vendor_id(struct dc_link *link)
> {
> struct dp_device_vendor_id dp_id;
> @@ -4424,6 +4474,27 @@ static void get_active_converter_info(
> translate_dpcd_max_bpc(
> hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
>
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + if (link->dc->caps.hdmi_frl_pcon_support) {
> + link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
> + dc_link_bw_kbps_from_raw_frl_link_rate_data(
> + hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
> +
> + union hdmi_encoded_link_bw hdmi_encoded_link_bw;
> +
> + // Intersect reported max link bw support with the supported link rate post FRL link training
> + if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS,
> + &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
> + link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
> + link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
> + hdmi_encoded_link_bw);
> + }
> +
> + if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
> + link->dpcd_caps.dongle_caps.extendedCapValid = true;
> + }
> +#endif
> +
> if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
> link->dpcd_caps.dongle_caps.extendedCapValid = true;
> }
> diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
> index c14e7db3f69d..2d001de42117 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc.h
> @@ -187,6 +187,7 @@ struct dc_caps {
> struct dc_color_caps color;
> #if defined(CONFIG_DRM_AMD_DC_DCN)
> bool dp_hpo;
> + bool hdmi_frl_pcon_support;
> #endif
> bool edp_dsc_support;
> bool vbios_lttpr_aware;
> @@ -1294,6 +1295,11 @@ struct dc_sink_dsc_caps {
> // 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
> // 'false' if they are sink's DSC caps
> bool is_virtual_dpcd_dsc;
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + // 'true' if MST topology supports DSC passthrough for sink
> + // 'false' if MST topology does not support DSC passthrough
> + bool is_dsc_passthrough_supported;
> +#endif
> struct dsc_dec_dpcd_caps dsc_dec_caps;
> };
>
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
> index e68e9a86a4d9..99d26fb31566 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
> @@ -378,7 +378,14 @@ enum dpcd_downstream_port_detailed_type {
> union dwnstream_port_caps_byte2 {
> struct {
> uint8_t MAX_BITS_PER_COLOR_COMPONENT:2;
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + uint8_t MAX_ENCODED_LINK_BW_SUPPORT:3;
> + uint8_t SOURCE_CONTROL_MODE_SUPPORT:1;
> + uint8_t CONCURRENT_LINK_BRING_UP_SEQ_SUPPORT:1;
> + uint8_t RESERVED:1;
> +#else
> uint8_t RESERVED:6;
> +#endif
> } bits;
> uint8_t raw;
> };
> @@ -416,6 +423,30 @@ union dwnstream_port_caps_byte3_hdmi {
> uint8_t raw;
> };
>
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> +union hdmi_sink_encoded_link_bw_support {
> + struct {
> + uint8_t HDMI_SINK_ENCODED_LINK_BW_SUPPORT:3;
> + uint8_t RESERVED:5;
> + } bits;
> + uint8_t raw;
> +};
> +
> +union hdmi_encoded_link_bw {
> + struct {
> + uint8_t FRL_MODE:1; // Bit 0
> + uint8_t BW_9Gbps:1;
> + uint8_t BW_18Gbps:1;
> + uint8_t BW_24Gbps:1;
> + uint8_t BW_32Gbps:1;
> + uint8_t BW_40Gbps:1;
> + uint8_t BW_48Gbps:1;
> + uint8_t RESERVED:1; // Bit 7
> + } bits;
> + uint8_t raw;
> +};
> +#endif
> +
> /*4-byte structure for detailed capabilities of a down-stream port
> (DP-to-TMDS converter).*/
> union dwnstream_portxcaps {
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> index 52355fe6994c..eac34f591a3f 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> @@ -741,6 +741,9 @@ struct dc_dsc_config {
> uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */
> bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */
> int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + bool is_frl; /* indicate if DSC is applied based on HDMI FRL sink's capability */
> +#endif
> bool is_dp; /* indicate if DSC is applied based on DP's capability */
> };
> struct dc_crtc_timing {
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
> index d449e72a4e2a..d5887d976ef6 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_link.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
> @@ -443,6 +443,7 @@ bool dc_link_is_fec_supported(const struct dc_link *link);
> bool dc_link_should_enable_fec(const struct dc_link *link);
>
> #if defined(CONFIG_DRM_AMD_DC_DCN)
> +uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw);
> enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link);
> #endif
> #endif /* DC_LINK_H_ */
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
> index 388457ffc0a8..cb26ff8a54c5 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_types.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
> @@ -430,6 +430,7 @@ struct dc_dongle_caps {
> uint32_t dp_hdmi_max_bpc;
> uint32_t dp_hdmi_max_pixel_clk_in_khz;
> #if defined(CONFIG_DRM_AMD_DC_DCN)
> + uint32_t dp_hdmi_frl_max_link_bw_in_kbps;
> struct dc_dongle_dfp_cap_ext dfp_cap_ext;
> #endif
> };
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
> index 3883f918b3bb..40b122a708ef 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
> @@ -3796,6 +3796,8 @@ static bool dcn20_resource_construct(
> dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
> dc->caps.color.mpc.ocsc = 1;
>
> + dc->caps.hdmi_frl_pcon_support = true;
> +
> if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
> dc->debug = debug_defaults_drv;
> } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
> index d452a0d1777e..da6031cef244 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
> @@ -2028,6 +2028,8 @@ static bool dcn21_resource_construct(
> dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
> dc->caps.color.mpc.ocsc = 1;
>
> + dc->caps.hdmi_frl_pcon_support = true;
> +
> if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
> dc->debug = debug_defaults_drv;
> else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> index 79a66e0c4303..77331a45a749 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> @@ -2639,6 +2639,8 @@ static bool dcn30_resource_construct(
> dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
> dc->caps.color.mpc.ocsc = 1;
>
> + dc->caps.hdmi_frl_pcon_support = true;
> +
> /* read VBIOS LTTPR caps */
> {
> if (ctx->dc_bios->funcs->get_lttpr_caps) {
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
> index 6460fab496f6..673e080e1982 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
> @@ -2193,6 +2193,7 @@ static bool dcn31_resource_construct(
> dc->caps.post_blend_color_processing = true;
> dc->caps.force_dp_tps4_for_cp2520 = true;
> dc->caps.dp_hpo = true;
> + dc->caps.hdmi_frl_pcon_support = true;
> dc->caps.edp_dsc_support = true;
> dc->caps.extended_aux_timeout_support = true;
> dc->caps.dmcub_support = true;
>
More information about the amd-gfx
mailing list