Commit 46db138d authored by Stylon Wang's avatar Stylon Wang Committed by Alex Deucher

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: default avatarStylon Wang <stylon.wang@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0713921b
......@@ -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)
{
......
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