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: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Wayne Lin <Wayne.Lin@amd.com> Acked-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Jude Shih <shenshih@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
b0ce627218
commit
88f52b1fff
5 changed files with 97 additions and 23 deletions
|
@ -11345,29 +11345,74 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int linkIndex,
|
int amdgpu_dm_set_dmub_async_sync_status(bool is_cmd_aux, struct dc_context *ctx,
|
||||||
struct aux_payload *payload, enum aux_return_code_type *operation_result)
|
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;
|
struct amdgpu_device *adev = ctx->driver_context;
|
||||||
int ret = 0;
|
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);
|
ret = wait_for_completion_interruptible_timeout(&adev->dm.dmub_aux_transfer_done, 10*HZ);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
*operation_result = AUX_RET_ERROR_TIMEOUT;
|
return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
|
||||||
return -1;
|
ctx, DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT,
|
||||||
}
|
(uint32_t *)operation_result);
|
||||||
*operation_result = (enum aux_return_code_type)adev->dm.dmub_notify->result;
|
|
||||||
|
|
||||||
if (adev->dm.dmub_notify->result == AUX_RET_SUCCESS) {
|
|
||||||
(*payload->reply) = adev->dm.dmub_notify->aux_reply.command;
|
|
||||||
|
|
||||||
// For read case, Copy data to payload
|
|
||||||
if (!payload->write && adev->dm.dmub_notify->aux_reply.length &&
|
|
||||||
(*payload->reply == 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;
|
if (is_cmd_aux) {
|
||||||
|
if (adev->dm.dmub_notify->result == AUX_RET_SUCCESS) {
|
||||||
|
struct aux_payload *payload = (struct aux_payload *)cmd_payload;
|
||||||
|
|
||||||
|
payload->reply[0] = adev->dm.dmub_notify->aux_reply.command;
|
||||||
|
if (!payload->write && adev->dm.dmub_notify->aux_reply.length &&
|
||||||
|
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 amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
|
||||||
|
ctx, DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS,
|
||||||
|
(uint32_t *)operation_result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,13 @@
|
||||||
#define AMDGPU_DM_MAX_NUM_EDP 2
|
#define AMDGPU_DM_MAX_NUM_EDP 2
|
||||||
|
|
||||||
#define AMDGPU_DMUB_NOTIFICATION_MAX 5
|
#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 "include/amdgpu_dal_power_if.h"
|
||||||
#include "amdgpu_dm_irq.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;
|
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,
|
int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux,
|
||||||
struct aux_payload *payload, enum aux_return_code_type *operation_result);
|
struct dc_context *ctx, unsigned int link_index,
|
||||||
|
void *payload, void *operation_result);
|
||||||
#endif /* __AMDGPU_DM_H__ */
|
#endif /* __AMDGPU_DM_H__ */
|
||||||
|
|
|
@ -683,8 +683,21 @@ int dm_helper_dmub_aux_transfer_sync(
|
||||||
struct aux_payload *payload,
|
struct aux_payload *payload,
|
||||||
enum aux_return_code_type *operation_result)
|
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)
|
void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
|
||||||
{
|
{
|
||||||
/* TODO: something */
|
/* TODO: something */
|
||||||
|
@ -799,4 +812,4 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable)
|
||||||
{
|
{
|
||||||
/* TODO: add peridic detection implementation */
|
/* TODO: add peridic detection implementation */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -659,10 +659,12 @@ int dc_link_aux_transfer_raw(struct ddc_service *ddc,
|
||||||
struct aux_payload *payload,
|
struct aux_payload *payload,
|
||||||
enum aux_return_code_type *operation_result)
|
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);
|
return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
|
||||||
else
|
} else {
|
||||||
return dce_aux_transfer_raw(ddc, payload, operation_result);
|
return dce_aux_transfer_raw(ddc, payload, operation_result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dc_link_aux_transfer_with_retries() - Attempt to submit an
|
/* dc_link_aux_transfer_with_retries() - Attempt to submit an
|
||||||
|
|
|
@ -130,6 +130,12 @@ static enum dc_status core_link_send_set_config(struct dc_link *link,
|
||||||
payload.msg_type = msg_type;
|
payload.msg_type = msg_type;
|
||||||
payload.msg_data = msg_data;
|
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 */
|
/* set_config should return ACK if successful */
|
||||||
return (set_config_result == SET_CONFIG_ACK_RECEIVED) ? DC_OK : DC_ERROR_UNEXPECTED;
|
return (set_config_result == SET_CONFIG_ACK_RECEIVED) ? DC_OK : DC_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue