Am 01.06.2018 um 23:24 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. > v4: fixing a bug in v3. > > 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) > +{ > + 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 <christian.koenig at amd.com>. 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,