summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorWayne Lin <Wayne.Lin@amd.com>2026-03-06 16:32:36 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-04-17 15:21:05 -0400
commit602b8ef9d2a607c6028c6b9d8e174b2e859dd769 (patch)
treebd6f092b0cdba7cc4a9017b1653d1cfe547bb30b /drivers/gpu/drm/amd
parent6f71d5dd320663f2003fff252a5da93f4f753bef (diff)
drm/amd/display: Enable sink freesync via MCCS
If sink like HDMI indicates supporting freesync via MCCS, explicitly to send vcp set command on sink to enable freesync. Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Wayne Lin <Wayne.Lin@amd.com> Signed-off-by: Roman Li <roman.li@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c74
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_helpers.h5
3 files changed, 81 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c7dd75c5d921..5f9bbe178265 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -13383,6 +13383,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
(!sink->edid_caps.freesync_vcp_code ||
(sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
freesync_capable = false;
+ if (sink->mccs_caps.freesync_supported && freesync_capable)
+ dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
update:
if (dm_con_state)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 1332969c7491..3b8ae7798a93 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1606,3 +1606,77 @@ void dm_helpers_read_mccs_caps(struct dc_context *ctx, struct dc_link *link,
}
}
+static int mccs_operation_vcp_set(unsigned int vcp_code, struct dc_link *link, uint16_t value)
+{
+ const unsigned char retry_interval_ms = 40;
+ unsigned char retry = 5;
+ struct amdgpu_dm_connector *aconnector = link->priv;
+ struct i2c_adapter *ddc;
+ struct i2c_msg msg = {0};
+ int ret = 0;
+ int idx;
+
+ unsigned char wr_data[MCCS_OP_BUFF_SIZE_WR_VCP_SET] = {
+ MCCS_SRC_ADDR, /* Byte0 - Src Addr */
+ MCCS_LENGTH_OFFSET + 4, /* Byte1 - Length */
+ MCCS_OP_CODE_VCP_SET, /* Byte2 - MCCS Command */
+ (unsigned char)vcp_code, /* Byte3 - VCP Code */
+ (unsigned char)(value >> 8), /* Byte4 - Value High Byte */
+ (unsigned char)(value & 0xFF), /* Byte5 - Value Low Byte */
+ MCCS_DEST_ADDR << 1 /* Byte6 - CheckSum */
+ };
+
+ /* calculate checksum */
+ for (idx = 0; idx < (MCCS_OP_BUFF_SIZE_WR_VCP_SET - 1); idx++)
+ wr_data[MCCS_OP_BUFF_SIZE_WR_VCP_SET - 1] ^= wr_data[idx];
+
+ if (link->aux_mode)
+ ddc = &aconnector->dm_dp_aux.aux.ddc;
+ else
+ ddc = &aconnector->i2c->base;
+
+ do {
+ msg.addr = MCCS_DEST_ADDR;
+ msg.flags = 0;
+ msg.len = MCCS_OP_BUFF_SIZE_WR_VCP_SET;
+ msg.buf = wr_data;
+
+ ret = i2c_transfer(ddc, &msg, 1);
+ if (ret == 1)
+ break;
+
+ retry--;
+ msleep(retry_interval_ms);
+ } while (retry);
+
+ if (!retry)
+ return -EIO;
+
+ return 0;
+}
+
+void dm_helpers_mccs_vcp_set(struct dc_context *ctx, struct dc_link *link,
+ struct dc_sink *sink)
+{
+ struct drm_device *dev;
+ const uint16_t enable = 0x0101;
+
+ if (!ctx)
+ return;
+ dev = adev_to_drm(ctx->driver_context);
+
+ if (!link || !sink) {
+ drm_dbg_driver(dev, "%s: link or sink is NULL", __func__);
+ return;
+ }
+
+ if (!sink->mccs_caps.freesync_supported) {
+ drm_dbg_driver(dev, "%s: MCCS freesync not supported on this sink", __func__);
+ return;
+ }
+
+ if (mccs_operation_vcp_set(sink->edid_caps.freesync_vcp_code, link, enable))
+ drm_dbg_driver(dev, "%s: Failed to set VCP code %d", __func__,
+ sink->edid_caps.freesync_vcp_code);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
index 3aa2b11f559b..107aec6a1265 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
@@ -186,6 +186,11 @@ void dm_helpers_read_mccs_caps(
struct dc_link *link,
struct dc_sink *sink);
+void dm_helpers_mccs_vcp_set(
+ struct dc_context *ctx,
+ struct dc_link *link,
+ struct dc_sink *sink);
+
bool dm_helpers_dp_handle_test_pattern_request(
struct dc_context *ctx,
const struct dc_link *link,