31,6 → 31,23 |
#include "radeon_asic.h" |
#include "sid.h" |
|
#define VCE_V1_0_FW_SIZE (256 * 1024) |
#define VCE_V1_0_STACK_SIZE (64 * 1024) |
#define VCE_V1_0_DATA_SIZE (7808 * (RADEON_MAX_VCE_HANDLES + 1)) |
|
struct vce_v1_0_fw_signature |
{ |
int32_t off; |
uint32_t len; |
int32_t num; |
struct { |
uint32_t chip_id; |
uint32_t keyselect; |
uint32_t nonce[4]; |
uint32_t sigval[4]; |
} val[8]; |
}; |
|
/** |
* vce_v1_0_get_rptr - get read pointer |
* |
82,6 → 99,186 |
WREG32(VCE_RB_WPTR2, ring->wptr); |
} |
|
void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable) |
{ |
u32 tmp; |
|
if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) { |
tmp = RREG32(VCE_CLOCK_GATING_A); |
tmp |= CGC_DYN_CLOCK_MODE; |
WREG32(VCE_CLOCK_GATING_A, tmp); |
|
tmp = RREG32(VCE_UENC_CLOCK_GATING); |
tmp &= ~0x1ff000; |
tmp |= 0xff800000; |
WREG32(VCE_UENC_CLOCK_GATING, tmp); |
|
tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); |
tmp &= ~0x3ff; |
WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); |
} else { |
tmp = RREG32(VCE_CLOCK_GATING_A); |
tmp &= ~CGC_DYN_CLOCK_MODE; |
WREG32(VCE_CLOCK_GATING_A, tmp); |
|
tmp = RREG32(VCE_UENC_CLOCK_GATING); |
tmp |= 0x1ff000; |
tmp &= ~0xff800000; |
WREG32(VCE_UENC_CLOCK_GATING, tmp); |
|
tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); |
tmp |= 0x3ff; |
WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); |
} |
} |
|
static void vce_v1_0_init_cg(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
tmp = RREG32(VCE_CLOCK_GATING_A); |
tmp |= CGC_DYN_CLOCK_MODE; |
WREG32(VCE_CLOCK_GATING_A, tmp); |
|
tmp = RREG32(VCE_CLOCK_GATING_B); |
tmp |= 0x1e; |
tmp &= ~0xe100e1; |
WREG32(VCE_CLOCK_GATING_B, tmp); |
|
tmp = RREG32(VCE_UENC_CLOCK_GATING); |
tmp &= ~0xff9ff000; |
WREG32(VCE_UENC_CLOCK_GATING, tmp); |
|
tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); |
tmp &= ~0x3ff; |
WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); |
} |
|
int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data) |
{ |
struct vce_v1_0_fw_signature *sign = (void*)rdev->vce_fw->data; |
uint32_t chip_id; |
int i; |
|
switch (rdev->family) { |
case CHIP_TAHITI: |
chip_id = 0x01000014; |
break; |
case CHIP_VERDE: |
chip_id = 0x01000015; |
break; |
case CHIP_PITCAIRN: |
case CHIP_OLAND: |
chip_id = 0x01000016; |
break; |
case CHIP_ARUBA: |
chip_id = 0x01000017; |
break; |
default: |
return -EINVAL; |
} |
|
for (i = 0; i < sign->num; ++i) { |
if (sign->val[i].chip_id == chip_id) |
break; |
} |
|
if (i == sign->num) |
return -EINVAL; |
|
data += (256 - 64) / 4; |
data[0] = sign->val[i].nonce[0]; |
data[1] = sign->val[i].nonce[1]; |
data[2] = sign->val[i].nonce[2]; |
data[3] = sign->val[i].nonce[3]; |
data[4] = sign->len + 64; |
|
memset(&data[5], 0, 44); |
memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); |
|
data += data[4] / 4; |
data[0] = sign->val[i].sigval[0]; |
data[1] = sign->val[i].sigval[1]; |
data[2] = sign->val[i].sigval[2]; |
data[3] = sign->val[i].sigval[3]; |
|
rdev->vce.keyselect = sign->val[i].keyselect; |
|
return 0; |
} |
|
unsigned vce_v1_0_bo_size(struct radeon_device *rdev) |
{ |
WARN_ON(VCE_V1_0_FW_SIZE < rdev->vce_fw->size); |
return VCE_V1_0_FW_SIZE + VCE_V1_0_STACK_SIZE + VCE_V1_0_DATA_SIZE; |
} |
|
int vce_v1_0_resume(struct radeon_device *rdev) |
{ |
uint64_t addr = rdev->vce.gpu_addr; |
uint32_t size; |
int i; |
|
WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16)); |
WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); |
WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); |
WREG32(VCE_CLOCK_GATING_B, 0); |
|
WREG32_P(VCE_LMI_FW_PERIODIC_CTRL, 0x4, ~0x4); |
|
WREG32(VCE_LMI_CTRL, 0x00398000); |
WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1); |
WREG32(VCE_LMI_SWAP_CNTL, 0); |
WREG32(VCE_LMI_SWAP_CNTL1, 0); |
WREG32(VCE_LMI_VM_CTRL, 0); |
|
WREG32(VCE_VCPU_SCRATCH7, RADEON_MAX_VCE_HANDLES); |
|
addr += 256; |
size = VCE_V1_0_FW_SIZE; |
WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff); |
WREG32(VCE_VCPU_CACHE_SIZE0, size); |
|
addr += size; |
size = VCE_V1_0_STACK_SIZE; |
WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff); |
WREG32(VCE_VCPU_CACHE_SIZE1, size); |
|
addr += size; |
size = VCE_V1_0_DATA_SIZE; |
WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff); |
WREG32(VCE_VCPU_CACHE_SIZE2, size); |
|
WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100); |
|
WREG32(VCE_LMI_FW_START_KEYSEL, rdev->vce.keyselect); |
|
for (i = 0; i < 10; ++i) { |
mdelay(10); |
if (RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_DONE) |
break; |
} |
|
if (i == 10) |
return -ETIMEDOUT; |
|
if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_PASS)) |
return -EINVAL; |
|
for (i = 0; i < 10; ++i) { |
mdelay(10); |
if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_BUSY)) |
break; |
} |
|
if (i == 10) |
return -ETIMEDOUT; |
|
vce_v1_0_init_cg(rdev); |
|
return 0; |
} |
|
/** |
* vce_v1_0_start - start VCE block |
* |