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