1250 lines · 30.3 KB · C
RawDownload
/* * Copyright 2011 Advanced Micro Devices, Inc. * All Rights Reserved. * * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * *//* * Authors: *    Christian König <deathsimple@vodafone.de> */ #include <linux/firmware.h>#include <linux/module.h>#include <drm/drmP.h>#include <drm/drm.h> #include "amdgpu.h"#include "amdgpu_pm.h"#include "amdgpu_uvd.h"#include "cikd.h"#include "uvd/uvd_4_2_d.h" /* 1 second timeout */#define UVD_IDLE_TIMEOUT	msecs_to_jiffies(1000) /* Firmware versions for VI */#define FW_1_65_10	((1 << 24) | (65 << 16) | (10 << 8))#define FW_1_87_11	((1 << 24) | (87 << 16) | (11 << 8))#define FW_1_87_12	((1 << 24) | (87 << 16) | (12 << 8))#define FW_1_37_15	((1 << 24) | (37 << 16) | (15 << 8)) /* Polaris10/11 firmware version */#define FW_1_66_16	((1 << 24) | (66 << 16) | (16 << 8)) /* Firmware Names */#ifdef CONFIG_DRM_AMDGPU_CIK#define FIRMWARE_BONAIRE	"radeon/bonaire_uvd.bin"#define FIRMWARE_KABINI	"radeon/kabini_uvd.bin"#define FIRMWARE_KAVERI	"radeon/kaveri_uvd.bin"#define FIRMWARE_HAWAII	"radeon/hawaii_uvd.bin"#define FIRMWARE_MULLINS	"radeon/mullins_uvd.bin"#endif#define FIRMWARE_TONGA		"amdgpu/tonga_uvd.bin"#define FIRMWARE_CARRIZO	"amdgpu/carrizo_uvd.bin"#define FIRMWARE_FIJI		"amdgpu/fiji_uvd.bin"#define FIRMWARE_STONEY		"amdgpu/stoney_uvd.bin"#define FIRMWARE_POLARIS10	"amdgpu/polaris10_uvd.bin"#define FIRMWARE_POLARIS11	"amdgpu/polaris11_uvd.bin"#define FIRMWARE_POLARIS12	"amdgpu/polaris12_uvd.bin" #define FIRMWARE_VEGA10		"amdgpu/vega10_uvd.bin" #define mmUVD_GPCOM_VCPU_DATA0_VEGA10 (0x03c4 + 0x7e00)#define mmUVD_GPCOM_VCPU_DATA1_VEGA10 (0x03c5 + 0x7e00)#define mmUVD_GPCOM_VCPU_CMD_VEGA10 (0x03c3 + 0x7e00)#define mmUVD_NO_OP_VEGA10 (0x03ff + 0x7e00)#define mmUVD_ENGINE_CNTL_VEGA10 (0x03c6 + 0x7e00) /** * amdgpu_uvd_cs_ctx - Command submission parser context * * Used for emulating virtual memory support on UVD 4.2. */struct amdgpu_uvd_cs_ctx {	struct amdgpu_cs_parser *parser;	unsigned reg, count;	unsigned data0, data1;	unsigned idx;	unsigned ib_idx; 	/* does the IB has a msg command */	bool has_msg_cmd; 	/* minimum buffer sizes */	unsigned *buf_sizes;}; #ifdef CONFIG_DRM_AMDGPU_CIKMODULE_FIRMWARE(FIRMWARE_BONAIRE);MODULE_FIRMWARE(FIRMWARE_KABINI);MODULE_FIRMWARE(FIRMWARE_KAVERI);MODULE_FIRMWARE(FIRMWARE_HAWAII);MODULE_FIRMWARE(FIRMWARE_MULLINS);#endifMODULE_FIRMWARE(FIRMWARE_TONGA);MODULE_FIRMWARE(FIRMWARE_CARRIZO);MODULE_FIRMWARE(FIRMWARE_FIJI);MODULE_FIRMWARE(FIRMWARE_STONEY);MODULE_FIRMWARE(FIRMWARE_POLARIS10);MODULE_FIRMWARE(FIRMWARE_POLARIS11);MODULE_FIRMWARE(FIRMWARE_POLARIS12); MODULE_FIRMWARE(FIRMWARE_VEGA10); static void amdgpu_uvd_idle_work_handler(struct work_struct *work); int amdgpu_uvd_sw_init(struct amdgpu_device *adev){	struct amdgpu_ring *ring;	struct amd_sched_rq *rq;	unsigned long bo_size;	const char *fw_name;	const struct common_firmware_header *hdr;	unsigned version_major, version_minor, family_id;	int i, r; 	INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler); 	switch (adev->asic_type) {#ifdef CONFIG_DRM_AMDGPU_CIK	case CHIP_BONAIRE:		fw_name = FIRMWARE_BONAIRE;		break;	case CHIP_KABINI:		fw_name = FIRMWARE_KABINI;		break;	case CHIP_KAVERI:		fw_name = FIRMWARE_KAVERI;		break;	case CHIP_HAWAII:		fw_name = FIRMWARE_HAWAII;		break;	case CHIP_MULLINS:		fw_name = FIRMWARE_MULLINS;		break;#endif	case CHIP_TONGA:		fw_name = FIRMWARE_TONGA;		break;	case CHIP_FIJI:		fw_name = FIRMWARE_FIJI;		break;	case CHIP_CARRIZO:		fw_name = FIRMWARE_CARRIZO;		break;	case CHIP_STONEY:		fw_name = FIRMWARE_STONEY;		break;	case CHIP_POLARIS10:		fw_name = FIRMWARE_POLARIS10;		break;	case CHIP_POLARIS11:		fw_name = FIRMWARE_POLARIS11;		break;	case CHIP_VEGA10:		fw_name = FIRMWARE_VEGA10;		break;	case CHIP_POLARIS12:		fw_name = FIRMWARE_POLARIS12;		break;	default:		return -EINVAL;	} 	r = request_firmware(&adev->uvd.fw, fw_name, adev->dev);	if (r) {		dev_err(adev->dev, "amdgpu_uvd: Can't load firmware \"%s\"\n",			fw_name);		return r;	} 	r = amdgpu_ucode_validate(adev->uvd.fw);	if (r) {		dev_err(adev->dev, "amdgpu_uvd: Can't validate firmware \"%s\"\n",			fw_name);		release_firmware(adev->uvd.fw);		adev->uvd.fw = NULL;		return r;	} 	/* Set the default UVD handles that the firmware can handle */	adev->uvd.max_handles = AMDGPU_DEFAULT_UVD_HANDLES; 	hdr = (const struct common_firmware_header *)adev->uvd.fw->data;	family_id = le32_to_cpu(hdr->ucode_version) & 0xff;	version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;	version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;	DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",		version_major, version_minor, family_id); 	/*	 * Limit the number of UVD handles depending on microcode major	 * and minor versions. The firmware version which has 40 UVD	 * instances support is 1.80. So all subsequent versions should	 * also have the same support.	 */	if ((version_major > 0x01) ||	    ((version_major == 0x01) && (version_minor >= 0x50)))		adev->uvd.max_handles = AMDGPU_MAX_UVD_HANDLES; 	adev->uvd.fw_version = ((version_major << 24) | (version_minor << 16) |				(family_id << 8)); 	if ((adev->asic_type == CHIP_POLARIS10 ||	     adev->asic_type == CHIP_POLARIS11) &&	    (adev->uvd.fw_version < FW_1_66_16))		DRM_ERROR("POLARIS10/11 UVD firmware version %hu.%hu is too old.\n",			  version_major, version_minor); 	bo_size = AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE		  +  AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles;	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); 	r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,				    AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.vcpu_bo,				    &adev->uvd.gpu_addr, &adev->uvd.cpu_addr);	if (r) {		dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);		return r;	} 	ring = &adev->uvd.ring;	rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL];	r = amd_sched_entity_init(&ring->sched, &adev->uvd.entity,				  rq, amdgpu_sched_jobs);	if (r != 0) {		DRM_ERROR("Failed setting up UVD run queue.\n");		return r;	} 	for (i = 0; i < adev->uvd.max_handles; ++i) {		atomic_set(&adev->uvd.handles[i], 0);		adev->uvd.filp[i] = NULL;	} 	/* from uvd v5.0 HW addressing capacity increased to 64 bits */	if (!amdgpu_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))		adev->uvd.address_64_bit = true; 	switch (adev->asic_type) {	case CHIP_TONGA:		adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_65_10;		break;	case CHIP_CARRIZO:		adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_87_11;		break;	case CHIP_FIJI:		adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_87_12;		break;	case CHIP_STONEY:		adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_37_15;		break;	default:		adev->uvd.use_ctx_buf = adev->asic_type >= CHIP_POLARIS10;	} 	return 0;} int amdgpu_uvd_sw_fini(struct amdgpu_device *adev){	kfree(adev->uvd.saved_bo); 	amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity); 	amdgpu_bo_free_kernel(&adev->uvd.vcpu_bo,			      &adev->uvd.gpu_addr,			      (void **)&adev->uvd.cpu_addr); 	amdgpu_ring_fini(&adev->uvd.ring); 	release_firmware(adev->uvd.fw); 	return 0;} int amdgpu_uvd_suspend(struct amdgpu_device *adev){	unsigned size;	void *ptr;	int i; 	if (adev->uvd.vcpu_bo == NULL)		return 0; 	for (i = 0; i < adev->uvd.max_handles; ++i)		if (atomic_read(&adev->uvd.handles[i]))			break; 	if (i == AMDGPU_MAX_UVD_HANDLES)		return 0; 	cancel_delayed_work_sync(&adev->uvd.idle_work); 	size = amdgpu_bo_size(adev->uvd.vcpu_bo);	ptr = adev->uvd.cpu_addr; 	adev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);	if (!adev->uvd.saved_bo)		return -ENOMEM; 	memcpy_fromio(adev->uvd.saved_bo, ptr, size); 	return 0;} int amdgpu_uvd_resume(struct amdgpu_device *adev){	unsigned size;	void *ptr; 	if (adev->uvd.vcpu_bo == NULL)		return -EINVAL; 	size = amdgpu_bo_size(adev->uvd.vcpu_bo);	ptr = adev->uvd.cpu_addr; 	if (adev->uvd.saved_bo != NULL) {		memcpy_toio(ptr, adev->uvd.saved_bo, size);		kfree(adev->uvd.saved_bo);		adev->uvd.saved_bo = NULL;	} else {		const struct common_firmware_header *hdr;		unsigned offset; 		hdr = (const struct common_firmware_header *)adev->uvd.fw->data;		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {			offset = le32_to_cpu(hdr->ucode_array_offset_bytes);			memcpy_toio(adev->uvd.cpu_addr, adev->uvd.fw->data + offset,				    le32_to_cpu(hdr->ucode_size_bytes));			size -= le32_to_cpu(hdr->ucode_size_bytes);			ptr += le32_to_cpu(hdr->ucode_size_bytes);		}		memset_io(ptr, 0, size);	} 	return 0;} void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp){	struct amdgpu_ring *ring = &adev->uvd.ring;	int i, r; 	for (i = 0; i < adev->uvd.max_handles; ++i) {		uint32_t handle = atomic_read(&adev->uvd.handles[i]);		if (handle != 0 && adev->uvd.filp[i] == filp) {			struct dma_fence *fence; 			r = amdgpu_uvd_get_destroy_msg(ring, handle,						       false, &fence);			if (r) {				DRM_ERROR("Error destroying UVD (%d)!\n", r);				continue;			} 			dma_fence_wait(fence, false);			dma_fence_put(fence); 			adev->uvd.filp[i] = NULL;			atomic_set(&adev->uvd.handles[i], 0);		}	}} static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo){	int i;	for (i = 0; i < abo->placement.num_placement; ++i) {		abo->placements[i].fpfn = 0 >> PAGE_SHIFT;		abo->placements[i].lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;	}} static u64 amdgpu_uvd_get_addr_from_ctx(struct amdgpu_uvd_cs_ctx *ctx){	uint32_t lo, hi;	uint64_t addr; 	lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);	hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);	addr = ((uint64_t)lo) | (((uint64_t)hi) << 32); 	return addr;} /** * amdgpu_uvd_cs_pass1 - first parsing round * * @ctx: UVD parser context * * Make sure UVD message and feedback buffers are in VRAM and * nobody is violating an 256MB boundary. */static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx){	struct amdgpu_bo_va_mapping *mapping;	struct amdgpu_bo *bo;	uint32_t cmd;	uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx);	int r = 0; 	mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo);	if (mapping == NULL) {		DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);		return -EINVAL;	} 	if (!ctx->parser->adev->uvd.address_64_bit) {		/* check if it's a message or feedback command */		cmd = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->idx) >> 1;		if (cmd == 0x0 || cmd == 0x3) {			/* yes, force it into VRAM */			uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM;			amdgpu_ttm_placement_from_domain(bo, domain);		}		amdgpu_uvd_force_into_uvd_segment(bo); 		r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);	} 	return r;} /** * amdgpu_uvd_cs_msg_decode - handle UVD decode message * * @msg: pointer to message structure * @buf_sizes: returned buffer sizes * * Peek into the decode message and calculate the necessary buffer sizes. */static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,	unsigned buf_sizes[]){	unsigned stream_type = msg[4];	unsigned width = msg[6];	unsigned height = msg[7];	unsigned dpb_size = msg[9];	unsigned pitch = msg[28];	unsigned level = msg[57]; 	unsigned width_in_mb = width / 16;	unsigned height_in_mb = ALIGN(height / 16, 2);	unsigned fs_in_mb = width_in_mb * height_in_mb; 	unsigned image_size, tmp, min_dpb_size, num_dpb_buffer;	unsigned min_ctx_size = ~0; 	image_size = width * height;	image_size += image_size / 2;	image_size = ALIGN(image_size, 1024); 	switch (stream_type) {	case 0: /* H264 */		switch(level) {		case 30:			num_dpb_buffer = 8100 / fs_in_mb;			break;		case 31:			num_dpb_buffer = 18000 / fs_in_mb;			break;		case 32:			num_dpb_buffer = 20480 / fs_in_mb;			break;		case 41:			num_dpb_buffer = 32768 / fs_in_mb;			break;		case 42:			num_dpb_buffer = 34816 / fs_in_mb;			break;		case 50:			num_dpb_buffer = 110400 / fs_in_mb;			break;		case 51:			num_dpb_buffer = 184320 / fs_in_mb;			break;		default:			num_dpb_buffer = 184320 / fs_in_mb;			break;		}		num_dpb_buffer++;		if (num_dpb_buffer > 17)			num_dpb_buffer = 17; 		/* reference picture buffer */		min_dpb_size = image_size * num_dpb_buffer; 		/* macroblock context buffer */		min_dpb_size += width_in_mb * height_in_mb * num_dpb_buffer * 192;

Lines 1–500 of 1250.