Commit 88f52b1f authored by Jude Shih's avatar Jude Shih Committed by Alex Deucher
Browse files

drm/amd/display: Support for SET_CONFIG processing with DMUB



[Why]
To process SET_CONFIG transactions with DMUB using inbox1 and
outbox1 mail boxes.

[How]
1) DMUB posts SET_CONFIG reply as an Outbox1 message of type
   DMUB_OUT_CMD__SET_CONFIG_REPLY.
2) The dmub async to sync mechanism for AUX is modified to accommodate
   SET_CONFIG commands for both command issue and reply code paths.

Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarWayne Lin <Wayne.Lin@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarJude Shih <shenshih@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b0ce6272
Loading
Loading
Loading
Loading
+59 −14
Original line number Diff line number Diff line
@@ -11345,29 +11345,74 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
	return value;
}

int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int linkIndex,
				struct aux_payload *payload, enum aux_return_code_type *operation_result)
int amdgpu_dm_set_dmub_async_sync_status(bool is_cmd_aux, struct dc_context *ctx,
	uint8_t status_type, uint32_t *operation_result)
{
	struct amdgpu_device *adev = ctx->driver_context;
	int return_status = -1;
	struct dmub_notification *p_notify = adev->dm.dmub_notify;

	if (is_cmd_aux) {
		if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS) {
			return_status = p_notify->aux_reply.length;
			*operation_result = p_notify->result;
		} else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT) {
			*operation_result = AUX_RET_ERROR_TIMEOUT;
		} else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_FAIL) {
			*operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
		} else {
			*operation_result = AUX_RET_ERROR_UNKNOWN;
		}
	} else {
		if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS) {
			return_status = 0;
			*operation_result = p_notify->sc_status;
		} else {
			*operation_result = SET_CONFIG_UNKNOWN_ERROR;
		}
	}

	return return_status;
}

int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux, struct dc_context *ctx,
	unsigned int link_index, void *cmd_payload, void *operation_result)
{
	struct amdgpu_device *adev = ctx->driver_context;
	int ret = 0;

	dc_process_dmub_aux_transfer_async(ctx->dc, linkIndex, payload);
	if (is_cmd_aux) {
		dc_process_dmub_aux_transfer_async(ctx->dc,
			link_index, (struct aux_payload *)cmd_payload);
	} else if (dc_process_dmub_set_config_async(ctx->dc, link_index,
					(struct set_config_cmd_payload *)cmd_payload,
					adev->dm.dmub_notify)) {
		return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
					ctx, DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS,
					(uint32_t *)operation_result);
	}

	ret = wait_for_completion_interruptible_timeout(&adev->dm.dmub_aux_transfer_done, 10*HZ);
	if (ret == 0) {
		*operation_result = AUX_RET_ERROR_TIMEOUT;
		return -1;
		return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
				ctx, DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT,
				(uint32_t *)operation_result);
	}
	*operation_result = (enum aux_return_code_type)adev->dm.dmub_notify->result;

	if (is_cmd_aux) {
		if (adev->dm.dmub_notify->result == AUX_RET_SUCCESS) {
		(*payload->reply) = adev->dm.dmub_notify->aux_reply.command;
			struct aux_payload *payload = (struct aux_payload *)cmd_payload;

		// For read case, Copy data to payload
			payload->reply[0] = adev->dm.dmub_notify->aux_reply.command;
			if (!payload->write && adev->dm.dmub_notify->aux_reply.length &&
		(*payload->reply == AUX_TRANSACTION_REPLY_AUX_ACK))
			    payload->reply[0] == AUX_TRANSACTION_REPLY_AUX_ACK) {
				memcpy(payload->data, adev->dm.dmub_notify->aux_reply.data,
				       adev->dm.dmub_notify->aux_reply.length);
			}
		}
	}

	return adev->dm.dmub_notify->aux_reply.length;
	return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
			ctx, DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS,
			(uint32_t *)operation_result);
}
+10 −2
Original line number Diff line number Diff line
@@ -49,6 +49,13 @@
#define AMDGPU_DM_MAX_NUM_EDP 2

#define AMDGPU_DMUB_NOTIFICATION_MAX 5

/**
 * DMUB Async to Sync Mechanism Status
 **/
#define DMUB_ASYNC_TO_SYNC_ACCESS_FAIL 1
#define DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT 2
#define DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS 3
/*
#include "include/amdgpu_dal_power_if.h"
#include "amdgpu_dm_irq.h"
@@ -721,6 +728,7 @@ void amdgpu_dm_update_connector_after_detect(

extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;

int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int linkIndex,
					struct aux_payload *payload, enum aux_return_code_type *operation_result);
int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux,
					struct dc_context *ctx, unsigned int link_index,
					void *payload, void *operation_result);
#endif /* __AMDGPU_DM_H__ */
+15 −2
Original line number Diff line number Diff line
@@ -683,8 +683,21 @@ int dm_helper_dmub_aux_transfer_sync(
		struct aux_payload *payload,
		enum aux_return_code_type *operation_result)
{
	return amdgpu_dm_process_dmub_aux_transfer_sync(ctx, link->link_index, payload, operation_result);
	return amdgpu_dm_process_dmub_aux_transfer_sync(true, ctx,
			link->link_index, (void *)payload,
			(void *)operation_result);
}

int dm_helpers_dmub_set_config_sync(struct dc_context *ctx,
		const struct dc_link *link,
		struct set_config_cmd_payload *payload,
		enum set_config_status *operation_result)
{
	return amdgpu_dm_process_dmub_aux_transfer_sync(false, ctx,
			link->link_index, (void *)payload,
			(void *)operation_result);
}

void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
{
	/* TODO: something */
+4 −2
Original line number Diff line number Diff line
@@ -659,11 +659,13 @@ int dc_link_aux_transfer_raw(struct ddc_service *ddc,
		struct aux_payload *payload,
		enum aux_return_code_type *operation_result)
{
	if (dc_enable_dmub_notifications(ddc->ctx->dc))
	if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc ||
	    !ddc->ddc_pin) {
		return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
	else
	} else {
		return dce_aux_transfer_raw(ddc, payload, operation_result);
	}
}

/* dc_link_aux_transfer_with_retries() - Attempt to submit an
 * aux payload, retrying on timeouts, defers, and busy states
+6 −0
Original line number Diff line number Diff line
@@ -130,6 +130,12 @@ static enum dc_status core_link_send_set_config(struct dc_link *link,
	payload.msg_type = msg_type;
	payload.msg_data = msg_data;

	if (!link->ddc->ddc_pin && !link->aux_access_disabled &&
	    (dm_helpers_dmub_set_config_sync(link->ctx, link,
					     &payload, &set_config_result) == -1)) {
		return DC_ERROR_UNEXPECTED;
	}

	/* set_config should return ACK if successful */
	return (set_config_result == SET_CONFIG_ACK_RECEIVED) ? DC_OK : DC_ERROR_UNEXPECTED;
}