diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 141 | 
1 files changed, 101 insertions, 40 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index bcc9343353b5..81bfee978b74 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -67,7 +67,8 @@  #include "smuio_v11_0_6.h"  #include "smuio_v13_0.h" -MODULE_FIRMWARE("amdgpu/ip_discovery.bin"); +#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin" +MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);  #define mmRCC_CONFIG_MEMSIZE	0xde3  #define mmMM_INDEX		0x0 @@ -179,7 +180,7 @@ static int hw_id_map[MAX_HWIP] = {  	[DCI_HWIP]	= DCI_HWID,  }; -static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary) +static int amdgpu_discovery_read_binary_from_vram(struct amdgpu_device *adev, uint8_t *binary)  {  	uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;  	uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET; @@ -189,6 +190,34 @@ static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *bin  	return 0;  } +static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary) +{ +	const struct firmware *fw; +	const char *fw_name; +	int r; + +	switch (amdgpu_discovery) { +	case 2: +		fw_name = FIRMWARE_IP_DISCOVERY; +		break; +	default: +		dev_warn(adev->dev, "amdgpu_discovery is not set properly\n"); +		return -EINVAL; +	} + +	r = request_firmware(&fw, fw_name, adev->dev); +	if (r) { +		dev_err(adev->dev, "can't load firmware \"%s\"\n", +			fw_name); +		return r; +	} + +	memcpy((u8 *)binary, (u8 *)fw->data, adev->mman.discovery_tmr_size); +	release_firmware(fw); + +	return 0; +} +  static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size)  {  	uint16_t checksum = 0; @@ -206,13 +235,44 @@ static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size  	return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);  } +static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary) +{ +	struct binary_header *bhdr; +	bhdr = (struct binary_header *)binary; + +	return (le32_to_cpu(bhdr->binary_signature) == BINARY_SIGNATURE); +} + +static void amdgpu_discovery_harvest_config_quirk(struct amdgpu_device *adev) +{ +	/* +	 * So far, apply this quirk only on those Navy Flounder boards which +	 * have a bad harvest table of VCN config. +	 */ +	if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) && +		(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2))) { +		switch (adev->pdev->revision) { +		case 0xC1: +		case 0xC2: +		case 0xC3: +		case 0xC5: +		case 0xC7: +		case 0xCF: +		case 0xDF: +			adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1; +			break; +		default: +			break; +		} +	} +} +  static int amdgpu_discovery_init(struct amdgpu_device *adev)  {  	struct table_info *info;  	struct binary_header *bhdr;  	struct ip_discovery_header *ihdr;  	struct gpu_info_header *ghdr; -	const struct firmware *fw;  	uint16_t offset;  	uint16_t size;  	uint16_t checksum; @@ -223,31 +283,32 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)  	if (!adev->mman.discovery_bin)  		return -ENOMEM; -	if (amdgpu_discovery == 2) { -		r = request_firmware(&fw, "amdgpu/ip_discovery.bin", adev->dev); -		if (r) -			goto get_from_vram; -		dev_info(adev->dev, "Using IP discovery from file\n"); -		memcpy((u8 *)adev->mman.discovery_bin, (u8 *)fw->data, -		       adev->mman.discovery_tmr_size); -		release_firmware(fw); -	} else { -get_from_vram: -		r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin); +	r = amdgpu_discovery_read_binary_from_vram(adev, adev->mman.discovery_bin); +	if (r) { +		dev_err(adev->dev, "failed to read ip discovery binary from vram\n"); +		r = -EINVAL; +		goto out; +	} + +	if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) { +		dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n"); +		/* retry read ip discovery binary from file */ +		r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);  		if (r) { -			DRM_ERROR("failed to read ip discovery binary\n"); +			dev_err(adev->dev, "failed to read ip discovery binary from file\n"); +			r = -EINVAL; +			goto out; +		} +		/* check the ip discovery binary signature */ +		if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) { +			dev_warn(adev->dev, "get invalid ip discovery binary signature from file\n"); +			r = -EINVAL;  			goto out;  		}  	}  	bhdr = (struct binary_header *)adev->mman.discovery_bin; -	if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) { -		DRM_ERROR("invalid ip discovery binary signature\n"); -		r = -EINVAL; -		goto out; -	} -  	offset = offsetof(struct binary_header, binary_checksum) +  		sizeof(bhdr->binary_checksum);  	size = le16_to_cpu(bhdr->binary_size) - offset; @@ -255,7 +316,7 @@ get_from_vram:  	if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,  					      size, checksum)) { -		DRM_ERROR("invalid ip discovery binary checksum\n"); +		dev_err(adev->dev, "invalid ip discovery binary checksum\n");  		r = -EINVAL;  		goto out;  	} @@ -266,14 +327,14 @@ get_from_vram:  	ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);  	if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) { -		DRM_ERROR("invalid ip discovery data table signature\n"); +		dev_err(adev->dev, "invalid ip discovery data table signature\n");  		r = -EINVAL;  		goto out;  	}  	if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,  					      le16_to_cpu(ihdr->size), checksum)) { -		DRM_ERROR("invalid ip discovery data table checksum\n"); +		dev_err(adev->dev, "invalid ip discovery data table checksum\n");  		r = -EINVAL;  		goto out;  	} @@ -285,7 +346,7 @@ get_from_vram:  	if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,  				              le32_to_cpu(ghdr->size), checksum)) { -		DRM_ERROR("invalid gc data table checksum\n"); +		dev_err(adev->dev, "invalid gc data table checksum\n");  		r = -EINVAL;  		goto out;  	} @@ -379,8 +440,18 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)  				  ip->major, ip->minor,  				  ip->revision); -			if (le16_to_cpu(ip->hw_id) == VCN_HWID) +			if (le16_to_cpu(ip->hw_id) == VCN_HWID) { +				/* Bit [5:0]: original revision value +				 * Bit [7:6]: en/decode capability: +				 *     0b00 : VCN function normally +				 *     0b10 : encode is disabled +				 *     0b01 : decode is disabled +				 */ +				adev->vcn.vcn_config[adev->vcn.num_vcn_inst] = +					ip->revision & 0xc0; +				ip->revision &= ~0xc0;  				adev->vcn.num_vcn_inst++; +			}  			if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||  			    le16_to_cpu(ip->hw_id) == SDMA1_HWID ||  			    le16_to_cpu(ip->hw_id) == SDMA2_HWID || @@ -472,14 +543,6 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int n  	return -EINVAL;  } - -int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance, -				     int *major, int *minor, int *revision) -{ -	return amdgpu_discovery_get_ip_version(adev, VCN_HWID, -					       vcn_instance, major, minor, revision); -} -  void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)  {  	struct binary_header *bhdr; @@ -509,10 +572,9 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)  			break;  		}  	} -	/* some IP discovery tables on Navy Flounder don't have this set correctly */ -	if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) && -	    (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2))) -		adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1; + +	amdgpu_discovery_harvest_config_quirk(adev); +  	if (vcn_harvest_count == adev->vcn.num_vcn_inst) {  		adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;  		adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK; @@ -949,7 +1011,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)  			break;  		case IP_VERSION(3, 0, 0):  		case IP_VERSION(3, 0, 16): -		case IP_VERSION(3, 0, 64):  		case IP_VERSION(3, 1, 1):  		case IP_VERSION(3, 0, 2):  		case IP_VERSION(3, 0, 192): @@ -986,7 +1047,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)  		amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);  		break;  	default: -		break;; +		break;  	}  	return 0;  }  | 
