diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 142 | 
1 files changed, 137 insertions, 5 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 9a19a6a57b23..f99093f2ebc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -27,6 +27,7 @@  #include <linux/firmware.h>  #include <linux/module.h>  #include <linux/pci.h> +#include <linux/debugfs.h>  #include <drm/drm_drv.h>  #include "amdgpu.h" @@ -51,6 +52,7 @@  #define FIRMWARE_ALDEBARAN	"amdgpu/aldebaran_vcn.bin"  #define FIRMWARE_BEIGE_GOBY	"amdgpu/beige_goby_vcn.bin"  #define FIRMWARE_YELLOW_CARP	"amdgpu/yellow_carp_vcn.bin" +#define FIRMWARE_VCN_3_1_2	"amdgpu/vcn_3_1_2_vcn.bin"  MODULE_FIRMWARE(FIRMWARE_RAVEN);  MODULE_FIRMWARE(FIRMWARE_PICASSO); @@ -68,6 +70,7 @@ MODULE_FIRMWARE(FIRMWARE_VANGOGH);  MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH);  MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY);  MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP); +MODULE_FIRMWARE(FIRMWARE_VCN_3_1_2);  static void amdgpu_vcn_idle_work_handler(struct work_struct *work); @@ -77,6 +80,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)  	const char *fw_name;  	const struct common_firmware_header *hdr;  	unsigned char fw_check; +	unsigned int fw_shared_size, log_offset;  	int i, r;  	INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler); @@ -165,6 +169,12 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)  		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))  			adev->vcn.indirect_sram = true;  		break; +	case IP_VERSION(3, 1, 2): +		fw_name = FIRMWARE_VCN_3_1_2; +		if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && +		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) +			adev->vcn.indirect_sram = true; +		break;  	default:  		return -EINVAL;  	} @@ -218,7 +228,12 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)  	bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;  	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)  		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); -	bo_size += AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); +	fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); +	log_offset = offsetof(struct amdgpu_fw_shared, fw_log); +	bo_size += fw_shared_size; + +	if (amdgpu_vcnfw_log) +		bo_size += AMDGPU_VCNFW_LOG_SIZE;  	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {  		if (adev->vcn.harvest_config & (1 << i)) @@ -232,10 +247,18 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)  			return r;  		} -		adev->vcn.inst[i].fw_shared_cpu_addr = adev->vcn.inst[i].cpu_addr + -				bo_size - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); -		adev->vcn.inst[i].fw_shared_gpu_addr = adev->vcn.inst[i].gpu_addr + -				bo_size - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); +		adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr + +				bo_size - fw_shared_size; +		adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr + +				bo_size - fw_shared_size; + +		adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size; + +		if (amdgpu_vcnfw_log) { +			adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE; +			adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE; +			adev->vcn.inst[i].fw_shared.log_offset = log_offset; +		}  		if (adev->vcn.indirect_sram) {  			r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE, @@ -971,3 +994,112 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)  		dev_info(adev->dev, "Will use PSP to load VCN firmware\n");  	}  } + +/* + * debugfs for mapping vcn firmware log buffer. + */ +#if defined(CONFIG_DEBUG_FS) +static ssize_t amdgpu_debugfs_vcn_fwlog_read(struct file *f, char __user *buf, +                                             size_t size, loff_t *pos) +{ +	struct amdgpu_vcn_inst *vcn; +	void *log_buf; +	volatile struct amdgpu_vcn_fwlog *plog; +	unsigned int read_pos, write_pos, available, i, read_bytes = 0; +	unsigned int read_num[2] = {0}; + +	vcn = file_inode(f)->i_private; +	if (!vcn) +		return -ENODEV; + +	if (!vcn->fw_shared.cpu_addr || !amdgpu_vcnfw_log) +		return -EFAULT; + +	log_buf = vcn->fw_shared.cpu_addr + vcn->fw_shared.mem_size; + +	plog = (volatile struct amdgpu_vcn_fwlog *)log_buf; +	read_pos = plog->rptr; +	write_pos = plog->wptr; + +	if (read_pos > AMDGPU_VCNFW_LOG_SIZE || write_pos > AMDGPU_VCNFW_LOG_SIZE) +		return -EFAULT; + +	if (!size || (read_pos == write_pos)) +		return 0; + +	if (write_pos > read_pos) { +		available = write_pos - read_pos; +		read_num[0] = min(size, (size_t)available); +	} else { +		read_num[0] = AMDGPU_VCNFW_LOG_SIZE - read_pos; +		available = read_num[0] + write_pos - plog->header_size; +		if (size > available) +			read_num[1] = write_pos - plog->header_size; +		else if (size > read_num[0]) +			read_num[1] = size - read_num[0]; +		else +			read_num[0] = size; +	} + +	for (i = 0; i < 2; i++) { +		if (read_num[i]) { +			if (read_pos == AMDGPU_VCNFW_LOG_SIZE) +				read_pos = plog->header_size; +			if (read_num[i] == copy_to_user((buf + read_bytes), +			                                (log_buf + read_pos), read_num[i])) +				return -EFAULT; + +			read_bytes += read_num[i]; +			read_pos += read_num[i]; +		} +	} + +	plog->rptr = read_pos; +	*pos += read_bytes; +	return read_bytes; +} + +static const struct file_operations amdgpu_debugfs_vcnfwlog_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_vcn_fwlog_read, +	.llseek = default_llseek +}; +#endif + +void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, uint8_t i, +                                   struct amdgpu_vcn_inst *vcn) +{ +#if defined(CONFIG_DEBUG_FS) +	struct drm_minor *minor = adev_to_drm(adev)->primary; +	struct dentry *root = minor->debugfs_root; +	char name[32]; + +	sprintf(name, "amdgpu_vcn_%d_fwlog", i); +	debugfs_create_file_size(name, S_IFREG | S_IRUGO, root, vcn, +				 &amdgpu_debugfs_vcnfwlog_fops, +				 AMDGPU_VCNFW_LOG_SIZE); +#endif +} + +void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn) +{ +#if defined(CONFIG_DEBUG_FS) +	volatile uint32_t *flag = vcn->fw_shared.cpu_addr; +	void *fw_log_cpu_addr = vcn->fw_shared.cpu_addr + vcn->fw_shared.mem_size; +	uint64_t fw_log_gpu_addr = vcn->fw_shared.gpu_addr + vcn->fw_shared.mem_size; +	volatile struct amdgpu_vcn_fwlog *log_buf = fw_log_cpu_addr; +	volatile struct amdgpu_fw_shared_fw_logging *fw_log = vcn->fw_shared.cpu_addr +                                                         + vcn->fw_shared.log_offset; +	*flag |= cpu_to_le32(AMDGPU_VCN_FW_LOGGING_FLAG); +	fw_log->is_enabled = 1; +	fw_log->addr_lo = cpu_to_le32(fw_log_gpu_addr & 0xFFFFFFFF); +	fw_log->addr_hi = cpu_to_le32(fw_log_gpu_addr >> 32); +	fw_log->size = cpu_to_le32(AMDGPU_VCNFW_LOG_SIZE); + +	log_buf->header_size = sizeof(struct amdgpu_vcn_fwlog); +	log_buf->buffer_size = AMDGPU_VCNFW_LOG_SIZE; +	log_buf->rptr = log_buf->header_size; +	log_buf->wptr = log_buf->header_size; +	log_buf->wrapped = 0; +#endif +} | 
