drm/amd/display: Update HDCP and info_packet modules for FRL

The HDCP module has a minor update for FRL, and info_packet is
updated for ALLM.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Harry Wentland 2026-04-24 14:31:43 -04:00 committed by Alex Deucher
parent fdaf63d9a8
commit 952df08d5b
9 changed files with 112 additions and 30 deletions

View File

@ -7620,7 +7620,7 @@ create_stream_for_sink(struct drm_connector *connector,
update_stream_signal(stream, sink);
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false);
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||

View File

@ -66,6 +66,7 @@ static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
return is_auth_needed &&
!hdcp->connection.link.adjust.hdcp1.disable &&
!is_frl_hdcp(hdcp) &&
!hdcp->connection.is_hdcp1_revoked;
}
@ -584,6 +585,7 @@ enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode(
switch (signal) {
case SIGNAL_TYPE_DVI_SINGLE_LINK:
case SIGNAL_TYPE_HDMI_TYPE_A:
case SIGNAL_TYPE_HDMI_FRL:
mode = MOD_HDCP_MODE_DEFAULT;
break;
case SIGNAL_TYPE_EDP:

View File

@ -406,6 +406,12 @@ static inline uint8_t is_hdmi_dvi_sl_hdcp(struct mod_hdcp *hdcp)
return (hdcp->connection.link.mode == MOD_HDCP_MODE_DEFAULT);
}
static inline uint8_t is_frl_hdcp(struct mod_hdcp *hdcp)
{
return (hdcp->connection.link.mode == MOD_HDCP_MODE_DEFAULT &&
hdcp->connection.link.hdmi.frl_enabled);
}
/* hdcp state helpers */
static inline uint8_t current_state(struct mod_hdcp *hdcp)
{

View File

@ -200,6 +200,8 @@ static enum mod_hdcp_status add_display_to_topology_v3(
TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_3;
dtm_cmd->dtm_in_message.topology_update_v3.encoder_type = TA_DTM_ENCODER_TYPE__DIG;
dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE;
if (is_frl_hdcp(hdcp))
dtm_cmd->dtm_in_message.topology_update_v3.encoder_type = TA_DTM_ENCODER_TYPE__FRL;
dtm_cmd->dtm_in_message.topology_update_v3.phy_id = link->phy_idx;
dtm_cmd->dtm_in_message.topology_update_v3.link_hdcp_cap = link->hdcp_supported_informational;
dtm_cmd->dtm_in_message.topology_update_v3.dio_output_type = link->dp.usb4_enabled ?

View File

@ -84,6 +84,7 @@ struct ta_dtm_topology_update_input_v2 {
uint32_t dig_fe;
uint32_t dp_mst_vcid;
uint32_t is_assr;
/*uint32_t is_frl;*/ /*todo*/
uint32_t max_hdcp_supported_version;
};
@ -91,6 +92,7 @@ struct ta_dtm_topology_update_input_v2 {
/* Security code will check real HW register values and these SW enum values */
enum ta_dtm_encoder_type {
TA_DTM_ENCODER_TYPE__INVALID = 0,
TA_DTM_ENCODER_TYPE__FRL = 0x20,
TA_DTM_ENCODER_TYPE__DIG = 0x10
};

View File

@ -90,6 +90,7 @@ struct mod_vrr_params_flip_interval {
struct mod_vrr_params {
bool supported;
bool send_info_frame;
bool m_const_engaged; // this is used when m_const is set up in OPTC so no overriding happens from FreeSync Module
enum mod_vrr_state state;
uint32_t min_refresh_in_uhz;
@ -98,6 +99,8 @@ struct mod_vrr_params {
uint32_t min_duration_in_us;
uint32_t fixed_refresh_in_uhz;
uint32_t m_const;
struct dc_crtc_timing_adjust adjust;
struct mod_vrr_params_fixed_refresh fixed;

View File

@ -114,6 +114,7 @@ struct mod_hdcp_displayport {
};
struct mod_hdcp_hdmi {
uint8_t frl_enabled;
uint8_t reserved;
};
enum mod_hdcp_operation_mode {

View File

@ -46,7 +46,7 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
enum color_transfer_func tf);
void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet);
struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue);
enum adaptive_sync_sdp_version {
AS_SDP_VER_0 = 0x0,

View File

@ -504,13 +504,16 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
* @info_packet: output structure where to store VSIF
*/
void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet)
struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue)
{
unsigned int length = 5;
bool hdmi_vic_mode = false;
uint8_t checksum = 0;
uint32_t i = 0;
enum dc_timing_3d_format format;
bool bALLM = (bool)ALLMEnabled;
bool bALLMVal = (bool)ALLMValue;
int CCBPC = 0;
info_packet->valid = false;
format = stream->timing.timing_3d_format;
@ -523,47 +526,110 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
&& format == TIMING_3D_FORMAT_NONE)
hdmi_vic_mode = true;
if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode)
if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode && !bALLM)
return;
info_packet->sb[1] = 0x03;
info_packet->sb[2] = 0x0C;
info_packet->sb[3] = 0x00;
if (!bALLM) {
info_packet->sb[1] = 0x03;
info_packet->sb[2] = 0x0C;
info_packet->sb[3] = 0x00;
if (format != TIMING_3D_FORMAT_NONE)
info_packet->sb[4] = (2 << 5);
if (format != TIMING_3D_FORMAT_NONE)
info_packet->sb[4] = (2 << 5);
else if (hdmi_vic_mode)
info_packet->sb[4] = (1 << 5);
else if (hdmi_vic_mode)
info_packet->sb[4] = (1 << 5);
switch (format) {
case TIMING_3D_FORMAT_HW_FRAME_PACKING:
case TIMING_3D_FORMAT_SW_FRAME_PACKING:
info_packet->sb[5] = (0x0 << 4);
break;
switch (format) {
case TIMING_3D_FORMAT_HW_FRAME_PACKING:
case TIMING_3D_FORMAT_SW_FRAME_PACKING:
info_packet->sb[5] = (0x0 << 4);
break;
case TIMING_3D_FORMAT_SIDE_BY_SIDE:
case TIMING_3D_FORMAT_SBS_SW_PACKED:
info_packet->sb[5] = (0x8 << 4);
length = 6;
break;
case TIMING_3D_FORMAT_SIDE_BY_SIDE:
case TIMING_3D_FORMAT_SBS_SW_PACKED:
info_packet->sb[5] = (0x8 << 4);
length = 6;
break;
case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
case TIMING_3D_FORMAT_TB_SW_PACKED:
info_packet->sb[5] = (0x6 << 4);
break;
case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
case TIMING_3D_FORMAT_TB_SW_PACKED:
info_packet->sb[5] = (0x6 << 4);
break;
default:
break;
}
default:
break;
if (hdmi_vic_mode) {
ASSERT(stream->timing.hdmi_vic <= 0xFF);
info_packet->sb[5] = (uint8_t)stream->timing.hdmi_vic;
}
} else {
info_packet->sb[1] = 0xD8;
info_packet->sb[2] = 0x5D;
info_packet->sb[3] = 0xC4;
info_packet->sb[4] = HF_VSIF_VERSION;
if (format != TIMING_3D_FORMAT_NONE) {
info_packet->sb[5] |= 0x01;
length = 6;
switch (format) {
case TIMING_3D_FORMAT_HW_FRAME_PACKING:
case TIMING_3D_FORMAT_SW_FRAME_PACKING:
info_packet->sb[6] = (0x0 << 4);
break;
case TIMING_3D_FORMAT_SIDE_BY_SIDE:
case TIMING_3D_FORMAT_SBS_SW_PACKED:
info_packet->sb[6] = (0x8 << 4);
break;
case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
case TIMING_3D_FORMAT_TB_SW_PACKED:
info_packet->sb[6] = (0x6 << 4);
break;
default:
break;
}
}
info_packet->sb[5] = (info_packet->sb[5] & ~0x02) | (bALLMVal << 1);
switch (stream->timing.display_color_depth) {
case COLOR_DEPTH_888:
CCBPC = 1;
break;
case COLOR_DEPTH_101010:
CCBPC = 3;
break;
case COLOR_DEPTH_121212:
CCBPC = 5;
break;
case COLOR_DEPTH_161616:
CCBPC = 9;
break;
case COLOR_DEPTH_UNDEFINED:
case COLOR_DEPTH_666:
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
case COLOR_DEPTH_999:
case COLOR_DEPTH_111111:
#endif
case COLOR_DEPTH_141414:
default:
break;
}
info_packet->sb[5] = (uint8_t)((info_packet->sb[5] & ~0xF0) | (CCBPC << 4));
}
if (hdmi_vic_mode)
info_packet->sb[5] = stream->timing.hdmi_vic;
info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR;
info_packet->hb1 = 0x01;
info_packet->hb2 = (uint8_t) (length);
checksum += info_packet->hb0;
checksum += info_packet->hb1;
checksum += info_packet->hb2;