Commit 4f8e37db authored by Meenakshikumar Somasundaram's avatar Meenakshikumar Somasundaram Committed by Alex Deucher
Browse files

drm/amd/display: Support for DMUB AUX



[WHY]
To process AUX transactions with DMUB using inbox1 and outbox1 mail boxes.

[HOW]
1) Added inbox1 command DMUB_CMD__DP_AUX_ACCESS to issue AUX commands
   to DMUB in dc_process_dmub_aux_transfer_async(). DMUB processes AUX cmd
   with DCN and sends reply back in an outbox1 message triggering an
   outbox1 interrupt to driver.
2) In existing driver implementation, AUX commands are processed
   synchronously by configuring DCN reg. But in DMUB AUX, driver sends an
   inbox1 message and waits for a conditional variable (CV) which will be
   signaled by outbox1 ISR.
3) As the driver holds dal and dc locks while waiting for CV, the outbox1
   ISR is registered with noMutexWait set to true, which allows ISR to run
   and signal CV. This sets a constraint on ISR to not modify variables
   such as dc, dmub, etc.
4) Created dmub_outbox.c with dmub_enable_outbox_notification() to enable
   outbox1 mailbox.
5) New mailbox address ranges allocated for outbox1 of size DMUB_RB_SIZE.
   Created dmub functions for Outbox1: dmub_dcn20_setup_out_mailbox(),
   dmub_dcn20_get_outbox1_wptr() and dmub_dcn20_set_outbox1_rptr().
6) Added functions dc_stat_get_dmub_notification() and
   dmub_srv_stat_get_notification() to retrieve Outbox1 message.
7) Currently, DMUB doesn't opens DDC in AUX mode before issuing AUX
   transaction. A workaround is added in dce_aux_transfer_dmub_raw() to
   open in DDC in AUX mode for every AUX transaction.
8) Added dc debug option enable_dmub_aux_for_legacy_ddc enable/disable
   DMUB AUX. This debug option is checked dce_aux_transfer_with_retries()
   to select the method to process AUX transactions.

Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarMeenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c524c1c9
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include "dc_link_ddc.h"

#include "i2caux_interface.h"
#include "dmub_cmd.h"
#if defined(CONFIG_DEBUG_FS)
#include "amdgpu_dm_debugfs.h"
#endif
@@ -51,7 +52,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
{
	ssize_t result = 0;
	struct aux_payload payload;
	enum aux_channel_operation_result operation_result;
	enum aux_return_code_type operation_result;

	if (WARN_ON(msg->size > 16))
		return -E2BIG;
@@ -73,17 +74,19 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,

	if (result < 0)
		switch (operation_result) {
		case AUX_CHANNEL_OPERATION_SUCCEEDED:
		case AUX_RET_SUCCESS:
			break;
		case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
		case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
		case AUX_RET_ERROR_HPD_DISCON:
		case AUX_RET_ERROR_UNKNOWN:
		case AUX_RET_ERROR_INVALID_OPERATION:
		case AUX_RET_ERROR_PROTOCOL_ERROR:
			result = -EIO;
			break;
		case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
		case AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE:
		case AUX_RET_ERROR_INVALID_REPLY:
		case AUX_RET_ERROR_ENGINE_ACQUIRE:
			result = -EBUSY;
			break;
		case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
		case AUX_RET_ERROR_TIMEOUT:
			result = -ETIMEDOUT;
			break;
		}
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI

include $(AMD_DC)

DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \
DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \
dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o

ifdef CONFIG_DRM_AMD_DC_DCN
+94 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@

#include "dmub/dmub_srv.h"

#include "i2caux_interface.h"
#include "dce/dmub_hw_lock_mgr.h"

#include "dc_trace.h"
@@ -3190,3 +3191,96 @@ void dc_hardware_release(struct dc *dc)
		dc->hwss.hardware_release(dc);
}
#endif

/**
 *****************************************************************************
 *  Function: dc_enable_dmub_notifications
 *
 *  @brief
 *		Returns whether dmub notification can be enabled
 *
 *  @param
 *		[in] dc: dc structure
 *
 *	@return
 *		True to enable dmub notifications, False otherwise
 *****************************************************************************
 */
bool dc_enable_dmub_notifications(struct dc *dc)
{
	/* dmub aux needs dmub notifications to be enabled */
	return dc->debug.enable_dmub_aux_for_legacy_ddc;
}

/**
 *****************************************************************************
 *  Function: dc_process_dmub_aux_transfer_async
 *
 *  @brief
 *		Submits aux command to dmub via inbox message
 *		Sets port index appropriately for legacy DDC
 *
 *  @param
 *		[in] dc: dc structure
 *		[in] link_index: link index
 *		[in] payload: aux payload
 *
 *	@return
 *		True if successful, False if failure
 *****************************************************************************
 */
bool dc_process_dmub_aux_transfer_async(struct dc *dc,
				uint32_t link_index,
				struct aux_payload *payload)
{
	uint8_t action;
	union dmub_rb_cmd cmd = {0};
	struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;

	ASSERT(payload->length <= 16);

	cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS;
	cmd.dp_aux_access.header.payload_bytes = 0;
	cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_LEGACY_DDC;
	cmd.dp_aux_access.aux_control.instance = dc->links[link_index]->ddc_hw_inst;
	cmd.dp_aux_access.aux_control.sw_crc_enabled = 0;
	cmd.dp_aux_access.aux_control.timeout = 0;
	cmd.dp_aux_access.aux_control.dpaux.address = payload->address;
	cmd.dp_aux_access.aux_control.dpaux.is_i2c_over_aux = payload->i2c_over_aux;
	cmd.dp_aux_access.aux_control.dpaux.length = payload->length;

	/* set aux action */
	if (payload->i2c_over_aux) {
		if (payload->write) {
			if (payload->mot)
				action = DP_AUX_REQ_ACTION_I2C_WRITE_MOT;
			else
				action = DP_AUX_REQ_ACTION_I2C_WRITE;
		} else {
			if (payload->mot)
				action = DP_AUX_REQ_ACTION_I2C_READ_MOT;
			else
				action = DP_AUX_REQ_ACTION_I2C_READ;
			}
	} else {
		if (payload->write)
			action = DP_AUX_REQ_ACTION_DPCD_WRITE;
		else
			action = DP_AUX_REQ_ACTION_DPCD_READ;
	}

	cmd.dp_aux_access.aux_control.dpaux.action = action;

	if (payload->length && payload->write) {
		memcpy(cmd.dp_aux_access.aux_control.dpaux.data,
			payload->data,
			payload->length
			);
	}

	dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
	dc_dmub_srv_cmd_execute(dmub_srv);
	dc_dmub_srv_wait_idle(dmub_srv);

	return true;
}
+2 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "core_types.h"
#include "dc_link_ddc.h"
#include "dce/dce_aux.h"
#include "dmub/inc/dmub_cmd.h"

#define DC_LOGGER_INIT(logger)

@@ -655,7 +656,7 @@ bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
 */
int dc_link_aux_transfer_raw(struct ddc_service *ddc,
		struct aux_payload *payload,
		enum aux_channel_operation_result *operation_result)
		enum aux_return_code_type *operation_result)
{
	return dce_aux_transfer_raw(ddc, payload, operation_result);
}
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 */

#include "dc/dc_stat.h"
#include "dmub/dmub_srv_stat.h"
#include "dc_dmub_srv.h"

/**
 * DOC: DC STAT Interface
 *
 * These interfaces are called without acquiring DAL and DC locks.
 * Hence, there is limitations on whese interfaces can access. Only
 * variables exclusively defined for these interfaces can be modified.
 */

/**
 *****************************************************************************
 *  Function: dc_stat_get_dmub_notification
 *
 *  @brief
 *		Calls dmub layer to retrieve dmub notification
 *
 *  @param
 *		[in] dc: dc structure
 *		[in] notify: dmub notification structure
 *
 *  @return
 *     None
 *****************************************************************************
 */
void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification *notify)
{
	/**
	 * This function is called without dal and dc locks, so
	 * we shall not modify any dc, dc_dmub_srv or dmub variables
	 * except variables exclusively accessed by this function
	 */
	struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub;
	enum dmub_status status;

	status = dmub_srv_stat_get_notification(dmub, notify);
	ASSERT(status == DMUB_STATUS_OK);
}
Loading