Commit 01fcfc83 authored by David Francis's avatar David Francis Committed by Alex Deucher
Browse files

drm/amd: Add ucode DMCU support



DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

DMCU has two pieces of firmware: the ERAM and the interrupt
vectors, which must be loaded seperately.

To this end, the DMCU firmware has a custom header and parsing
logic similar to MEC, to extract the two ucodes from a single
struct firmware.

Signed-off-by: default avatarDavid Francis <David.Francis@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 240cd9a6
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -322,6 +322,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
{
	const struct common_firmware_header *header = NULL;
	const struct gfx_firmware_header_v1_0 *cp_hdr = NULL;
	const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;

	if (NULL == ucode->fw)
		return 0;
@@ -333,8 +334,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
		return 0;

	header = (const struct common_firmware_header *)ucode->fw->data;

	cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
	dmcu_hdr = (const struct dmcu_firmware_header_v1_0 *)ucode->fw->data;

	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
	    (ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
@@ -343,7 +344,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
	     ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2_JT &&
	     ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL &&
	     ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
	     ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM)) {
	     ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
		 ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
		 ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV)) {
		ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);

		memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
@@ -365,6 +368,20 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
					      le32_to_cpu(header->ucode_array_offset_bytes) +
					      le32_to_cpu(cp_hdr->jt_offset) * 4),
		       ucode->ucode_size);
	} else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_ERAM) {
		ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
				le32_to_cpu(dmcu_hdr->intv_size_bytes);

		memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
					      le32_to_cpu(header->ucode_array_offset_bytes)),
		       ucode->ucode_size);
	} else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_INTV) {
		ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size_bytes);

		memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
					      le32_to_cpu(header->ucode_array_offset_bytes) +
					      le32_to_cpu(dmcu_hdr->intv_offset_bytes)),
		       ucode->ucode_size);
	} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
		ucode->ucode_size = adev->gfx.rlc.save_restore_list_cntl_size_bytes;
		memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
+10 −0
Original line number Diff line number Diff line
@@ -157,6 +157,13 @@ struct gpu_info_firmware_header_v1_0 {
	uint16_t version_minor; /* version */
};

/* version_major=1, version_minor=0 */
struct dmcu_firmware_header_v1_0 {
	struct common_firmware_header header;
	uint32_t intv_offset_bytes; /* interrupt vectors offset from end of header, in bytes */
	uint32_t intv_size_bytes;  /* size of interrupt vectors, in bytes */
};

/* header is fixed size */
union amdgpu_firmware_header {
	struct common_firmware_header common;
@@ -170,6 +177,7 @@ union amdgpu_firmware_header {
	struct sdma_firmware_header_v1_0 sdma;
	struct sdma_firmware_header_v1_1 sdma_v1_1;
	struct gpu_info_firmware_header_v1_0 gpu_info;
	struct dmcu_firmware_header_v1_0 dmcu;
	uint8_t raw[0x100];
};

@@ -196,6 +204,8 @@ enum AMDGPU_UCODE_ID {
	AMDGPU_UCODE_ID_UVD1,
	AMDGPU_UCODE_ID_VCE,
	AMDGPU_UCODE_ID_VCN,
	AMDGPU_UCODE_ID_DMCU_ERAM,
	AMDGPU_UCODE_ID_DMCU_INTV,
	AMDGPU_UCODE_ID_MAXIMUM,
};