On 2018-06-01 01:54 PM, Christian König wrote: > Am 01.06.2018 um 18:35 schrieb boyuan.zhang at amd.com: >> From: Boyuan Zhang <boyuan.zhang at amd.com> >> >> 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. >> >> Signed-off-by: Boyuan Zhang <boyuan.zhang at amd.com> >> --- >>  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) > > &ptr only works in C++, you need to use *ptr here :) > > But apart from that the patch now looks good to me, > Christian. Oops, sorry my fault. I've no idea why I made this obvious mistake. This is totally accidental... Anyways, just sent out patch#9 v4. > >> +{ >> +   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, >