Am 01.06.2018 um 23:24 schrieb [email protected]:
From: Boyuan Zhang <[email protected]>

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 <[email protected]>
---
  drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 92 +++++++++++++++++++++++++++++++++++
  1 file changed, 92 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c 
b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index ea1d677..e8d24a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -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))) {

Looks like you are using way to many tabs here. Same problem below.

Apart from that the patch is Reviewed-by: Christian König <[email protected]>.

Regards,
Christian.

+               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,

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to