Re: RE: [PATCH v2 5/5] media: chips-media: wave5: support Wave515 decoder

From: Ivan Bornyakov
Date: Wed Mar 27 2024 - 07:30:20 EST


On Wed, Mar 27, 2024 at 10:34:15AM +0000, Nas Chung wrote:
> Hi, Ivan.
>
> >-----Original Message-----
> >From: Ivan Bornyakov <brnkv.i1@xxxxxxxxx>
> >Sent: Monday, March 25, 2024 3:41 PM
> >To: Nas Chung <nas.chung@xxxxxxxxxxxxxxx>; jackson.lee
> ><jackson.lee@xxxxxxxxxxxxxxx>; Mauro Carvalho Chehab <mchehab@xxxxxxxxxx>;
> >Philipp Zabel <p.zabel@xxxxxxxxxxxxxx>
> >Cc: Ivan Bornyakov <brnkv.i1@xxxxxxxxx>; linux-media@xxxxxxxxxxxxxxx;
> >linux-kernel@xxxxxxxxxxxxxxx
> >Subject: [PATCH v2 5/5] media: chips-media: wave5: support Wave515
> >decoder
> >
> >Add initial support for Wave515 multi-decoder IP. For now it is only
> >able to decode HEVC Main/Main10 profile videos.
>
> Thanks for your updates.
> Could you share some test result for HEVC decoding ? (ex. Fluster test)

I've tested decoding with ffmpeg like so:
ffmpeg -c:v hevc_v4l2m2m -i coded_file.h265 -fps_mode passthrough decoded_file.yuv

I didn't run fluster test, but I will.

> As you know, wave515 can support VP9 and AVS2.
> Did you have any chance to test VP9 or AVS2 streams ?

The plan is to settle initial support, then start working on support for
other formats.

>
> Thanks.
> Nas.
>
> >
> >This was tested on FPGA prototype, so wave5_dt_ids[] was not expanded.
> >Users of the real hardware with Wave515 IP will have to
> > * provide firmware specific to their SoC
> > * add struct wave5_match_data like this:
> >
> > static const struct wave5_match_data platform_name_wave515_data = {
> > .flags = WAVE5_IS_DEC,
> > .fw_name = "cnm/wave515_platform_name_fw.bin",
> > };
> >
> > * add item to wave5_dt_ids[] like this:
> >
> > {
> > .compatible = "vendor,soc-wave515",
> > .data = &platform_name_wave515_data,
> > },
> >
> > * describe new compatible in
> > Documentation/devicetree/bindings/media/cnm,wave521c.yaml
> >
> >Signed-off-by: Ivan Bornyakov <brnkv.i1@xxxxxxxxx>
> >---
> > .../platform/chips-media/wave5/wave5-helper.c | 3 +-
> > .../platform/chips-media/wave5/wave5-hw.c | 245 ++++++++++++++----
> > .../chips-media/wave5/wave5-regdefine.h | 5 +
> > .../platform/chips-media/wave5/wave5-vdi.c | 6 +-
> > .../chips-media/wave5/wave5-vpu-dec.c | 14 +-
> > .../platform/chips-media/wave5/wave5-vpu.c | 8 +-
> > .../platform/chips-media/wave5/wave5-vpuapi.h | 1 +
> > .../chips-media/wave5/wave5-vpuconfig.h | 9 +-
> > .../media/platform/chips-media/wave5/wave5.h | 1 +
> > 9 files changed, 233 insertions(+), 59 deletions(-)
> >
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c
> >b/drivers/media/platform/chips-media/wave5/wave5-helper.c
> >index 8433ecab230c..c68f1e110ed9 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-helper.c
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c
> >@@ -29,7 +29,8 @@ void wave5_cleanup_instance(struct vpu_instance *inst)
> > {
> > int i;
> >
> >- if (list_is_singular(&inst->list))
> >+ if (list_is_singular(&inst->list) &&
> >+ inst->dev->product_code != WAVE515_CODE)
> > wave5_vdi_free_sram(inst->dev);
> >
> > for (i = 0; i < inst->fbc_buf_count; i++)
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-hw.c
> >b/drivers/media/platform/chips-media/wave5/wave5-hw.c
> >index cdd0a0948a94..e38995de6870 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-hw.c
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c
> >@@ -24,8 +24,10 @@
> > #define FEATURE_HEVC_ENCODER BIT(0)
> >
> > /* Decoder support fields */
> >+#define W515_FEATURE_HEVC10BIT_DEC BIT(1)
> > #define FEATURE_AVC_DECODER BIT(3)
> > #define FEATURE_HEVC_DECODER BIT(2)
> >+#define W515_FEATURE_HEVC_DECODER BIT(0)
> >
> > #define FEATURE_BACKBONE BIT(16)
> > #define FEATURE_VCORE_BACKBONE BIT(22)
> >@@ -155,6 +157,8 @@ static int wave5_wait_bus_busy(struct vpu_device
> >*vpu_dev, unsigned int addr)
> > {
> > u32 gdi_status_check_value = 0x3f;
> >
> >+ if (vpu_dev->product_code == WAVE515_CODE)
> >+ gdi_status_check_value = 0x0738;
> > if (vpu_dev->product_code == WAVE521C_CODE ||
> > vpu_dev->product_code == WAVE521_CODE ||
> > vpu_dev->product_code == WAVE521E1_CODE)
> >@@ -186,6 +190,8 @@ unsigned int wave5_vpu_get_product_id(struct
> >vpu_device *vpu_dev)
> > u32 val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER);
> >
> > switch (val) {
> >+ case WAVE515_CODE:
> >+ return PRODUCT_ID_515;
> > case WAVE521C_CODE:
> > return PRODUCT_ID_521;
> > case WAVE521_CODE:
> >@@ -349,17 +355,33 @@ static int setup_wave5_properties(struct device
> >*dev)
> > hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1);
> > hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE);
> >
> >- p_attr->support_hevc10bit_enc = FIELD_GET(FEATURE_HEVC10BIT_ENC,
> >hw_config_feature);
> >- p_attr->support_avc10bit_enc = FIELD_GET(FEATURE_AVC10BIT_ENC,
> >hw_config_feature);
> >-
> >- p_attr->support_decoders = FIELD_GET(FEATURE_AVC_DECODER,
> >hw_config_def1) << STD_AVC;
> >- p_attr->support_decoders |= FIELD_GET(FEATURE_HEVC_DECODER,
> >hw_config_def1) << STD_HEVC;
> >- p_attr->support_encoders = FIELD_GET(FEATURE_AVC_ENCODER,
> >hw_config_def1) << STD_AVC;
> >- p_attr->support_encoders |= FIELD_GET(FEATURE_HEVC_ENCODER,
> >hw_config_def1) << STD_HEVC;
> >-
> >- p_attr->support_backbone = FIELD_GET(FEATURE_BACKBONE,
> >hw_config_def0);
> >- p_attr->support_vcpu_backbone = FIELD_GET(FEATURE_VCPU_BACKBONE,
> >hw_config_def0);
> >- p_attr->support_vcore_backbone = FIELD_GET(FEATURE_VCORE_BACKBONE,
> >hw_config_def0);
> >+ if (vpu_dev->product_code == WAVE515_CODE) {
> >+ p_attr->support_hevc10bit_dec =
> >FIELD_GET(W515_FEATURE_HEVC10BIT_DEC,
> >+ hw_config_feature);
> >+ p_attr->support_decoders =
> >FIELD_GET(W515_FEATURE_HEVC_DECODER,
> >+ hw_config_def1) << STD_HEVC;
> >+ } else {
> >+ p_attr->support_hevc10bit_enc =
> >FIELD_GET(FEATURE_HEVC10BIT_ENC,
> >+ hw_config_feature);
> >+ p_attr->support_avc10bit_enc =
> >FIELD_GET(FEATURE_AVC10BIT_ENC,
> >+ hw_config_feature);
> >+
> >+ p_attr->support_decoders = FIELD_GET(FEATURE_AVC_DECODER,
> >+ hw_config_def1) << STD_AVC;
> >+ p_attr->support_decoders |= FIELD_GET(FEATURE_HEVC_DECODER,
> >+ hw_config_def1) << STD_HEVC;
> >+ p_attr->support_encoders = FIELD_GET(FEATURE_AVC_ENCODER,
> >+ hw_config_def1) << STD_AVC;
> >+ p_attr->support_encoders |= FIELD_GET(FEATURE_HEVC_ENCODER,
> >+ hw_config_def1) << STD_HEVC;
> >+
> >+ p_attr->support_backbone = FIELD_GET(FEATURE_BACKBONE,
> >+ hw_config_def0);
> >+ p_attr->support_vcpu_backbone =
> >FIELD_GET(FEATURE_VCPU_BACKBONE,
> >+ hw_config_def0);
> >+ p_attr->support_vcore_backbone =
> >FIELD_GET(FEATURE_VCORE_BACKBONE,
> >+ hw_config_def0);
> >+ }
> >
> > setup_wave5_interrupts(vpu_dev);
> >
> >@@ -403,12 +425,18 @@ int wave5_vpu_init(struct device *dev, u8 *fw,
> >size_t size)
> > common_vb = &vpu_dev->common_mem;
> >
> > code_base = common_vb->daddr;
> >+
> >+ if (vpu_dev->product_code == WAVE515_CODE)
> >+ code_size = WAVE515_MAX_CODE_BUF_SIZE;
> >+ else
> >+ code_size = WAVE5_MAX_CODE_BUF_SIZE;
> >+
> > /* ALIGN TO 4KB */
> >- code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
> >+ code_size &= ~0xfff;
> > if (code_size < size * 2)
> > return -EINVAL;
> >
> >- temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;
> >+ temp_base = code_base + code_size;
> > temp_size = WAVE5_TEMPBUF_SIZE;
> >
> > ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size);
> >@@ -436,9 +464,12 @@ int wave5_vpu_init(struct device *dev, u8 *fw,
> >size_t size)
> >
> > /* These register must be reset explicitly */
> > vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
> >- wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
> >- wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
> >- vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
> >+
> >+ if (vpu_dev->product_code != WAVE515_CODE) {
> >+ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
> >+ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
> >+ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
> >+ }
> >
> > reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
> > if (FIELD_GET(FEATURE_BACKBONE, reg_val)) {
> >@@ -453,6 +484,24 @@ int wave5_vpu_init(struct device *dev, u8 *fw,
> >size_t size)
> > wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
> > }
> >
> >+ if (vpu_dev->product_code == WAVE515_CODE) {
> >+ dma_addr_t task_buf_base;
> >+
> >+ vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,
> >WAVE515_COMMAND_QUEUE_DEPTH);
> >+ vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,
> >WAVE515_ONE_TASKBUF_SIZE);
> >+
> >+ for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {
> >+ task_buf_base = temp_base + temp_size +
> >+ (i * WAVE515_ONE_TASKBUF_SIZE);
> >+ vpu_write_reg(vpu_dev,
> >+ W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),
> >+ task_buf_base);
> >+ }
> >+
> >+ vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI, vpu_dev-
> >>sram_buf.daddr);
> >+ vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE, vpu_dev-
> >>sram_buf.size);
> >+ }
> >+
> > vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
> > vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
> > vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
> >@@ -493,29 +542,39 @@ int wave5_vpu_build_up_dec_param(struct
> >vpu_instance *inst,
> > return -EINVAL;
> > }
> >
> >- p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;
> >+ if (vpu_dev->product == PRODUCT_ID_515)
> >+ p_dec_info->vb_work.size = WAVE515DEC_WORKBUF_SIZE;
> >+ else
> >+ p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;
> >+
> > ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info-
> >>vb_work);
> > if (ret)
> > return ret;
> >
> >- vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1);
> >+ if (inst->dev->product_code != WAVE515_CODE)
> >+ vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1);
> >
> > wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work);
> >
> > vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info-
> >>vb_work.daddr);
> > vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size);
> >
> >- vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev-
> >>sram_buf.daddr);
> >- vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev-
> >>sram_buf.size);
> >+ if (inst->dev->product_code != WAVE515_CODE) {
> >+ vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev-
> >>sram_buf.daddr);
> >+ vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev-
> >>sram_buf.size);
> >+ }
> >
> > vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info-
> >>stream_buf_start_addr);
> > vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info-
> >>stream_buf_size);
> >
> > /* NOTE: SDMA reads MSB first */
> > vpu_write_reg(inst->dev, W5_CMD_BS_PARAM,
> >BITSTREAM_ENDIANNESS_BIG_ENDIAN);
> >- /* This register must be reset explicitly */
> >- vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);
> >- vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1,
> >(COMMAND_QUEUE_DEPTH - 1));
> >+
> >+ if (inst->dev->product_code != WAVE515_CODE) {
> >+ /* This register must be reset explicitly */
> >+ vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);
> >+ vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1,
> >(COMMAND_QUEUE_DEPTH - 1));
> >+ }
> >
> > ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL,
> >NULL);
> > if (ret) {
> >@@ -566,7 +625,7 @@ static u32 get_bitstream_options(struct dec_info
> >*info)
> > int wave5_vpu_dec_init_seq(struct vpu_instance *inst)
> > {
> > struct dec_info *p_dec_info = &inst->codec_info->dec_info;
> >- u32 cmd_option = INIT_SEQ_NORMAL;
> >+ u32 bs_option, cmd_option = INIT_SEQ_NORMAL;
> > u32 reg_val, fail_res;
> > int ret;
> >
> >@@ -576,7 +635,12 @@ int wave5_vpu_dec_init_seq(struct vpu_instance *inst)
> > vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);
> > vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);
> >
> >- vpu_write_reg(inst->dev, W5_BS_OPTION,
> >get_bitstream_options(p_dec_info));
> >+ bs_option = get_bitstream_options(p_dec_info);
> >+
> >+ if (inst->dev->product_code == WAVE515_CODE)
> >+ bs_option |= BSOPTION_RD_PTR_VALID_FLAG;
> >+
> >+ vpu_write_reg(inst->dev, W5_BS_OPTION, bs_option);
> >
> > vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option);
> > vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info-
> >>user_data_enable);
> >@@ -642,10 +706,12 @@ static void wave5_get_dec_seq_result(struct
> >vpu_instance *inst, struct dec_initi
> > info->profile = FIELD_GET(SEQ_PARAM_PROFILE_MASK, reg_val);
> > }
> >
> >- info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);
> >- info->param_buf_size = vpu_read_reg(inst->dev,
> >W5_RET_PARAM_BUF_SIZE);
> >- p_dec_info->vlc_buf_size = info->vlc_buf_size;
> >- p_dec_info->param_buf_size = info->param_buf_size;
> >+ if (inst->dev->product_code != WAVE515_CODE) {
> >+ info->vlc_buf_size = vpu_read_reg(inst->dev,
> >W5_RET_VLC_BUF_SIZE);
> >+ info->param_buf_size = vpu_read_reg(inst->dev,
> >W5_RET_PARAM_BUF_SIZE);
> >+ p_dec_info->vlc_buf_size = info->vlc_buf_size;
> >+ p_dec_info->param_buf_size = info->param_buf_size;
> >+ }
> > }
> >
> > int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct
> >dec_initial_info *info)
> >@@ -747,22 +813,27 @@ int wave5_vpu_dec_register_framebuffer(struct
> >vpu_instance *inst, struct frame_b
> >
> > pic_size = (init_info->pic_width << 16) | (init_info-
> >>pic_height);
> >
> >- vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +
> >+ if (inst->dev->product_code != WAVE515_CODE) {
> >+ vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM)
> >+
> > (p_dec_info->param_buf_size *
> >COMMAND_QUEUE_DEPTH);
> >- vb_buf.daddr = 0;
> >+ vb_buf.daddr = 0;
> >
> >- if (vb_buf.size != p_dec_info->vb_task.size) {
> >- wave5_vdi_free_dma_memory(inst->dev, &p_dec_info-
> >>vb_task);
> >- ret = wave5_vdi_allocate_dma_memory(inst->dev,
> >&vb_buf);
> >- if (ret)
> >- goto free_fbc_c_tbl_buffers;
> >+ if (vb_buf.size != p_dec_info->vb_task.size) {
> >+ wave5_vdi_free_dma_memory(inst->dev,
> >+ &p_dec_info->vb_task);
> >+ ret = wave5_vdi_allocate_dma_memory(inst->dev,
> >+ &vb_buf);
> >+ if (ret)
> >+ goto free_fbc_c_tbl_buffers;
> >
> >- p_dec_info->vb_task = vb_buf;
> >- }
> >+ p_dec_info->vb_task = vb_buf;
> >+ }
> >
> >- vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
> >- p_dec_info->vb_task.daddr);
> >- vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE,
> >vb_buf.size);
> >+ vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
> >+ p_dec_info->vb_task.daddr);
> >+ vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE,
> >+ vb_buf.size);
> >+ }
> > } else {
> > pic_size = (init_info->pic_width << 16) | (init_info-
> >>pic_height);
> >
> >@@ -999,17 +1070,24 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw,
> >size_t size)
> > dma_addr_t code_base, temp_base;
> > dma_addr_t old_code_base, temp_size;
> > u32 code_size, reason_code;
> >- u32 reg_val;
> >+ u32 i, reg_val;
> > struct vpu_device *vpu_dev = dev_get_drvdata(dev);
> >
> > common_vb = &vpu_dev->common_mem;
> >
> > code_base = common_vb->daddr;
> >+
> >+ if (vpu_dev->product_code == WAVE515_CODE)
> >+ code_size = WAVE515_MAX_CODE_BUF_SIZE;
> >+ else
> >+ code_size = WAVE5_MAX_CODE_BUF_SIZE;
> >+
> > /* ALIGN TO 4KB */
> >- code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
> >+ code_size &= ~0xfff;
> > if (code_size < size * 2)
> > return -EINVAL;
> >- temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;
> >+
> >+ temp_base = code_base + code_size;
> > temp_size = WAVE5_TEMPBUF_SIZE;
> >
> > old_code_base = vpu_read_reg(vpu_dev, W5_VPU_REMAP_PADDR);
> >@@ -1043,9 +1121,12 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw,
> >size_t size)
> >
> > /* These register must be reset explicitly */
> > vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
> >- wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
> >- wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
> >- vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
> >+
> >+ if (vpu_dev->product_code != WAVE515_CODE) {
> >+ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR,
> >0);
> >+ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
> >+ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
> >+ }
> >
> > reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
> > if (FIELD_GET(FEATURE_BACKBONE, reg_val)) {
> >@@ -1060,6 +1141,28 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw,
> >size_t size)
> > wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID,
> >reg_val);
> > }
> >
> >+ if (vpu_dev->product_code == WAVE515_CODE) {
> >+ dma_addr_t task_buf_base;
> >+
> >+ vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,
> >+ WAVE515_COMMAND_QUEUE_DEPTH);
> >+ vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,
> >+ WAVE515_ONE_TASKBUF_SIZE);
> >+
> >+ for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {
> >+ task_buf_base = temp_base + temp_size +
> >+ (i * WAVE515_ONE_TASKBUF_SIZE);
> >+ vpu_write_reg(vpu_dev,
> >+ W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),
> >+ task_buf_base);
> >+ }
> >+
> >+ vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI,
> >+ vpu_dev->sram_buf.daddr);
> >+ vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE,
> >+ vpu_dev->sram_buf.size);
> >+ }
> >+
> > vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
> > vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
> > vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
> >@@ -1081,10 +1184,10 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw,
> >size_t size)
> > static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake,
> >const uint16_t *code,
> > size_t size)
> > {
> >- u32 reg_val;
> >+ u32 i, reg_val;
> > struct vpu_buf *common_vb;
> >- dma_addr_t code_base;
> >- u32 code_size, reason_code;
> >+ dma_addr_t code_base, temp_base;
> >+ u32 code_size, temp_size, reason_code;
> > struct vpu_device *vpu_dev = dev_get_drvdata(dev);
> > int ret;
> >
> >@@ -1114,13 +1217,22 @@ static int wave5_vpu_sleep_wake(struct device
> >*dev, bool i_sleep_wake, const uin
> > common_vb = &vpu_dev->common_mem;
> >
> > code_base = common_vb->daddr;
> >+
> >+ if (vpu_dev->product_code == WAVE515_CODE)
> >+ code_size = WAVE515_MAX_CODE_BUF_SIZE;
> >+ else
> >+ code_size = WAVE5_MAX_CODE_BUF_SIZE;
> >+
> > /* ALIGN TO 4KB */
> >- code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
> >+ code_size &= ~0xfff;
> > if (code_size < size * 2) {
> > dev_err(dev, "size too small\n");
> > return -EINVAL;
> > }
> >
> >+ temp_base = code_base + code_size;
> >+ temp_size = WAVE5_TEMPBUF_SIZE;
> >+
> > /* Power on without DEBUG mode */
> > vpu_write_reg(vpu_dev, W5_PO_CONF, 0);
> >
> >@@ -1133,9 +1245,12 @@ static int wave5_vpu_sleep_wake(struct device *dev,
> >bool i_sleep_wake, const uin
> >
> > /* These register must be reset explicitly */
> > vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
> >- wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
> >- wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
> >- vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
> >+
> >+ if (vpu_dev->product_code != WAVE515_CODE) {
> >+ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR,
> >0);
> >+ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
> >+ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
> >+ }
> >
> > setup_wave5_interrupts(vpu_dev);
> >
> >@@ -1152,6 +1267,28 @@ static int wave5_vpu_sleep_wake(struct device *dev,
> >bool i_sleep_wake, const uin
> > wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID,
> >reg_val);
> > }
> >
> >+ if (vpu_dev->product_code == WAVE515_CODE) {
> >+ dma_addr_t task_buf_base;
> >+
> >+ vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,
> >+ WAVE515_COMMAND_QUEUE_DEPTH);
> >+ vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,
> >+ WAVE515_ONE_TASKBUF_SIZE);
> >+
> >+ for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {
> >+ task_buf_base = temp_base + temp_size +
> >+ (i * WAVE515_ONE_TASKBUF_SIZE);
> >+ vpu_write_reg(vpu_dev,
> >+ W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),
> >+ task_buf_base);
> >+ }
> >+
> >+ vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI,
> >+ vpu_dev->sram_buf.daddr);
> >+ vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE,
> >+ vpu_dev->sram_buf.size);
> >+ }
> >+
> > vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
> > vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU);
> > /* Start VPU after settings */
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-regdefine.h
> >b/drivers/media/platform/chips-media/wave5/wave5-regdefine.h
> >index a15c6b2c3d8b..557344754c4c 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-regdefine.h
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-regdefine.h
> >@@ -205,6 +205,9 @@ enum query_opt {
> > #define W5_ADDR_TEMP_BASE (W5_REG_BASE + 0x011C)
> > #define W5_TEMP_SIZE (W5_REG_BASE + 0x0120)
> > #define W5_HW_OPTION (W5_REG_BASE + 0x012C)
> >+#define W5_CMD_INIT_NUM_TASK_BUF (W5_REG_BASE + 0x0134)
> >+#define W5_CMD_INIT_ADDR_TASK_BUF0 (W5_REG_BASE + 0x0138)
> >+#define W5_CMD_INIT_TASK_BUF_SIZE (W5_REG_BASE + 0x0178)
> > #define W5_SEC_AXI_PARAM (W5_REG_BASE + 0x0180)
> >
> >
> >/************************************************************************
> >/
> >@@ -216,7 +219,9 @@ enum query_opt {
> > #define W5_CMD_DEC_BS_SIZE (W5_REG_BASE + 0x0120)
> > #define W5_CMD_BS_PARAM (W5_REG_BASE + 0x0124)
> > #define W5_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0130)
> >+#define W515_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0124)
> > #define W5_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0134)
> >+#define W515_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0128)
> > #define W5_CMD_EXT_ADDR (W5_REG_BASE + 0x0138)
> > #define W5_CMD_NUM_CQ_DEPTH_M1 (W5_REG_BASE + 0x013C)
> > #define W5_CMD_ERR_CONCEAL (W5_REG_BASE + 0x0140)
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c
> >b/drivers/media/platform/chips-media/wave5/wave5-vdi.c
> >index a63fffed55e9..78888c57b6da 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c
> >@@ -18,7 +18,11 @@ static int wave5_vdi_allocate_common_memory(struct
> >device *dev)
> > if (!vpu_dev->common_mem.vaddr) {
> > int ret;
> >
> >- vpu_dev->common_mem.size = SIZE_COMMON;
> >+ if (vpu_dev->product_code == WAVE515_CODE)
> >+ vpu_dev->common_mem.size = WAVE515_SIZE_COMMON;
> >+ else
> >+ vpu_dev->common_mem.size = SIZE_COMMON;
> >+
> > ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev-
> >>common_mem);
> > if (ret) {
> > dev_err(dev, "unable to allocate common buffer\n");
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
> >b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
> >index 5a71a711f2e8..65a99053c5e8 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
> >@@ -1869,7 +1869,8 @@ static int wave5_vpu_open_dec(struct file *filp)
> > goto cleanup_inst;
> > }
> >
> >- wave5_vdi_allocate_sram(inst->dev);
> >+ if (inst->dev->product_code != WAVE515_CODE)
> >+ wave5_vdi_allocate_sram(inst->dev);
> >
> > return 0;
> >
> >@@ -1897,6 +1898,14 @@ int wave5_vpu_dec_register_device(struct
> >vpu_device *dev)
> > struct video_device *vdev_dec;
> > int ret;
> >
> >+ /*
> >+ * secondary AXI setup for Wave515 is done by INIT_VPU command,
> >+ * that's why SRAM memory is allocated at VPU device register
> >+ * rather than at device open.
> >+ */
> >+ if (dev->product_code == WAVE515_CODE)
> >+ wave5_vdi_allocate_sram(dev);
> >+
> > vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec),
> >GFP_KERNEL);
> > if (!vdev_dec)
> > return -ENOMEM;
> >@@ -1930,6 +1939,9 @@ int wave5_vpu_dec_register_device(struct vpu_device
> >*dev)
> >
> > void wave5_vpu_dec_unregister_device(struct vpu_device *dev)
> > {
> >+ if (dev->product_code == WAVE515_CODE)
> >+ wave5_vdi_free_sram(dev);
> >+
> > video_unregister_device(dev->video_dev_dec);
> > if (dev->v4l2_m2m_dec_dev)
> > v4l2_m2m_release(dev->v4l2_m2m_dec_dev);
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.c
> >b/drivers/media/platform/chips-media/wave5/wave5-vpu.c
> >index 2a972cddf4a6..fc267348399e 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c
> >@@ -60,7 +60,13 @@ static irqreturn_t wave5_vpu_irq_thread(int irq, void
> >*dev_id)
> >
> > if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
> > irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {
> >- if (seq_done & BIT(inst->id)) {
> >+ if ((dev->product_code == WAVE515_CODE) &&
> >+ (cmd_done & BIT(inst->id))) {
> >+ cmd_done &= ~BIT(inst->id);
> >+ wave5_vdi_write_register(dev,
> >W5_RET_QUEUE_CMD_DONE_INST,
> >+ cmd_done);
> >+ complete(&inst->irq_done);
> >+ } else if (seq_done & BIT(inst->id)) {
> > seq_done &= ~BIT(inst->id);
> > wave5_vdi_write_register(dev,
> >W5_RET_SEQ_DONE_INSTANCE_INFO,
> > seq_done);
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
> >b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
> >index 975d96b22191..601205df4433 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
> >@@ -18,6 +18,7 @@
> > #include "wave5-vdi.h"
> >
> > enum product_id {
> >+ PRODUCT_ID_515,
> > PRODUCT_ID_521,
> > PRODUCT_ID_511,
> > PRODUCT_ID_517,
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
> >b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
> >index 9d99afb78c89..b4128524fcfd 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
> >+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
> >@@ -8,6 +8,7 @@
> > #ifndef _VPU_CONFIG_H_
> > #define _VPU_CONFIG_H_
> >
> >+#define WAVE515_CODE 0x5150
> > #define WAVE517_CODE 0x5170
> > #define WAVE537_CODE 0x5370
> > #define WAVE511_CODE 0x5110
> >@@ -21,12 +22,13 @@
> > ((c) == WAVE517_CODE || (c) == WAVE537_CODE || \
> > (c) == WAVE511_CODE || (c) == WAVE521_CODE || \
> > (c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \
> >- (c) == WAVE521C_DUAL_CODE); \
> >+ (c) == WAVE521C_DUAL_CODE) || (c) == WAVE515_CODE; \
> > })
> >
> > #define WAVE517_WORKBUF_SIZE (2 * 1024 * 1024)
> > #define WAVE521ENC_WORKBUF_SIZE (128 * 1024) //HEVC 128K, AVC
> >40K
> > #define WAVE521DEC_WORKBUF_SIZE (1784 * 1024)
> >+#define WAVE515DEC_WORKBUF_SIZE (2 * 1024 * 1024)
> >
> > #define WAVE5_MAX_SRAM_SIZE (64 * 1024)
> >
> >@@ -52,16 +54,21 @@
> > #define VLC_BUF_NUM (2)
> >
> > #define COMMAND_QUEUE_DEPTH (2)
> >+#define WAVE515_COMMAND_QUEUE_DEPTH (4)
> >
> > #define W5_REMAP_INDEX0 0
> > #define W5_REMAP_INDEX1 1
> > #define W5_REMAP_MAX_SIZE (1024 * 1024)
> >
> > #define WAVE5_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
> >+#define WAVE515_MAX_CODE_BUF_SIZE (1024 * 1024)
> > #define WAVE5_TEMPBUF_OFFSET WAVE5_MAX_CODE_BUF_SIZE
> > #define WAVE5_TEMPBUF_SIZE (1024 * 1024)
> >+#define WAVE515_TASKBUF_OFFSET (WAVE515_MAX_CODE_BUF_SIZE +
> >WAVE5_TEMPBUF_SIZE)
> >
> > #define SIZE_COMMON (WAVE5_MAX_CODE_BUF_SIZE +
> >WAVE5_TEMPBUF_SIZE)
> >+#define WAVE515_ONE_TASKBUF_SIZE (8 * 1024 * 1024)
> >+#define WAVE515_SIZE_COMMON (WAVE515_TASKBUF_OFFSET +
> >WAVE515_COMMAND_QUEUE_DEPTH * WAVE515_ONE_TASKBUF_SIZE)
> >
> > //=====4. VPU REPORT MEMORY ======================//
> >
> >diff --git a/drivers/media/platform/chips-media/wave5/wave5.h
> >b/drivers/media/platform/chips-media/wave5/wave5.h
> >index 063028eccd3b..57b00e182b6e 100644
> >--- a/drivers/media/platform/chips-media/wave5/wave5.h
> >+++ b/drivers/media/platform/chips-media/wave5/wave5.h
> >@@ -22,6 +22,7 @@
> > */
> > #define BSOPTION_ENABLE_EXPLICIT_END BIT(0)
> > #define BSOPTION_HIGHLIGHT_STREAM_END BIT(1)
> >+#define BSOPTION_RD_PTR_VALID_FLAG BIT(31)
> >
> > /*
> > * Currently the driver only supports hardware with little endian but for
> >source
> >--
> >2.44.0
>