mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
drm/amd/display: Add Freesync HDMI support to DM with DMUB
[Why] Changes in DM needed to support Freesync HDMI on DMUB. [How] Change implementation to parse CEA blocks in case of DMUB-enabled ASICs. Signed-off-by: Stylon Wang <stylon.wang@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
0713921b4c
commit
46db138dc8
|
|
@ -10549,13 +10549,68 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,
|
|||
return capable;
|
||||
}
|
||||
|
||||
static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
||||
static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
|
||||
unsigned int offset,
|
||||
unsigned int total_length,
|
||||
uint8_t *data,
|
||||
unsigned int length,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb)
|
||||
{
|
||||
bool res;
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dmub_cmd_send_edid_cea *input;
|
||||
struct dmub_cmd_edid_cea_output *output;
|
||||
|
||||
if (length > DMUB_EDID_CEA_DATA_CHUNK_BYTES)
|
||||
return false;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
input = &cmd.edid_cea.data.input;
|
||||
|
||||
cmd.edid_cea.header.type = DMUB_CMD__EDID_CEA;
|
||||
cmd.edid_cea.header.sub_type = 0;
|
||||
cmd.edid_cea.header.payload_bytes =
|
||||
sizeof(cmd.edid_cea) - sizeof(cmd.edid_cea.header);
|
||||
input->offset = offset;
|
||||
input->length = length;
|
||||
input->total_length = total_length;
|
||||
memcpy(input->payload, data, length);
|
||||
|
||||
res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd);
|
||||
if (!res) {
|
||||
DRM_ERROR("EDID CEA parser failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
output = &cmd.edid_cea.data.output;
|
||||
|
||||
if (output->type == DMUB_CMD__EDID_CEA_ACK) {
|
||||
if (!output->ack.success) {
|
||||
DRM_ERROR("EDID CEA ack failed at offset %d\n",
|
||||
output->ack.offset);
|
||||
}
|
||||
} else if (output->type == DMUB_CMD__EDID_CEA_AMD_VSDB) {
|
||||
if (!output->amd_vsdb.vsdb_found)
|
||||
return false;
|
||||
|
||||
vsdb->freesync_supported = output->amd_vsdb.freesync_supported;
|
||||
vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version;
|
||||
vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate;
|
||||
vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate;
|
||||
} else {
|
||||
DRM_ERROR("Unknown EDID CEA parser results\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
|
||||
uint8_t *edid_ext, int len,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
|
||||
struct dc *dc = adev->dm.dc;
|
||||
|
||||
/* send extension block to DMCU for parsing */
|
||||
for (i = 0; i < len; i += 8) {
|
||||
|
|
@ -10563,14 +10618,14 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
|||
int offset;
|
||||
|
||||
/* send 8 bytes a time */
|
||||
if (!dc_edid_parser_send_cea(dc, i, len, &edid_ext[i], 8))
|
||||
if (!dc_edid_parser_send_cea(dm->dc, i, len, &edid_ext[i], 8))
|
||||
return false;
|
||||
|
||||
if (i+8 == len) {
|
||||
/* EDID block sent completed, expect result */
|
||||
int version, min_rate, max_rate;
|
||||
|
||||
res = dc_edid_parser_recv_amd_vsdb(dc, &version, &min_rate, &max_rate);
|
||||
res = dc_edid_parser_recv_amd_vsdb(dm->dc, &version, &min_rate, &max_rate);
|
||||
if (res) {
|
||||
/* amd vsdb found */
|
||||
vsdb_info->freesync_supported = 1;
|
||||
|
|
@ -10584,7 +10639,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
|||
}
|
||||
|
||||
/* check for ack*/
|
||||
res = dc_edid_parser_recv_cea_ack(dc, &offset);
|
||||
res = dc_edid_parser_recv_cea_ack(dm->dc, &offset);
|
||||
if (!res)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -10592,6 +10647,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
|
||||
uint8_t *edid_ext, int len,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* send extension block to DMCU for parsing */
|
||||
for (i = 0; i < len; i += 8) {
|
||||
/* send 8 bytes a time */
|
||||
if (!dm_edid_parser_send_cea(dm, i, len, &edid_ext[i], 8, vsdb_info))
|
||||
return false;
|
||||
}
|
||||
|
||||
return vsdb_info->freesync_supported;
|
||||
}
|
||||
|
||||
static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
||||
uint8_t *edid_ext, int len,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
|
||||
|
||||
if (adev->dm.dmub_srv)
|
||||
return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
|
||||
else
|
||||
return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
|
||||
}
|
||||
|
||||
static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
|
||||
struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user