18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2013 Advanced Micro Devices, Inc.
38c2ecf20Sopenharmony_ci * All Rights Reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
68c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the
78c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
88c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
98c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
108c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
118c2ecf20Sopenharmony_ci * the following conditions:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
148c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
158c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
168c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
178c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
188c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
198c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the
228c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
238c2ecf20Sopenharmony_ci * of the Software.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * Authors: Christian König <christian.koenig@amd.com>
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include <linux/firmware.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include "radeon.h"
318c2ecf20Sopenharmony_ci#include "radeon_asic.h"
328c2ecf20Sopenharmony_ci#include "sid.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define VCE_V1_0_FW_SIZE	(256 * 1024)
358c2ecf20Sopenharmony_ci#define VCE_V1_0_STACK_SIZE	(64 * 1024)
368c2ecf20Sopenharmony_ci#define VCE_V1_0_DATA_SIZE	(7808 * (RADEON_MAX_VCE_HANDLES + 1))
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistruct vce_v1_0_fw_signature
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	int32_t off;
418c2ecf20Sopenharmony_ci	uint32_t len;
428c2ecf20Sopenharmony_ci	int32_t num;
438c2ecf20Sopenharmony_ci	struct {
448c2ecf20Sopenharmony_ci		uint32_t chip_id;
458c2ecf20Sopenharmony_ci		uint32_t keyselect;
468c2ecf20Sopenharmony_ci		uint32_t nonce[4];
478c2ecf20Sopenharmony_ci		uint32_t sigval[4];
488c2ecf20Sopenharmony_ci	} val[8];
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/**
528c2ecf20Sopenharmony_ci * vce_v1_0_get_rptr - get read pointer
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer
558c2ecf20Sopenharmony_ci * @ring: radeon_ring pointer
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * Returns the current hardware read pointer
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_ciuint32_t vce_v1_0_get_rptr(struct radeon_device *rdev,
608c2ecf20Sopenharmony_ci			   struct radeon_ring *ring)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
638c2ecf20Sopenharmony_ci		return RREG32(VCE_RB_RPTR);
648c2ecf20Sopenharmony_ci	else
658c2ecf20Sopenharmony_ci		return RREG32(VCE_RB_RPTR2);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/**
698c2ecf20Sopenharmony_ci * vce_v1_0_get_wptr - get write pointer
708c2ecf20Sopenharmony_ci *
718c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer
728c2ecf20Sopenharmony_ci * @ring: radeon_ring pointer
738c2ecf20Sopenharmony_ci *
748c2ecf20Sopenharmony_ci * Returns the current hardware write pointer
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_ciuint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
778c2ecf20Sopenharmony_ci			   struct radeon_ring *ring)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
808c2ecf20Sopenharmony_ci		return RREG32(VCE_RB_WPTR);
818c2ecf20Sopenharmony_ci	else
828c2ecf20Sopenharmony_ci		return RREG32(VCE_RB_WPTR2);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci/**
868c2ecf20Sopenharmony_ci * vce_v1_0_set_wptr - set write pointer
878c2ecf20Sopenharmony_ci *
888c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer
898c2ecf20Sopenharmony_ci * @ring: radeon_ring pointer
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci * Commits the write pointer to the hardware
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_civoid vce_v1_0_set_wptr(struct radeon_device *rdev,
948c2ecf20Sopenharmony_ci		       struct radeon_ring *ring)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
978c2ecf20Sopenharmony_ci		WREG32(VCE_RB_WPTR, ring->wptr);
988c2ecf20Sopenharmony_ci	else
998c2ecf20Sopenharmony_ci		WREG32(VCE_RB_WPTR2, ring->wptr);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_civoid vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	u32 tmp;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) {
1078c2ecf20Sopenharmony_ci		tmp = RREG32(VCE_CLOCK_GATING_A);
1088c2ecf20Sopenharmony_ci		tmp |= CGC_DYN_CLOCK_MODE;
1098c2ecf20Sopenharmony_ci		WREG32(VCE_CLOCK_GATING_A, tmp);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci		tmp = RREG32(VCE_UENC_CLOCK_GATING);
1128c2ecf20Sopenharmony_ci		tmp &= ~0x1ff000;
1138c2ecf20Sopenharmony_ci		tmp |= 0xff800000;
1148c2ecf20Sopenharmony_ci		WREG32(VCE_UENC_CLOCK_GATING, tmp);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci		tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
1178c2ecf20Sopenharmony_ci		tmp &= ~0x3ff;
1188c2ecf20Sopenharmony_ci		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
1198c2ecf20Sopenharmony_ci	} else {
1208c2ecf20Sopenharmony_ci		tmp = RREG32(VCE_CLOCK_GATING_A);
1218c2ecf20Sopenharmony_ci		tmp &= ~CGC_DYN_CLOCK_MODE;
1228c2ecf20Sopenharmony_ci		WREG32(VCE_CLOCK_GATING_A, tmp);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci		tmp = RREG32(VCE_UENC_CLOCK_GATING);
1258c2ecf20Sopenharmony_ci		tmp |= 0x1ff000;
1268c2ecf20Sopenharmony_ci		tmp &= ~0xff800000;
1278c2ecf20Sopenharmony_ci		WREG32(VCE_UENC_CLOCK_GATING, tmp);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci		tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
1308c2ecf20Sopenharmony_ci		tmp |= 0x3ff;
1318c2ecf20Sopenharmony_ci		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic void vce_v1_0_init_cg(struct radeon_device *rdev)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	u32 tmp;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	tmp = RREG32(VCE_CLOCK_GATING_A);
1408c2ecf20Sopenharmony_ci	tmp |= CGC_DYN_CLOCK_MODE;
1418c2ecf20Sopenharmony_ci	WREG32(VCE_CLOCK_GATING_A, tmp);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	tmp = RREG32(VCE_CLOCK_GATING_B);
1448c2ecf20Sopenharmony_ci	tmp |= 0x1e;
1458c2ecf20Sopenharmony_ci	tmp &= ~0xe100e1;
1468c2ecf20Sopenharmony_ci	WREG32(VCE_CLOCK_GATING_B, tmp);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	tmp = RREG32(VCE_UENC_CLOCK_GATING);
1498c2ecf20Sopenharmony_ci	tmp &= ~0xff9ff000;
1508c2ecf20Sopenharmony_ci	WREG32(VCE_UENC_CLOCK_GATING, tmp);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
1538c2ecf20Sopenharmony_ci	tmp &= ~0x3ff;
1548c2ecf20Sopenharmony_ci	WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ciint vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct vce_v1_0_fw_signature *sign = (void*)rdev->vce_fw->data;
1608c2ecf20Sopenharmony_ci	uint32_t chip_id;
1618c2ecf20Sopenharmony_ci	int i;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	switch (rdev->family) {
1648c2ecf20Sopenharmony_ci	case CHIP_TAHITI:
1658c2ecf20Sopenharmony_ci		chip_id = 0x01000014;
1668c2ecf20Sopenharmony_ci		break;
1678c2ecf20Sopenharmony_ci	case CHIP_VERDE:
1688c2ecf20Sopenharmony_ci		chip_id = 0x01000015;
1698c2ecf20Sopenharmony_ci		break;
1708c2ecf20Sopenharmony_ci	case CHIP_PITCAIRN:
1718c2ecf20Sopenharmony_ci		chip_id = 0x01000016;
1728c2ecf20Sopenharmony_ci		break;
1738c2ecf20Sopenharmony_ci	case CHIP_ARUBA:
1748c2ecf20Sopenharmony_ci		chip_id = 0x01000017;
1758c2ecf20Sopenharmony_ci		break;
1768c2ecf20Sopenharmony_ci	default:
1778c2ecf20Sopenharmony_ci		return -EINVAL;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	for (i = 0; i < le32_to_cpu(sign->num); ++i) {
1818c2ecf20Sopenharmony_ci		if (le32_to_cpu(sign->val[i].chip_id) == chip_id)
1828c2ecf20Sopenharmony_ci			break;
1838c2ecf20Sopenharmony_ci	}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (i == le32_to_cpu(sign->num))
1868c2ecf20Sopenharmony_ci		return -EINVAL;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	data += (256 - 64) / 4;
1898c2ecf20Sopenharmony_ci	data[0] = sign->val[i].nonce[0];
1908c2ecf20Sopenharmony_ci	data[1] = sign->val[i].nonce[1];
1918c2ecf20Sopenharmony_ci	data[2] = sign->val[i].nonce[2];
1928c2ecf20Sopenharmony_ci	data[3] = sign->val[i].nonce[3];
1938c2ecf20Sopenharmony_ci	data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	memset(&data[5], 0, 44);
1968c2ecf20Sopenharmony_ci	memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign));
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	data += (le32_to_cpu(sign->len) + 64) / 4;
1998c2ecf20Sopenharmony_ci	data[0] = sign->val[i].sigval[0];
2008c2ecf20Sopenharmony_ci	data[1] = sign->val[i].sigval[1];
2018c2ecf20Sopenharmony_ci	data[2] = sign->val[i].sigval[2];
2028c2ecf20Sopenharmony_ci	data[3] = sign->val[i].sigval[3];
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	rdev->vce.keyselect = le32_to_cpu(sign->val[i].keyselect);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	return 0;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ciunsigned vce_v1_0_bo_size(struct radeon_device *rdev)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	WARN_ON(VCE_V1_0_FW_SIZE < rdev->vce_fw->size);
2128c2ecf20Sopenharmony_ci	return VCE_V1_0_FW_SIZE + VCE_V1_0_STACK_SIZE + VCE_V1_0_DATA_SIZE;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ciint vce_v1_0_resume(struct radeon_device *rdev)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	uint64_t addr = rdev->vce.gpu_addr;
2188c2ecf20Sopenharmony_ci	uint32_t size;
2198c2ecf20Sopenharmony_ci	int i;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16));
2228c2ecf20Sopenharmony_ci	WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
2238c2ecf20Sopenharmony_ci	WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
2248c2ecf20Sopenharmony_ci	WREG32(VCE_CLOCK_GATING_B, 0);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	WREG32_P(VCE_LMI_FW_PERIODIC_CTRL, 0x4, ~0x4);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	WREG32(VCE_LMI_CTRL, 0x00398000);
2298c2ecf20Sopenharmony_ci	WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1);
2308c2ecf20Sopenharmony_ci	WREG32(VCE_LMI_SWAP_CNTL, 0);
2318c2ecf20Sopenharmony_ci	WREG32(VCE_LMI_SWAP_CNTL1, 0);
2328c2ecf20Sopenharmony_ci	WREG32(VCE_LMI_VM_CTRL, 0);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_SCRATCH7, RADEON_MAX_VCE_HANDLES);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	addr += 256;
2378c2ecf20Sopenharmony_ci	size = VCE_V1_0_FW_SIZE;
2388c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
2398c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_CACHE_SIZE0, size);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	addr += size;
2428c2ecf20Sopenharmony_ci	size = VCE_V1_0_STACK_SIZE;
2438c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
2448c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_CACHE_SIZE1, size);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	addr += size;
2478c2ecf20Sopenharmony_ci	size = VCE_V1_0_DATA_SIZE;
2488c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
2498c2ecf20Sopenharmony_ci	WREG32(VCE_VCPU_CACHE_SIZE2, size);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	WREG32(VCE_LMI_FW_START_KEYSEL, rdev->vce.keyselect);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	for (i = 0; i < 10; ++i) {
2568c2ecf20Sopenharmony_ci		mdelay(10);
2578c2ecf20Sopenharmony_ci		if (RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_DONE)
2588c2ecf20Sopenharmony_ci			break;
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	if (i == 10)
2628c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_PASS))
2658c2ecf20Sopenharmony_ci		return -EINVAL;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	for (i = 0; i < 10; ++i) {
2688c2ecf20Sopenharmony_ci		mdelay(10);
2698c2ecf20Sopenharmony_ci		if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_BUSY))
2708c2ecf20Sopenharmony_ci			break;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	if (i == 10)
2748c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	vce_v1_0_init_cg(rdev);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	return 0;
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci/**
2828c2ecf20Sopenharmony_ci * vce_v1_0_start - start VCE block
2838c2ecf20Sopenharmony_ci *
2848c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer
2858c2ecf20Sopenharmony_ci *
2868c2ecf20Sopenharmony_ci * Setup and start the VCE block
2878c2ecf20Sopenharmony_ci */
2888c2ecf20Sopenharmony_ciint vce_v1_0_start(struct radeon_device *rdev)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	struct radeon_ring *ring;
2918c2ecf20Sopenharmony_ci	int i, j, r;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/* set BUSY flag */
2948c2ecf20Sopenharmony_ci	WREG32_P(VCE_STATUS, 1, ~1);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
2978c2ecf20Sopenharmony_ci	WREG32(VCE_RB_RPTR, ring->wptr);
2988c2ecf20Sopenharmony_ci	WREG32(VCE_RB_WPTR, ring->wptr);
2998c2ecf20Sopenharmony_ci	WREG32(VCE_RB_BASE_LO, ring->gpu_addr);
3008c2ecf20Sopenharmony_ci	WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
3018c2ecf20Sopenharmony_ci	WREG32(VCE_RB_SIZE, ring->ring_size / 4);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
3048c2ecf20Sopenharmony_ci	WREG32(VCE_RB_RPTR2, ring->wptr);
3058c2ecf20Sopenharmony_ci	WREG32(VCE_RB_WPTR2, ring->wptr);
3068c2ecf20Sopenharmony_ci	WREG32(VCE_RB_BASE_LO2, ring->gpu_addr);
3078c2ecf20Sopenharmony_ci	WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
3088c2ecf20Sopenharmony_ci	WREG32(VCE_RB_SIZE2, ring->ring_size / 4);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	WREG32_P(VCE_SOFT_RESET,
3138c2ecf20Sopenharmony_ci		 VCE_ECPU_SOFT_RESET |
3148c2ecf20Sopenharmony_ci		 VCE_FME_SOFT_RESET, ~(
3158c2ecf20Sopenharmony_ci		 VCE_ECPU_SOFT_RESET |
3168c2ecf20Sopenharmony_ci		 VCE_FME_SOFT_RESET));
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	mdelay(100);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	WREG32_P(VCE_SOFT_RESET, 0, ~(
3218c2ecf20Sopenharmony_ci		 VCE_ECPU_SOFT_RESET |
3228c2ecf20Sopenharmony_ci		 VCE_FME_SOFT_RESET));
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	for (i = 0; i < 10; ++i) {
3258c2ecf20Sopenharmony_ci		uint32_t status;
3268c2ecf20Sopenharmony_ci		for (j = 0; j < 100; ++j) {
3278c2ecf20Sopenharmony_ci			status = RREG32(VCE_STATUS);
3288c2ecf20Sopenharmony_ci			if (status & 2)
3298c2ecf20Sopenharmony_ci				break;
3308c2ecf20Sopenharmony_ci			mdelay(10);
3318c2ecf20Sopenharmony_ci		}
3328c2ecf20Sopenharmony_ci		r = 0;
3338c2ecf20Sopenharmony_ci		if (status & 2)
3348c2ecf20Sopenharmony_ci			break;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci		DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
3378c2ecf20Sopenharmony_ci		WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET);
3388c2ecf20Sopenharmony_ci		mdelay(10);
3398c2ecf20Sopenharmony_ci		WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET);
3408c2ecf20Sopenharmony_ci		mdelay(10);
3418c2ecf20Sopenharmony_ci		r = -1;
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	/* clear BUSY flag */
3458c2ecf20Sopenharmony_ci	WREG32_P(VCE_STATUS, 0, ~1);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	if (r) {
3488c2ecf20Sopenharmony_ci		DRM_ERROR("VCE not responding, giving up!!!\n");
3498c2ecf20Sopenharmony_ci		return r;
3508c2ecf20Sopenharmony_ci	}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	return 0;
3538c2ecf20Sopenharmony_ci}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ciint vce_v1_0_init(struct radeon_device *rdev)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	struct radeon_ring *ring;
3588c2ecf20Sopenharmony_ci	int r;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	r = vce_v1_0_start(rdev);
3618c2ecf20Sopenharmony_ci	if (r)
3628c2ecf20Sopenharmony_ci		return r;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
3658c2ecf20Sopenharmony_ci	ring->ready = true;
3668c2ecf20Sopenharmony_ci	r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring);
3678c2ecf20Sopenharmony_ci	if (r) {
3688c2ecf20Sopenharmony_ci		ring->ready = false;
3698c2ecf20Sopenharmony_ci		return r;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
3738c2ecf20Sopenharmony_ci	ring->ready = true;
3748c2ecf20Sopenharmony_ci	r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring);
3758c2ecf20Sopenharmony_ci	if (r) {
3768c2ecf20Sopenharmony_ci		ring->ready = false;
3778c2ecf20Sopenharmony_ci		return r;
3788c2ecf20Sopenharmony_ci	}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	DRM_INFO("VCE initialized successfully.\n");
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	return 0;
3838c2ecf20Sopenharmony_ci}
384