mirror of https://gitee.com/openkylin/linux.git
drm/amdgpu: implement patch for fixing a known bug
Implement a patch to maunally reset read pointer v2: using ring assignment instead of amdgpu_ring_write. adding comments for each steps in the patch function. v3: fixing a typo bug. v4: fixing a bug in v3. Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
d2314b48d6
commit
8a998052f2
|
@ -40,6 +40,7 @@ static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
|||
static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr);
|
||||
|
||||
/**
|
||||
* vcn_v1_0_early_init - set function pointers
|
||||
|
@ -1442,6 +1443,97 @@ static void vcn_v1_0_jpeg_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
}
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
ring->ring[(*ptr)++] = 0;
|
||||
ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0);
|
||||
} else {
|
||||
ring->ring[(*ptr)++] = reg_offset;
|
||||
ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0);
|
||||
}
|
||||
ring->ring[(*ptr)++] = val;
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
uint32_t reg, reg_offset, val, mask, i;
|
||||
|
||||
// 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW);
|
||||
reg_offset = (reg << 2);
|
||||
val = lower_32_bits(ring->gpu_addr);
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH);
|
||||
reg_offset = (reg << 2);
|
||||
val = upper_32_bits(ring->gpu_addr);
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 3rd to 5th: issue MEM_READ commands
|
||||
for (i = 0; i <= 2; i++) {
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2);
|
||||
ring->ring[ptr++] = 0;
|
||||
}
|
||||
|
||||
// 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x13;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 7th: program mmUVD_JRBC_RB_REF_DATA
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x1;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 8th: issue conditional register read mmUVD_JRBC_RB_CNTL
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x1;
|
||||
mask = 0x1;
|
||||
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0);
|
||||
ring->ring[ptr++] = 0x01400200;
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0);
|
||||
ring->ring[ptr++] = val;
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
ring->ring[ptr++] = 0;
|
||||
ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3);
|
||||
} else {
|
||||
ring->ring[ptr++] = reg_offset;
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3);
|
||||
}
|
||||
ring->ring[ptr++] = mask;
|
||||
|
||||
//9th to 21st: insert no-op
|
||||
for (i = 0; i <= 12; i++) {
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
|
||||
ring->ring[ptr++] = 0;
|
||||
}
|
||||
|
||||
//22nd: reset mmUVD_JRBC_RB_RPTR
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_RPTR);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
//23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x12;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
}
|
||||
|
||||
static int vcn_v1_0_set_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
|
|
Loading…
Reference in New Issue