RE: [PATCH 2/2] drm/amdgpu: Add JPEG v5.0.2 SRIOV code path
"Deucher, Alexander" <[email protected]> Thu, 30 Jul 2026 20:33:04 +0000
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <BN9PR12MB5146B6FB172724965076364DF7C92@BN9PR12MB5146.namprd12.prod.outlook.com> |
AMD General > -----Original Message----- > From: amd-gfx <[email protected]> On Behalf Of Bokun > Zhang > Sent: Thursday, July 30, 2026 4:28 PM > To: [email protected] > Cc: Zhang, Bokun <[email protected]> > Subject: [PATCH 2/2] drm/amdgpu: Add JPEG v5.0.2 SRIOV code path > > - Add JPEG v5.0.2 SRIOV code path > - Add JPEG MMSCH init table transfer > - Skip unsupported actions such as power gating > and per queue reset for SRIOV VF. > > Signed-off-by: Bokun Zhang <[email protected]> Series is: Reviewed-by: Alex Deucher <[email protected]> > --- > drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c | 156 > ++++++++++++++++++++++- > 1 file changed, 152 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c > b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c > index 1c7f13e1cd75..e9df11a5dd26 100644 > --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c > +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c > @@ -34,6 +34,7 @@ > #include "vcn/vcn_5_0_0_sh_mask.h" > #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h" > > +static int jpeg_v5_0_2_start_sriov(struct amdgpu_device *adev); > static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev); > static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev); static > int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block, > @@ -164,9 +165,15 @@ static int jpeg_v5_0_2_sw_init(struct > amdgpu_ip_block *ip_block) > ring = &adev->jpeg.inst[i].ring_dec[j]; > ring->use_doorbell = true; > ring->vm_hub = AMDGPU_MMHUB0(adev- > >jpeg.inst[i].aid_id); > - ring->doorbell_index = > - (adev->doorbell_index.vcn.vcn_ring0_1 << 1) > + > - 1 + j + 11 * jpeg_inst; > + if (amdgpu_sriov_vf(adev)) { > + ring->doorbell_index = > + (adev- > >doorbell_index.vcn.vcn_ring0_1 << 1) + > + 2 + j + 32 * jpeg_inst; > + } else { > + ring->doorbell_index = > + (adev- > >doorbell_index.vcn.vcn_ring0_1 << 1) + > + 1 + j + 11 * jpeg_inst; > + } > sprintf(ring->name, "jpeg_dec_%d.%d", i, j); > r = amdgpu_ring_init(adev, ring, 512, &adev- > >jpeg.inst->irq, 0, > AMDGPU_RING_PRIO_DEFAULT, > NULL); @@ -187,7 +194,8 @@ static int jpeg_v5_0_2_sw_init(struct > amdgpu_ip_block *ip_block) > > adev->jpeg.supported_reset = > amdgpu_get_soft_full_reset_mask(&adev- > >jpeg.inst[0].ring_dec[0]); > - adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; > + if (!amdgpu_sriov_vf(adev)) > + adev->jpeg.supported_reset |= > AMDGPU_RESET_TYPE_PER_QUEUE; > r = amdgpu_jpeg_sysfs_reset_mask_init(adev); > > return r; > @@ -228,6 +236,23 @@ static int jpeg_v5_0_2_hw_init(struct > amdgpu_ip_block *ip_block) > struct amdgpu_ring *ring; > int i, j, r, jpeg_inst, tmp; > > + if (amdgpu_sriov_vf(adev)) { > + r = jpeg_v5_0_2_start_sriov(adev); > + if (r) > + return r; > + > + for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { > + for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { > + ring = &adev->jpeg.inst[i].ring_dec[j]; > + ring->wptr = 0; > + ring->wptr_old = 0; > + jpeg_v5_0_2_dec_ring_set_wptr(ring); > + ring->sched.ready = true; > + } > + } > + return 0; > + } > + > if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & > 0x100) > adev->jpeg.caps |= AMDGPU_JPEG_CAPS(RRMT_ENABLED); > > @@ -276,8 +301,10 @@ static int jpeg_v5_0_2_hw_fini(struct > amdgpu_ip_block *ip_block) > > cancel_delayed_work_sync(&adev->jpeg.idle_work); > > + if (!amdgpu_sriov_vf(adev)) { > if (adev->jpeg.cur_state != AMD_PG_STATE_GATE) > ret = jpeg_v5_0_2_set_powergating_state(ip_block, > AMD_PG_STATE_GATE); > + } > > return ret; > } > @@ -407,6 +434,122 @@ static void jpeg_v5_0_2_init_jrbc(struct > amdgpu_ring *ring) > reg_offset); > } > > +/** > + * jpeg_v5_0_2_start_sriov - start JPEG block under SRIOV env */ > +static int jpeg_v5_0_2_start_sriov(struct amdgpu_device *adev) { > + struct amdgpu_ring *ring; > + uint64_t ctx_addr; > + uint32_t param, resp, expected; > + uint32_t tmp, timeout; > + > + struct amdgpu_mm_table *table = &adev->virt.mm_table; > + uint32_t *table_loc; > + uint32_t table_size; > + uint32_t size, size_dw, item_offset; > + uint32_t init_status; > + int i, j, jpeg_inst; > + > + struct mmsch_v5_0_cmd_direct_write > + direct_wt = { {0} }; > + struct mmsch_v5_0_cmd_end end = { {0} }; > + struct mmsch_v5_0_init_header header; > + > + direct_wt.cmd_header.command_type = > + MMSCH_COMMAND__DIRECT_REG_WRITE; > + end.cmd_header.command_type = > + MMSCH_COMMAND__END; > + > + for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) { > + jpeg_inst = GET_INST(JPEG, i); > + > + memset(&header, 0, sizeof(struct > mmsch_v5_0_init_header)); > + header.version = MMSCH_VERSION; > + header.total_size = sizeof(struct mmsch_v5_0_init_header) >> > 2; > + > + table_loc = (uint32_t *)table->cpu_addr; > + table_loc += header.total_size; > + > + item_offset = header.total_size; > + > + for (j = 0; j < adev->jpeg.num_jpeg_rings; j++) { > + ring = &adev->jpeg.inst[i].ring_dec[j]; > + table_size = 0; > + > + tmp = SOC15_REG_OFFSET(JPEG, 0, > regUVD_LMI_JRBC_RB_64BIT_BAR_LOW); > + MMSCH_V5_0_INSERT_DIRECT_WT(tmp, > lower_32_bits(ring->gpu_addr)); > + tmp = SOC15_REG_OFFSET(JPEG, 0, > regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH); > + MMSCH_V5_0_INSERT_DIRECT_WT(tmp, > upper_32_bits(ring->gpu_addr)); > + tmp = SOC15_REG_OFFSET(JPEG, 0, > regUVD_JRBC_RB_SIZE); > + MMSCH_V5_0_INSERT_DIRECT_WT(tmp, ring- > >ring_size / 4); > + > + if (j < 5) { > + header.mjpegdec0[j].table_offset = > item_offset; > + header.mjpegdec0[j].init_status = 0; > + header.mjpegdec0[j].table_size = table_size; > + } else { > + header.mjpegdec1[j - 5].table_offset = > item_offset; > + header.mjpegdec1[j - 5].init_status = 0; > + header.mjpegdec1[j - 5].table_size = > table_size; > + } > + header.total_size += table_size; > + item_offset += table_size; > + } > + > + MMSCH_V5_0_INSERT_END(); > + > + /* send init table to MMSCH */ > + size = sizeof(struct mmsch_v5_0_init_header); > + table_loc = (uint32_t *)table->cpu_addr; > + memcpy((void *)table_loc, &header, size); > + > + ctx_addr = table->gpu_addr; > + WREG32_SOC15(VCN, jpeg_inst, > regMMSCH_VF_CTX_ADDR_LO, lower_32_bits(ctx_addr)); > + WREG32_SOC15(VCN, jpeg_inst, > regMMSCH_VF_CTX_ADDR_HI, > +upper_32_bits(ctx_addr)); > + > + tmp = RREG32_SOC15(VCN, jpeg_inst, > regMMSCH_VF_VMID); > + tmp &= ~MMSCH_VF_VMID__VF_CTX_VMID_MASK; > + tmp |= (0 << MMSCH_VF_VMID__VF_CTX_VMID__SHIFT); > + WREG32_SOC15(VCN, jpeg_inst, regMMSCH_VF_VMID, > tmp); > + > + size = header.total_size; > + WREG32_SOC15(VCN, jpeg_inst, regMMSCH_VF_CTX_SIZE, > size); > + > + WREG32_SOC15(VCN, jpeg_inst, > regMMSCH_VF_MAILBOX_RESP, 0); > + > + param = 0x00000001; > + WREG32_SOC15(VCN, jpeg_inst, > regMMSCH_VF_MAILBOX_HOST, param); > + tmp = 0; > + timeout = amdgpu_emu_mode ? 1000000 : 1000; > + resp = 0; > + expected = MMSCH_VF_MAILBOX_RESP__OK; > + init_status = > + ((struct mmsch_v5_0_init_header *)(table_loc))- > >mjpegdec0[i].init_status; > + while (resp != expected) { > + resp = RREG32_SOC15(VCN, jpeg_inst, > regMMSCH_VF_MAILBOX_RESP); > + > + if (resp != 0) > + break; > + udelay(10); > + tmp = tmp + 10; > + if (tmp >= timeout) { > + DRM_ERROR("failed to init MMSCH. TIME- > OUT after %d usec"\ > + " waiting for > regMMSCH_VF_MAILBOX_RESP "\ > + "(expected=0x%08x, > readback=0x%08x)\n", > + tmp, expected, resp); > + return -EBUSY; > + } > + } > + if (resp != expected && resp != > MMSCH_VF_MAILBOX_RESP__INCOMPLETE && > + init_status != > MMSCH_VF_ENGINE_STATUS__PASS) > + DRM_ERROR("MMSCH init status is incorrect! > readback=0x%08x, header init status for jpeg: %x\n", > + resp, init_status); > + > + } > + return 0; > +} > + > /** > * jpeg_v5_0_2_start - start JPEG block > * > @@ -566,6 +709,11 @@ static int > jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block, > struct amdgpu_device *adev = ip_block->adev; > int ret; > > + if (amdgpu_sriov_vf(adev)) { > + adev->jpeg.cur_state = AMD_PG_STATE_UNGATE; > + return 0; > + } > + > if (state == adev->jpeg.cur_state) > return 0; > > -- > 2.51.0