[PATCH 1/3] drm/amd: Add ucode DMCU support

Huang Rui ray.huang at amd.com
Thu Sep 13 07:16:48 UTC 2018


On Tue, Sep 11, 2018 at 03:15:11PM -0400, David Francis wrote:
> 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: David Francis <David.Francis at amd.com>

Reviewed-by: Huang Rui <ray.huang at amd.com>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 21 +++++++++++++++++++--
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 10 ++++++++++
>  2 files changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
> index a942fd28dae8..3b1af1cecf14 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
> @@ -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) * 4;
> +
> +		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) * 4;
> +
> +		memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
> +					      le32_to_cpu(header->ucode_array_offset_bytes) +
> +					      le32_to_cpu(dmcu_hdr->intv_offset) * 4),
> +		       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,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
> index b358e7519987..13bd540709b6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
> @@ -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; /* interrupt vectors offset from end of header, in words */
> +	uint32_t intv_size;  /* size of interrupt vectors, in words */
> +};
> +
>  /* 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,
>  };
>  
> -- 
> 2.17.1
> 
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list