Commit c022375a authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher

drm/amd/display: Add DP-HDMI FRL PCON Support in DC

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.

v2: squash in warning fix (Alex)
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 50b1f44e
...@@ -2750,8 +2750,23 @@ static bool dp_active_dongle_validate_timing( ...@@ -2750,8 +2750,23 @@ static bool dp_active_dongle_validate_timing(
return false; 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)) if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
return false; return false;
#endif
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
} }
......
...@@ -4313,6 +4313,56 @@ static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc) ...@@ -4313,6 +4313,56 @@ static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
return -1; 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) static void read_dp_device_vendor_id(struct dc_link *link)
{ {
struct dp_device_vendor_id dp_id; struct dp_device_vendor_id dp_id;
...@@ -4424,6 +4474,27 @@ static void get_active_converter_info( ...@@ -4424,6 +4474,27 @@ static void get_active_converter_info(
translate_dpcd_max_bpc( translate_dpcd_max_bpc(
hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT); hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link->dc->caps.hdmi_frl_pcon_support) {
union hdmi_encoded_link_bw hdmi_encoded_link_bw;
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);
// 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) if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
link->dpcd_caps.dongle_caps.extendedCapValid = true; link->dpcd_caps.dongle_caps.extendedCapValid = true;
} }
......
...@@ -187,6 +187,7 @@ struct dc_caps { ...@@ -187,6 +187,7 @@ struct dc_caps {
struct dc_color_caps color; struct dc_color_caps color;
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
bool dp_hpo; bool dp_hpo;
bool hdmi_frl_pcon_support;
#endif #endif
bool edp_dsc_support; bool edp_dsc_support;
bool vbios_lttpr_aware; bool vbios_lttpr_aware;
...@@ -1294,6 +1295,11 @@ struct dc_sink_dsc_caps { ...@@ -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), // 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
// 'false' if they are sink's DSC caps // 'false' if they are sink's DSC caps
bool is_virtual_dpcd_dsc; 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; struct dsc_dec_dpcd_caps dsc_dec_caps;
}; };
......
...@@ -378,7 +378,14 @@ enum dpcd_downstream_port_detailed_type { ...@@ -378,7 +378,14 @@ enum dpcd_downstream_port_detailed_type {
union dwnstream_port_caps_byte2 { union dwnstream_port_caps_byte2 {
struct { struct {
uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; 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; uint8_t RESERVED:6;
#endif
} bits; } bits;
uint8_t raw; uint8_t raw;
}; };
...@@ -416,6 +423,30 @@ union dwnstream_port_caps_byte3_hdmi { ...@@ -416,6 +423,30 @@ union dwnstream_port_caps_byte3_hdmi {
uint8_t raw; 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 /*4-byte structure for detailed capabilities of a down-stream port
(DP-to-TMDS converter).*/ (DP-to-TMDS converter).*/
union dwnstream_portxcaps { union dwnstream_portxcaps {
......
...@@ -741,6 +741,9 @@ struct dc_dsc_config { ...@@ -741,6 +741,9 @@ struct dc_dsc_config {
uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */ 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'. */ 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 */ 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 */ bool is_dp; /* indicate if DSC is applied based on DP's capability */
}; };
struct dc_crtc_timing { struct dc_crtc_timing {
......
...@@ -443,6 +443,7 @@ bool dc_link_is_fec_supported(const struct dc_link *link); ...@@ -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); bool dc_link_should_enable_fec(const struct dc_link *link);
#if defined(CONFIG_DRM_AMD_DC_DCN) #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); enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link);
#endif #endif
#endif /* DC_LINK_H_ */ #endif /* DC_LINK_H_ */
...@@ -430,6 +430,7 @@ struct dc_dongle_caps { ...@@ -430,6 +430,7 @@ struct dc_dongle_caps {
uint32_t dp_hdmi_max_bpc; uint32_t dp_hdmi_max_bpc;
uint32_t dp_hdmi_max_pixel_clk_in_khz; uint32_t dp_hdmi_max_pixel_clk_in_khz;
#if defined(CONFIG_DRM_AMD_DC_DCN) #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; struct dc_dongle_dfp_cap_ext dfp_cap_ext;
#endif #endif
}; };
......
...@@ -3796,6 +3796,8 @@ static bool dcn20_resource_construct( ...@@ -3796,6 +3796,8 @@ static bool dcn20_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0; dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1; dc->caps.color.mpc.ocsc = 1;
dc->caps.hdmi_frl_pcon_support = true;
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) { if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
dc->debug = debug_defaults_drv; dc->debug = debug_defaults_drv;
} else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) { } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
......
...@@ -2028,6 +2028,8 @@ static bool dcn21_resource_construct( ...@@ -2028,6 +2028,8 @@ static bool dcn21_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0; dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1; dc->caps.color.mpc.ocsc = 1;
dc->caps.hdmi_frl_pcon_support = true;
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv; dc->debug = debug_defaults_drv;
else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) { else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
......
...@@ -2639,6 +2639,8 @@ static bool dcn30_resource_construct( ...@@ -2639,6 +2639,8 @@ static bool dcn30_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0; dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1; dc->caps.color.mpc.ocsc = 1;
dc->caps.hdmi_frl_pcon_support = true;
/* read VBIOS LTTPR caps */ /* read VBIOS LTTPR caps */
{ {
if (ctx->dc_bios->funcs->get_lttpr_caps) { if (ctx->dc_bios->funcs->get_lttpr_caps) {
......
...@@ -2199,6 +2199,7 @@ static bool dcn31_resource_construct( ...@@ -2199,6 +2199,7 @@ static bool dcn31_resource_construct(
dc->caps.post_blend_color_processing = true; dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true; dc->caps.force_dp_tps4_for_cp2520 = true;
dc->caps.dp_hpo = true; dc->caps.dp_hpo = true;
dc->caps.hdmi_frl_pcon_support = true;
dc->caps.edp_dsc_support = true; dc->caps.edp_dsc_support = true;
dc->caps.extended_aux_timeout_support = true; dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true; dc->caps.dmcub_support = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment