From dda01fd15e4c6e56c861b7b12356fc01d0418d42 Mon Sep 17 00:00:00 2001 From: Nas Chung Date: Wed, 7 Dec 2022 13:13:48 +0100 Subject: [PATCH 01/16] media: chips-media: wave5: Add TODO file Add a TODO file with remaining elements to be improved/added. Signed-off-by: Robert Beckett Signed-off-by: Dafna Hirschfeld Signed-off-by: Sebastian Fricke Signed-off-by: Nas Chung [sw0312.kim: cherry-pick the commit b9ab65a219e6 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I5249e0f04859224e17b3a1d7702093eedaf000ca --- drivers/media/platform/chips-media/wave5/TODO | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 drivers/media/platform/chips-media/wave5/TODO diff --git a/drivers/media/platform/chips-media/wave5/TODO b/drivers/media/platform/chips-media/wave5/TODO new file mode 100644 index 0000000..2164fd0 --- /dev/null +++ b/drivers/media/platform/chips-media/wave5/TODO @@ -0,0 +1,18 @@ +* Handle interrupts better + +Currently the interrupt handling uses an unusual design employing a kfifo to +transfer irq status to irq thread. This was done as a work around for dropped +interrupts seen with IRQF_ONESHOT based handling. + +This needs further investigation and fixing properly, with the aid of +C&M. + +* power management handling - add (runtime_)suspen/resume cb where the clock is enabled + +* revise logic of wave5_vpu_(dec/enc)_register_framebuffer + +* check if the normal kernel endianness/__swab32 routines are sufficient. (instead of the ones + implemented in the driver) + +* Adjust STREAMON routine for the stateful decoder to adhere to the API, which + declares that STREAMON can be called before source buffers have been queued. -- 2.7.4 From 6b195aae33f452c60523d967e5652ffc1b5e36af Mon Sep 17 00:00:00 2001 From: Robert Beckett Date: Wed, 7 Dec 2022 13:13:49 +0100 Subject: [PATCH 02/16] dt-bindings: media: wave5: add yaml devicetree bindings Add bindings for the wave5 chips&media codec driver Signed-off-by: Robert Beckett Signed-off-by: Dafna Hirschfeld Signed-off-by: Sebastian Fricke [sw0312.kim: cherry-pick the commit cd9148ef1b14 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I754cbc1e881b7ee8ff6a9c3da15cfc3f5900d1b0 --- Documentation/devicetree/bindings/cnm,wave5.yml | 72 +++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Documentation/devicetree/bindings/cnm,wave5.yml diff --git a/Documentation/devicetree/bindings/cnm,wave5.yml b/Documentation/devicetree/bindings/cnm,wave5.yml new file mode 100644 index 0000000..01dddeb --- /dev/null +++ b/Documentation/devicetree/bindings/cnm,wave5.yml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/wave5.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Chips&Media Wave 5 Series multi-standard codec IP + +maintainers: + - Nas Chung + - Robert Beckett + - Sebastian Fricke + +description: |- + The Chips&Media WAVE codec IP is a multi format video encoder/decoder + +properties: + compatible: + anyOf: + - items: + - enum: + - cnm,cm511-vpu + - cnm,cm517-vpu + - cnm,cm521-vpu + - cnm,cm521c-vpu + - cnm,cm521c-dual-vpu + - cnm,cm521e1-vpu + - cnm,cm537-vpu + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 4 + + clock-names: + minItems: 1 + maxItems: 4 + + interrupts: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + sram: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle pointing to the SRAM device node + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + vpu: video-codec@12345678 { + compatible = "cnm,cm521-vpu"; + reg = <0x12345678 0x1000>; + interrupts = <42>; + clocks = <&clks 42>; + clock-names = "vcodec"; + sram = <&sram>; + }; -- 2.7.4 From d6bfc43c879e5cb39422f936047940f2a86168c9 Mon Sep 17 00:00:00 2001 From: Robert Beckett Date: Wed, 7 Dec 2022 13:13:50 +0100 Subject: [PATCH 03/16] media: chips-media: wave5: Add wave5 driver to maintainers file Add the Chips&Media wave5 encoder/decoder driver to the maintainers file Signed-off-by: Robert Beckett Signed-off-by: Dafna Hirschfeld Signed-off-by: Sebastian Fricke [sw0312.kim: cherry-pick the commit c6cf2b7965b0 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I4c08a4a6be0ea4f4b9900e58ad7522914f65246a --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 825091a..6958b15 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22257,6 +22257,15 @@ F: include/linux/watchdog.h F: include/uapi/linux/watchdog.h F: include/trace/events/watchdog.h +WAVE5 VPU CODEC DRIVER +M: Nas Chung +M: Robert Beckett +M: Sebastian Fricke +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/cnm,wave5.yaml +F: drivers/media/platform/chips-media/wave5/ + WHISKEYCOVE PMIC GPIO DRIVER M: Kuppuswamy Sathyanarayanan L: linux-gpio@vger.kernel.org -- 2.7.4 From d4d68adbfb0b502166598344420126b9f9ab57b3 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Thu, 22 Dec 2022 15:33:22 +0800 Subject: [PATCH 04/16] media: add wave511 v4l2 support for starfive platfrom Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit a76c4f273c26 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I170dd61340d2da9155dda478e570828347c5bdaf --- .../platform/chips-media/wave5/wave5-helper.c | 1 + .../media/platform/chips-media/wave5/wave5-hw.c | 19 ++++- .../media/platform/chips-media/wave5/wave5-vdi.c | 5 ++ .../platform/chips-media/wave5/wave5-vpu-dec.c | 96 ++++++++++++++++------ .../media/platform/chips-media/wave5/wave5-vpu.c | 78 +++++++++++++----- .../media/platform/chips-media/wave5/wave5-vpu.h | 3 + .../platform/chips-media/wave5/wave5-vpuapi.c | 6 ++ .../platform/chips-media/wave5/wave5-vpuapi.h | 2 + 8 files changed, 162 insertions(+), 48 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c index 2851f3f..fb9c94d 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.c +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c @@ -106,6 +106,7 @@ int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscr { struct vpu_instance *inst = wave5_to_vpu_inst(fh); bool is_decoder = inst->type == VPU_INST_TYPE_DEC; + printk("wave5 subscribe event type: %d id: %d | flags: %d\n",sub->type, sub->id, sub->flags); dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__, is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags); diff --git a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c index 25705e6..3c83286 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-hw.c +++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c @@ -568,6 +568,7 @@ static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initi reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE); info->pic_width = ((reg_val >> 16) & 0xffff); info->pic_height = (reg_val & 0xffff); + dev_dbg(inst->dev->dev, "%s info->pic_width %d info->pic_height %d\n",__func__, info->pic_width, info->pic_height); info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_DEC_NUM_REQUIRED_FB); info->frame_buf_delay = vpu_read_reg(inst->dev, W5_RET_DEC_NUM_REORDER_DELAY); @@ -577,6 +578,8 @@ static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initi reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_TOP_BOTTOM); info->pic_crop_rect.top = (reg_val >> 16) & 0xffff; info->pic_crop_rect.bottom = reg_val & 0xffff; + dev_dbg(inst->dev->dev, "%s pic_crop_rect.left %d pic_crop_rect.right %d pic_crop_rect.top %d pic_crop_rect.bottom %d\n",__func__, + info->pic_crop_rect.left, info->pic_crop_rect.right, info->pic_crop_rect.top, info->pic_crop_rect.bottom); info->f_rate_numerator = vpu_read_reg(inst->dev, W5_RET_DEC_FRAME_RATE_NR); info->f_rate_denominator = vpu_read_reg(inst->dev, W5_RET_DEC_FRAME_RATE_DR); @@ -715,6 +718,7 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b struct vpu_buf vb_buf; u32 color_format = 0; u32 pixel_order = 1; + u32 scale_en = 0; u32 bwb_flag = (map_type == LINEAR_FRAME_MAP) ? 1 : 0; cbcr_interleave = inst->cbcr_interleave; @@ -816,7 +820,10 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b p_dec_info->vb_fbc_c_tbl[i] = vb_buf; } } - pic_size = (init_info->pic_width << 16) | (init_info->pic_height); + pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); + if (init_info->pic_width != inst->display_fmt.width || + init_info->pic_height != inst->display_fmt.height) + scale_en = 1; // allocate task_buffer vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) + @@ -832,8 +839,12 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b 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); + pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); + if (init_info->pic_width != inst->display_fmt.width || + init_info->pic_height != inst->display_fmt.height) + scale_en = 1; } + dev_dbg(inst->dev->dev, "set pic_size 0x%x\n", pic_size); endian = wave5_vdi_convert_endian(inst->dev, fb_arr[0].endian); vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size); @@ -841,13 +852,15 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b color_format = 0; reg_val = + (scale_en << 29) | (bwb_flag << 28) | (pixel_order << 23) | /* PIXEL ORDER in 128bit. first pixel in low address */ (yuv_format << 20) | (color_format << 19) | (nv21 << 17) | (cbcr_interleave << 16) | - (fb_arr[0].stride); + inst->display_fmt.width; + dev_dbg(inst->dev->dev, "set W5_COMMON_PIC_INFO 0x%x\n",reg_val); vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, reg_val); remain = count; diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c index 8c7c090..ec8b6cb 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c @@ -10,6 +10,7 @@ #include "wave5-vpu.h" #include "wave5-regdefine.h" #include +#include #define VDI_SRAM_BASE_ADDR 0x00 @@ -94,6 +95,7 @@ int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) } memset(vb->vaddr, 0, vb->size); + sifive_l2_flush64_range(vb->daddr, vb->size); return vb->size; } @@ -115,6 +117,7 @@ int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_ wave5_swap_endian(vpu_dev, data, len, endian); memcpy(vb->vaddr + offset, data, len); + sifive_l2_flush64_range(vb->daddr + offset, len); return len; } @@ -135,6 +138,8 @@ int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb vb->vaddr = vaddr; vb->daddr = daddr; + sifive_l2_flush64_range(daddr, vb->size); + return 0; } 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 f32118d..f722924 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -101,6 +101,9 @@ static void wave5_handle_bitstream_buffer(struct vpu_instance *inst) size_t remain_size = 0; size_t offset; + if (src_size == vb2_plane_size(&vbuf->vb2_buf, 0)) + src_size = 0; + if (vpu_buf->consumed) { dev_dbg(inst->dev->dev, "already consumed src buf (%u)\n", vbuf->vb2_buf.index); @@ -199,13 +202,13 @@ static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: pix_mp->width = round_up(width, 32); - pix_mp->height = round_up(height, 16); + pix_mp->height = round_up(height, 8); pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2; break; case V4L2_PIX_FMT_YUV420M: pix_mp->width = round_up(width, 32); - pix_mp->height = round_up(height, 16); + pix_mp->height = round_up(height, 8); pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); pix_mp->plane_fmt[0].sizeimage = width * height; pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2; @@ -216,7 +219,7 @@ static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned case V4L2_PIX_FMT_NV12M: case V4L2_PIX_FMT_NV21M: pix_mp->width = round_up(width, 32); - pix_mp->height = round_up(height, 16); + pix_mp->height = round_up(height, 8); pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); pix_mp->plane_fmt[0].sizeimage = width * height; pix_mp->plane_fmt[1].bytesperline = round_up(width, 32); @@ -314,6 +317,11 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) int stride = dec_output_info.disp_frame.stride; int height = dec_output_info.disp_pic_height - dec_output_info.rc_display.bottom; + if (dec_output_info.disp_pic_height != inst->display_fmt.height) + height = inst->display_fmt.height; + dev_dbg(inst->dev->dev, "%s %d disp_pic_height %u rc_display.bottom %u\n", + __func__, __LINE__, dec_output_info.disp_pic_height, dec_output_info.rc_display.bottom); + dev_dbg(inst->dev->dev, "%s %d stride %u height %u\n", __func__, __LINE__, stride, height); if (inst->dst_fmt.num_planes == 1) { vb2_set_plane_payload(&dst_buf->vb2_buf, 0, @@ -372,6 +380,7 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); inst->eos = TRUE; + pr_err("wave5 queue event type: %d id: %d\n",vpu_event_eos.type, vpu_event_eos.id); v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos); v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx); @@ -471,16 +480,26 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form { struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i, ret; + unsigned int scalew, scaleh; - dev_dbg(inst->dev->dev, + printk( "%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n", __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field); ret = wave5_vpu_dec_try_fmt_cap(file, fh, f); + if (ret) return ret; + scalew = inst->src_fmt.width / f->fmt.pix_mp.width; + scaleh = inst->src_fmt.height / f->fmt.pix_mp.height; + + if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { + dev_err(inst->dev->dev,"Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter. \n"); + return -EINVAL; + } + inst->dst_fmt.width = f->fmt.pix_mp.width; inst->dst_fmt.height = f->fmt.pix_mp.height; inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat; @@ -505,6 +524,8 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form inst->nv21 = false; } + memcpy((void *)&inst->display_fmt, (void *)&inst->dst_fmt, sizeof(struct v4l2_pix_format_mplane)); + return 0; } @@ -513,15 +534,15 @@ static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_form struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i; - f->fmt.pix_mp.width = inst->dst_fmt.width; - f->fmt.pix_mp.height = inst->dst_fmt.height; - f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; - f->fmt.pix_mp.field = inst->dst_fmt.field; - f->fmt.pix_mp.flags = inst->dst_fmt.flags; - f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; + f->fmt.pix_mp.width = inst->display_fmt.width; + f->fmt.pix_mp.height = inst->display_fmt.height; + f->fmt.pix_mp.pixelformat = inst->display_fmt.pixelformat; + f->fmt.pix_mp.field = inst->display_fmt.field; + f->fmt.pix_mp.flags = inst->display_fmt.flags; + f->fmt.pix_mp.num_planes = inst->display_fmt.num_planes; for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { - f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->dst_fmt.plane_fmt[i].bytesperline; - f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->dst_fmt.plane_fmt[i].sizeimage; + f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->display_fmt.plane_fmt[i].bytesperline; + f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->display_fmt.plane_fmt[i].sizeimage; } f->fmt.pix_mp.colorspace = inst->colorspace; @@ -589,7 +610,7 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i, ret; - dev_dbg(inst->dev->dev, + printk( "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); @@ -793,7 +814,7 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff { struct vpu_instance *inst = vb2_get_drv_priv(q); struct v4l2_pix_format_mplane inst_format = - (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt; + (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->display_fmt; unsigned int i; int ret; @@ -905,6 +926,8 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff frame->stride = fb_stride; frame->map_type = COMPRESSED_FRAME_MAP; frame->update_fb_info = true; + dev_dbg(inst->dev->dev, "no linear framebuf y 0x%llx cb 0x%llx cr 0x%llx\n", + frame->buf_y, frame->buf_cb, frame->buf_cr); } } else if (inst->state == VPU_INST_STATE_STOP && q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -921,6 +944,7 @@ free_bitstream_vbuf: static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) { struct dec_initial_info initial_info; + unsigned int scalew, scaleh; int ret = 0; memset(&initial_info, 0, sizeof(struct dec_initial_info)); @@ -969,6 +993,16 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, initial_info.pic_height); } + + scalew = inst->dst_fmt.width / inst->display_fmt.width; + scaleh = inst->dst_fmt.height / inst->display_fmt.height; + + if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { + wave5_update_pix_fmt(&inst->display_fmt, inst->dst_fmt.width, + inst->dst_fmt.height); + } + + printk("wave5 queue event type: %d id: %d\n",vpu_event_src_ch.type, vpu_event_src_ch.id); v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch); wave5_handle_src_buffer(inst); @@ -982,6 +1016,7 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) struct dec_initial_info initial_info; struct dec_param pic_param; struct dec_output_info dec_output_info; + unsigned int scalew, scaleh; int ret = 0; u32 fail_res = 0; @@ -1040,6 +1075,15 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, initial_info.pic_height); } + + scalew = inst->dst_fmt.width / inst->display_fmt.width; + scaleh = inst->dst_fmt.height / inst->display_fmt.height; + + if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { + wave5_update_pix_fmt(&inst->display_fmt, inst->dst_fmt.width, + inst->dst_fmt.height); + } + v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch); wave5_handle_src_buffer(inst); @@ -1081,22 +1125,22 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) dma_addr_t buf_addr_y = 0, buf_addr_cb = 0, buf_addr_cr = 0; u32 buf_size = 0; u32 non_linear_num = inst->dst_buf_count; - u32 fb_stride = inst->dst_fmt.width; - u32 luma_size = fb_stride * inst->dst_fmt.height; - u32 chroma_size = (fb_stride / 2) * (inst->dst_fmt.height / 2); + u32 fb_stride = inst->display_fmt.width; + u32 luma_size = fb_stride * inst->display_fmt.height; + u32 chroma_size = (fb_stride / 2) * (inst->display_fmt.height / 2); - if (inst->dst_fmt.num_planes == 1) { + if (inst->display_fmt.num_planes == 1) { buf_size = vb2_plane_size(&vbuf->vb2_buf, 0); buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); buf_addr_cb = buf_addr_y + luma_size; buf_addr_cr = buf_addr_cb + chroma_size; - } else if (inst->dst_fmt.num_planes == 2) { + } else if (inst->display_fmt.num_planes == 2) { buf_size = vb2_plane_size(&vbuf->vb2_buf, 0) + vb2_plane_size(&vbuf->vb2_buf, 1); buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); buf_addr_cb = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 1); buf_addr_cr = buf_addr_cb + chroma_size; - } else if (inst->dst_fmt.num_planes == 3) { + } else if (inst->display_fmt.num_planes == 3) { buf_size = vb2_plane_size(&vbuf->vb2_buf, 0) + vb2_plane_size(&vbuf->vb2_buf, 1) + vb2_plane_size(&vbuf->vb2_buf, 2); @@ -1108,10 +1152,11 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) inst->frame_buf[vb->index + non_linear_num].buf_cb = buf_addr_cb; inst->frame_buf[vb->index + non_linear_num].buf_cr = buf_addr_cr; inst->frame_buf[vb->index + non_linear_num].size = buf_size; - inst->frame_buf[vb->index + non_linear_num].width = inst->src_fmt.width; + inst->frame_buf[vb->index + non_linear_num].width = inst->display_fmt.width; inst->frame_buf[vb->index + non_linear_num].stride = fb_stride; inst->frame_buf[vb->index + non_linear_num].map_type = LINEAR_FRAME_MAP; inst->frame_buf[vb->index + non_linear_num].update_fb_info = true; + dev_dbg(inst->dev->dev, "linear framebuf y 0x%llx cb 0x%llx cr 0x%llx\n",buf_addr_y, buf_addr_cb, buf_addr_cr); } if (!vb2_is_streaming(vb->vb2_queue)) @@ -1177,14 +1222,19 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) while (check_cmd) { struct queue_status_info q_status; struct dec_output_info dec_output_info; + int try_cnt = 0; wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); if (q_status.instance_queue_count + q_status.report_queue_count == 0) break; - if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0) - break; + if (wave5_vpu_wait_interrupt(inst, 600) < 0){ + try_cnt++; + if (try_cnt >= 100) + break; + continue; + } if (wave5_vpu_dec_get_output_info(inst, &dec_output_info)) dev_dbg(inst->dev->dev, "Getting decoding results from fw, fail\n"); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c index 9c60216..176bbe7 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -22,11 +25,40 @@ #define WAVE5_IS_ENC BIT(0) #define WAVE5_IS_DEC BIT(1) +struct clk_bulk_data vpu_clks[] = { + { .id = "apb_clk" }, + { .id = "axi_clk" }, + { .id = "bpu_clk" }, + { .id = "vce_clk" }, + { .id = "noc_bus" }, +}; + struct wave5_match_data { int flags; const char *fw_name; }; +static int vpu_clk_get(struct platform_device *pdev, struct vpu_device *vpu) +{ + struct device *dev = &pdev->dev; + int ret; + + vpu->clks = vpu_clks; + vpu->num_clks = ARRAY_SIZE(vpu_clks); + + vpu->resets = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(vpu->resets)) { + ret = PTR_ERR(vpu->resets); + dev_err(dev, "faied to get vpu reset controls\n"); + } + + ret = devm_clk_bulk_get(dev, vpu->num_clks, vpu->clks); + if (ret) + dev_err(dev, "faied to get vpu clk controls\n"); + + return 0; +} + int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout) { int ret; @@ -170,9 +202,7 @@ static int wave5_vpu_probe(struct platform_device *pdev) { int ret; struct vpu_device *dev; - struct device_node *np; const struct wave5_match_data *match_data; - struct resource sram; match_data = device_get_match_data(&pdev->dev); if (!match_data) { @@ -191,6 +221,7 @@ static int wave5_vpu_probe(struct platform_device *pdev) dev->vdb_register = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->vdb_register)) return PTR_ERR(dev->vdb_register); + dev_dbg(&pdev->dev, "vdb_register %p\n",dev->vdb_register); ida_init(&dev->inst_ida); mutex_init(&dev->dev_lock); @@ -198,14 +229,16 @@ static int wave5_vpu_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, dev); dev->dev = &pdev->dev; - ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks); + ret = vpu_clk_get(pdev, dev); /* continue without clock, assume externally managed */ if (ret < 0) { - dev_warn(&pdev->dev, "Getting clocks, fail: %d\n", ret); - ret = 0; + dev_err(&pdev->dev, "Getting clocks, fail: %d\n", ret); + return ret; } - dev->num_clks = ret; + + dev->sram_buf.daddr = VDI_SRAM_BASE_ADDR; + dev->sram_buf.size = VDI_WAVE511_SRAM_SIZE; ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks); if (ret) { @@ -213,28 +246,21 @@ static int wave5_vpu_probe(struct platform_device *pdev) return ret; } - np = of_parse_phandle(pdev->dev.of_node, "sram", 0); - if (!np) { - dev_warn(&pdev->dev, "sram node not found\n"); - } else { - ret = of_address_to_resource(np, 0, &sram); - if (ret) { - dev_err(&pdev->dev, "sram resource not available\n"); - goto err_put_node; - } - dev->sram_buf.daddr = sram.start; - dev->sram_buf.size = resource_size(&sram); - dev_dbg(&pdev->dev, "%s: sram daddr: %pad, size: 0x%lx\n", - __func__, &dev->sram_buf.daddr, dev->sram_buf.size); + ret = reset_control_deassert(dev->resets); + if (ret) { + dev_err(&pdev->dev, "Reset deassert, fail: %d\n", ret); + goto err_clk_dis; } dev->product_code = wave5_vdi_readl(dev, VPU_PRODUCT_CODE_REGISTER); + dev_dbg(&pdev->dev, "product_code %d\n",dev->product_code); ret = wave5_vdi_init(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret); - goto err_clk_dis; + goto err_rst_dis; } dev->product = wave5_vpu_get_product_id(dev); + dev_dbg(&pdev->dev, "product %d\n",dev->product); INIT_LIST_HEAD(&dev->instances); ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); @@ -264,6 +290,7 @@ static int wave5_vpu_probe(struct platform_device *pdev) ret = -ENXIO; goto err_enc_unreg; } + dev_dbg(&pdev->dev, "irq %d\n",dev->irq); ret = devm_request_threaded_irq(&pdev->dev, dev->irq, wave5_vpu_irq, wave5_vpu_irq_thread, 0, "vpu_irq", dev); @@ -294,10 +321,10 @@ err_v4l2_unregister: v4l2_device_unregister(&dev->v4l2_dev); err_vdi_release: wave5_vdi_release(&pdev->dev); +err_rst_dis: + reset_control_assert(dev->resets); err_clk_dis: clk_bulk_disable_unprepare(dev->num_clks, dev->clks); -err_put_node: - of_node_put(np); return ret; } @@ -306,6 +333,7 @@ static int wave5_vpu_remove(struct platform_device *pdev) { struct vpu_device *dev = dev_get_drvdata(&pdev->dev); + reset_control_assert(dev->resets); clk_bulk_disable_unprepare(dev->num_clks, dev->clks); wave5_vpu_enc_unregister_device(dev); wave5_vpu_dec_unregister_device(dev); @@ -336,6 +364,11 @@ static const struct wave5_match_data default_match_data = { .fw_name = "chagall.bin", }; +static const struct wave5_match_data sfdec_match_data = { + .flags = WAVE5_IS_DEC, + .fw_name = "chagall.bin", +}; + static const struct of_device_id wave5_dt_ids[] = { { .compatible = "cnm,cm511-vpu", .data = &wave511_data }, { .compatible = "cnm,cm517-vpu", .data = &default_match_data }, @@ -344,6 +377,7 @@ static const struct of_device_id wave5_dt_ids[] = { { .compatible = "cnm,cm521c-dual-vpu", .data = &wave521c_data }, { .compatible = "cnm,cm521e1-vpu", .data = &default_match_data }, { .compatible = "cnm,cm537-vpu", .data = &default_match_data }, + { .compatible = "starfive,vdec", .data = &sfdec_match_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, wave5_dt_ids); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.h b/drivers/media/platform/chips-media/wave5/wave5-vpu.h index 7156d8c..e83c186 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.h @@ -20,6 +20,9 @@ #define VPU_BUF_SYNC_TO_DEVICE 0 #define VPU_BUF_SYNC_FROM_DEVICE 1 +#define VDI_SRAM_BASE_ADDR 0x00000000 +#define VDI_WAVE511_SRAM_SIZE 0x2D000 + struct vpu_buffer { struct v4l2_m2m_buffer v4l2_m2m_buf; bool consumed; diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c index 1458c55..5a0078a 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c @@ -491,12 +491,16 @@ int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_i p_dec_info->dec_out_info[decoded_index].rc_decoded = rect_info; } info->rc_decoded = rect_info; + dev_dbg(inst->dev->dev, "%s %d %u %u %u %u\n", __func__, __LINE__, + rect_info.left, rect_info.right, rect_info.top, rect_info.bottom); disp_idx = info->index_frame_display; disp_info = &p_dec_info->dec_out_info[disp_idx]; if (info->index_frame_display >= 0 && info->index_frame_display < WAVE5_MAX_FBS) { u32 width = info->dec_pic_width; u32 height = info->dec_pic_height; + dev_dbg(inst->dev->dev, "%s %d dec_pic_width %u dec_pic_height %u\n", + __func__, __LINE__, info->dec_pic_width, info->dec_pic_height); if (info->index_frame_display != info->index_frame_decoded) { /* @@ -573,6 +577,8 @@ int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_i info->disp_pic_height = 0; } } + dev_dbg(inst->dev->dev, "%s %d disp_pic_width %u disp_pic_height %u\n", + __func__, __LINE__, info->disp_pic_width, info->disp_pic_height); p_dec_info->stream_rd_ptr = wave5_vpu_dec_get_rd_ptr(inst); p_dec_info->frame_display_flag = vpu_read_reg(vpu_dev, W5_RET_DEC_DISP_IDC); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h index 1b3ffb7..0a4dc20 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h @@ -1024,6 +1024,7 @@ struct vpu_device { u32 product_code; struct ida inst_ida; struct clk_bulk_data *clks; + struct reset_control *resets; int num_clks; }; @@ -1046,6 +1047,7 @@ struct vpu_instance { struct v4l2_pix_format_mplane src_fmt; struct v4l2_pix_format_mplane dst_fmt; + struct v4l2_pix_format_mplane display_fmt; enum v4l2_colorspace colorspace; enum v4l2_xfer_func xfer_func; enum v4l2_ycbcr_encoding ycbcr_enc; -- 2.7.4 From aeb0c1e01b775d911162e5246a48c7e06ce31d30 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Thu, 12 Jan 2023 09:16:41 +0800 Subject: [PATCH 05/16] Media:wave5: set default format for display_fmt Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit 6d80c00e9258 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: Ic0f74bf12580e72ba3209c766e8d167c204702c5 --- drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 1 + 1 file changed, 1 insertion(+) 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 f722924..bba48cb 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -1403,6 +1403,7 @@ static int wave5_vpu_open_dec(struct file *filp) v4l2_ctrl_handler_setup(&inst->v4l2_ctrl_hdl); wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt); + memcpy((void *)&inst->display_fmt, (void *)&inst->dst_fmt, sizeof(struct v4l2_pix_format_mplane)); inst->colorspace = V4L2_COLORSPACE_REC709; inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; inst->hsv_enc = 0; -- 2.7.4 From ba32ea8fc4196f4ef618ca37f1dcdd3d9dbaa3a2 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Thu, 9 Feb 2023 10:31:40 +0800 Subject: [PATCH 06/16] Media:wave5: wave5 v4l2 driver support gst/ffmpeg Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit 3f710b8fa137 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel - update sifive cache function name properly and add guard for its config option] Signed-off-by: Seung-Woo Kim Change-Id: Ib264712e893c737a28c42a566607b7a55d7f7117 --- .../platform/chips-media/wave5/wave5-helper.c | 12 +- .../platform/chips-media/wave5/wave5-helper.h | 2 +- .../media/platform/chips-media/wave5/wave5-hw.c | 35 +++- .../media/platform/chips-media/wave5/wave5-vdi.c | 14 +- .../platform/chips-media/wave5/wave5-vpu-dec.c | 181 +++++++++++++++------ .../platform/chips-media/wave5/wave5-vpuapi.h | 3 + 6 files changed, 180 insertions(+), 67 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c index fb9c94d..09dfb20 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.c +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c @@ -47,7 +47,7 @@ int wave5_vpu_release_device(struct file *filp, break; if (fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING) break; - if (!wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT)) + if (!wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT/10)) break; } while (--retry_count); @@ -106,7 +106,6 @@ int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscr { struct vpu_instance *inst = wave5_to_vpu_inst(fh); bool is_decoder = inst->type == VPU_INST_TYPE_DEC; - printk("wave5 subscribe event type: %d id: %d | flags: %d\n",sub->type, sub->id, sub->flags); dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__, is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags); @@ -130,8 +129,13 @@ int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f) struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i; - f->fmt.pix_mp.width = inst->src_fmt.width; - f->fmt.pix_mp.height = inst->src_fmt.height; + if (inst->state >= VPU_INST_STATE_INIT_SEQ){ + f->fmt.pix_mp.width = inst->src_fmt.width - inst->crop_rect.right; + f->fmt.pix_mp.height = inst->src_fmt.height - inst->crop_rect.bottom; + } else { + f->fmt.pix_mp.width = inst->src_fmt.width; + f->fmt.pix_mp.height = inst->src_fmt.height; + } f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat; f->fmt.pix_mp.field = inst->src_fmt.field; f->fmt.pix_mp.flags = inst->src_fmt.flags; diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h index d586d62..8a8dda8 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.h +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h @@ -11,7 +11,7 @@ #include "wave5-vpu.h" #define FMT_TYPES 2 -#define MAX_FMTS 6 +#define MAX_FMTS 3 void wave5_cleanup_instance(struct vpu_instance *inst); int wave5_vpu_release_device(struct file *filp, diff --git a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c index 3c83286..57bbc38 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-hw.c +++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c @@ -584,6 +584,17 @@ static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initi info->f_rate_numerator = vpu_read_reg(inst->dev, W5_RET_DEC_FRAME_RATE_NR); info->f_rate_denominator = vpu_read_reg(inst->dev, W5_RET_DEC_FRAME_RATE_DR); + if (info->f_rate_numerator > 0 && info->f_rate_denominator >0) { + if (inst->std == W_HEVC_DEC) + info->ns_per_frame = 1000000000 * (u64)info->f_rate_denominator / (u64)info->f_rate_numerator; + else if (inst->std == W_AVC_DEC) + info->ns_per_frame = 1000000000 * 2 * (u64)info->f_rate_denominator / (u64)info->f_rate_numerator; + else + info->ns_per_frame = 1000000000 / 30; //30fps + } else { + info->ns_per_frame = 1000000000 / 30; //30fps + } + reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_COLOR_SAMPLE_INFO); info->luma_bitdepth = reg_val & 0xf; info->chroma_bitdepth = (reg_val >> 4) & 0xf; @@ -820,10 +831,15 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b p_dec_info->vb_fbc_c_tbl[i] = vb_buf; } } - pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); - if (init_info->pic_width != inst->display_fmt.width || - init_info->pic_height != inst->display_fmt.height) + + if ((init_info->pic_width - init_info->pic_crop_rect.right != inst->display_fmt.width) || + init_info->pic_height - init_info->pic_crop_rect.bottom != inst->display_fmt.height) { + pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); scale_en = 1; + } else { + pic_size = (init_info->pic_width << 16) | (init_info->pic_height); + scale_en = 0; + } // allocate task_buffer vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) + @@ -839,10 +855,14 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b p_dec_info->vb_task.daddr); vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_buf.size); } else { - pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); - if (init_info->pic_width != inst->display_fmt.width || - init_info->pic_height != inst->display_fmt.height) + if ((init_info->pic_width - init_info->pic_crop_rect.right != inst->display_fmt.width) || + init_info->pic_height - init_info->pic_crop_rect.bottom != inst->display_fmt.height) { + pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); scale_en = 1; + } else { + pic_size = (init_info->pic_width << 16) | (init_info->pic_height); + scale_en = 0; + } } dev_dbg(inst->dev->dev, "set pic_size 0x%x\n", pic_size); endian = wave5_vdi_convert_endian(inst->dev, fb_arr[0].endian); @@ -859,7 +879,8 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b (color_format << 19) | (nv21 << 17) | (cbcr_interleave << 16) | - inst->display_fmt.width; + (scale_en ? inst->display_fmt.width : fb_arr[0].stride); + //inst->display_fmt.width; dev_dbg(inst->dev->dev, "set W5_COMMON_PIC_INFO 0x%x\n",reg_val); vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, reg_val); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c index ec8b6cb..e2b7dab 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c @@ -10,7 +10,9 @@ #include "wave5-vpu.h" #include "wave5-regdefine.h" #include +#ifdef CONFIG_SIFIVE_FLUSH #include +#endif #define VDI_SRAM_BASE_ADDR 0x00 @@ -95,7 +97,9 @@ int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) } memset(vb->vaddr, 0, vb->size); - sifive_l2_flush64_range(vb->daddr, vb->size); +#ifdef CONFIG_SIFIVE_FLUSH + sifive_flush64_range(vb->daddr, vb->size); +#endif return vb->size; } @@ -117,7 +121,9 @@ int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_ wave5_swap_endian(vpu_dev, data, len, endian); memcpy(vb->vaddr + offset, data, len); - sifive_l2_flush64_range(vb->daddr + offset, len); +#ifdef CONFIG_SIFIVE_FLUSH + sifive_flush64_range(vb->daddr + offset, len); +#endif return len; } @@ -138,7 +144,9 @@ int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb vb->vaddr = vaddr; vb->daddr = daddr; - sifive_l2_flush64_range(daddr, vb->size); +#ifdef CONFIG_SIFIVE_FLUSH + sifive_flush64_range(daddr, vb->size); +#endif return 0; } 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 bba48cb..275db3e 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -29,7 +29,7 @@ static const struct vpu_format dec_fmt_list[FMT_TYPES][MAX_FMTS] = { }, }, [VPU_FMT_TYPE_RAW] = { - { + /*{ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420, .max_width = 8192, .min_width = 8, @@ -49,7 +49,7 @@ static const struct vpu_format dec_fmt_list[FMT_TYPES][MAX_FMTS] = { .min_width = 8, .max_height = 4320, .min_height = 8, - }, + },*/ { .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M, .max_width = 8192, @@ -202,6 +202,46 @@ static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: pix_mp->width = round_up(width, 32); + pix_mp->height = round_up(height, 16); + pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); + pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2; + break; + case V4L2_PIX_FMT_YUV420M: + pix_mp->width = round_up(width, 32); + pix_mp->height = round_up(height, 16); + pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); + pix_mp->plane_fmt[0].sizeimage = width * height; + pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2; + pix_mp->plane_fmt[1].sizeimage = width * height / 4; + pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2; + pix_mp->plane_fmt[2].sizeimage = width * height / 4; + break; + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV21M: + pix_mp->width = round_up(width, 32); + pix_mp->height = round_up(height, 16); + pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); + pix_mp->plane_fmt[0].sizeimage = width * height; + pix_mp->plane_fmt[1].bytesperline = round_up(width, 32); + pix_mp->plane_fmt[1].sizeimage = width * height / 2; + break; + default: + pix_mp->width = width; + pix_mp->height = height; + pix_mp->plane_fmt[0].bytesperline = 0; + pix_mp->plane_fmt[0].sizeimage = width * height; + break; + } +} + +static void wave5_update_pix_fmt_r8(struct v4l2_pix_format_mplane *pix_mp, unsigned int width, + unsigned int height) +{ + switch (pix_mp->pixelformat) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + pix_mp->width = round_up(width, 32); pix_mp->height = round_up(height, 8); pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2; @@ -261,6 +301,7 @@ static void wave5_vpu_dec_start_decode(struct vpu_instance *inst) src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx); inst->state = VPU_INST_STATE_STOP; + //printk("%d wave5 state = %d\n",__LINE__, inst->state); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); } } @@ -271,6 +312,7 @@ static void wave5_vpu_dec_stop_decode(struct vpu_instance *inst) int ret; inst->state = VPU_INST_STATE_STOP; + //printk("%d wave5 state = %d\n",__LINE__, inst->state); ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0); if (ret) { @@ -314,14 +356,12 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) struct vb2_v4l2_buffer *dst_buf = v4l2_m2m_dst_buf_remove_by_idx(inst->v4l2_fh.m2m_ctx, dec_output_info.index_frame_display); - int stride = dec_output_info.disp_frame.stride; - int height = dec_output_info.disp_pic_height - - dec_output_info.rc_display.bottom; - if (dec_output_info.disp_pic_height != inst->display_fmt.height) - height = inst->display_fmt.height; + + int stride = inst->display_fmt.width; + int height =inst->display_fmt.height; dev_dbg(inst->dev->dev, "%s %d disp_pic_height %u rc_display.bottom %u\n", __func__, __LINE__, dec_output_info.disp_pic_height, dec_output_info.rc_display.bottom); - dev_dbg(inst->dev->dev, "%s %d stride %u height %u\n", __func__, __LINE__, stride, height); + dev_dbg(inst->dev->dev, "%s %d stride %u height %u num %d\n", __func__, __LINE__, stride, height,inst->dst_fmt.num_planes); if (inst->dst_fmt.num_planes == 1) { vb2_set_plane_payload(&dst_buf->vb2_buf, 0, @@ -340,7 +380,12 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) ((stride / 2) * (height / 2))); } - dst_buf->vb2_buf.timestamp = inst->timestamp; + if (inst->timestamp) { + dst_buf->vb2_buf.timestamp = inst->timestamp; + } else { + dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + } + dst_buf->field = V4L2_FIELD_NONE; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); @@ -380,7 +425,7 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); inst->eos = TRUE; - pr_err("wave5 queue event type: %d id: %d\n",vpu_event_eos.type, vpu_event_eos.id); + //pr_err("wave5 queue event type: %d id: %d\n",vpu_event_eos.type, vpu_event_eos.id); v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos); v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx); @@ -453,7 +498,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo if (!vpu_fmt) { f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; - wave5_update_pix_fmt(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height); + wave5_update_pix_fmt_r8(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height); } else { int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width); int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height); @@ -461,7 +506,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt; f->fmt.pix_mp.num_planes = info->mem_planes; - wave5_update_pix_fmt(&f->fmt.pix_mp, width, height); + wave5_update_pix_fmt_r8(&f->fmt.pix_mp, width, height); } f->fmt.pix_mp.flags = 0; @@ -482,7 +527,7 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form int i, ret; unsigned int scalew, scaleh; - printk( + dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n", __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field); @@ -495,28 +540,30 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form scalew = inst->src_fmt.width / f->fmt.pix_mp.width; scaleh = inst->src_fmt.height / f->fmt.pix_mp.height; - if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { - dev_err(inst->dev->dev,"Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter. \n"); - return -EINVAL; - } - - inst->dst_fmt.width = f->fmt.pix_mp.width; - inst->dst_fmt.height = f->fmt.pix_mp.height; + //if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { + // dev_err(inst->dev->dev,"Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter. \n"); + // return -EINVAL; + //} + + inst->display_fmt.width = f->fmt.pix_mp.width; + inst->display_fmt.height = f->fmt.pix_mp.height; + inst->display_fmt.pixelformat = f->fmt.pix_mp.pixelformat; + inst->display_fmt.field = f->fmt.pix_mp.field; + inst->display_fmt.flags = f->fmt.pix_mp.flags; + inst->display_fmt.num_planes = f->fmt.pix_mp.num_planes; inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat; - inst->dst_fmt.field = f->fmt.pix_mp.field; - inst->dst_fmt.flags = f->fmt.pix_mp.flags; inst->dst_fmt.num_planes = f->fmt.pix_mp.num_planes; - for (i = 0; i < inst->dst_fmt.num_planes; i++) { - inst->dst_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; - inst->dst_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; + for (i = 0; i < inst->display_fmt.num_planes; i++) { + inst->display_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; + inst->display_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; } - if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12 || - inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { + if (inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV12 || + inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { inst->cbcr_interleave = true; inst->nv21 = false; - } else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21 || - inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { + } else if (inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV21 || + inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { inst->cbcr_interleave = true; inst->nv21 = true; } else { @@ -524,8 +571,6 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form inst->nv21 = false; } - memcpy((void *)&inst->display_fmt, (void *)&inst->dst_fmt, sizeof(struct v4l2_pix_format_mplane)); - return 0; } @@ -610,11 +655,12 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i, ret; - printk( + dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); + ret = wave5_vpu_dec_try_fmt_out(file, fh, f); if (ret) return ret; @@ -636,7 +682,9 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form inst->quantization = f->fmt.pix_mp.quantization; inst->xfer_func = f->fmt.pix_mp.xfer_func; - wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); + + wave5_update_pix_fmt_r8(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); + wave5_update_pix_fmt_r8(&inst->display_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); return 0; } @@ -713,7 +761,10 @@ static int wave5_vpu_dec_decoder_cmd(struct file *file, void *fh, struct v4l2_de switch (dc->cmd) { case V4L2_DEC_CMD_STOP: + wave5_handle_bitstream_buffer(inst); + inst->ops->start_process(inst); inst->state = VPU_INST_STATE_STOP; + //printk("%d wave5 state = %d\n",__LINE__, inst->state); ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0); if (ret) { @@ -854,6 +905,8 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff if (inst->state == VPU_INST_STATE_NONE && q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { struct dec_open_param open_param; + *num_buffers = 4; + memset(&open_param, 0, sizeof(struct dec_open_param)); wave5_set_default_dec_openparam(&open_param); @@ -883,6 +936,7 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff } inst->state = VPU_INST_STATE_OPEN; + //printk("wave5 state = %d\n",inst->state); if (inst->thumbnail_mode) wave5_vpu_dec_give_command(inst, ENABLE_DEC_THUMBNAIL_MODE, NULL); @@ -893,9 +947,9 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff u32 fb_stride, fb_height; u32 luma_size, chroma_size; - if (*num_buffers > inst->min_dst_buf_count && - *num_buffers < WAVE5_MAX_FBS) - inst->dst_buf_count = *num_buffers; + //if (*num_buffers > inst->min_dst_buf_count && + // *num_buffers < WAVE5_MAX_FBS) + // inst->dst_buf_count = *num_buffers; *num_buffers = inst->dst_buf_count; non_linear_num = inst->dst_buf_count; @@ -951,17 +1005,17 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) ret = wave5_vpu_dec_issue_seq_init(inst); if (ret) { - dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_issue_seq_init, fail: %d\n", + dev_err(inst->dev->dev, "%s: wave5_vpu_dec_issue_seq_init, fail: %d\n", __func__, ret); return ret; } if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0) - dev_dbg(inst->dev->dev, "%s: failed to call vpu_wait_interrupt()\n", __func__); + dev_err(inst->dev->dev, "%s: failed to call vpu_wait_interrupt()\n", __func__); ret = wave5_vpu_dec_complete_seq_init(inst, &initial_info); if (ret) { - dev_dbg(inst->dev->dev, "%s: vpu_dec_complete_seq_init, fail: %d, reason: %u\n", + dev_err(inst->dev->dev, "%s: vpu_dec_complete_seq_init, fail: %d, reason: %u\n", __func__, ret, initial_info.seq_init_err_reason); } else { static const struct v4l2_event vpu_event_src_ch = { @@ -975,6 +1029,7 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) initial_info.profile, initial_info.min_frame_buffer_count); inst->state = VPU_INST_STATE_INIT_SEQ; + //printk("wave5 state = %d\n",inst->state); inst->min_dst_buf_count = initial_info.min_frame_buffer_count + 1; inst->dst_buf_count = inst->min_dst_buf_count; @@ -988,11 +1043,20 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) if (initial_info.pic_width != inst->src_fmt.width || initial_info.pic_height != inst->src_fmt.height) { - wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, - initial_info.pic_height); - wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, - initial_info.pic_height); + if (inst->std == W_AVC_DEC) { + wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, + initial_info.pic_height); + wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, + initial_info.pic_height); + } else { //HEVC + wave5_update_pix_fmt_r8(&inst->src_fmt, initial_info.pic_width, + initial_info.pic_height); + wave5_update_pix_fmt_r8(&inst->dst_fmt, initial_info.pic_width, + initial_info.pic_height); + } } + inst->crop_rect.right = initial_info.pic_crop_rect.right; + inst->crop_rect.bottom = initial_info.pic_crop_rect.bottom; scalew = inst->dst_fmt.width / inst->display_fmt.width; scaleh = inst->dst_fmt.height / inst->display_fmt.height; @@ -1002,7 +1066,7 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) inst->dst_fmt.height); } - printk("wave5 queue event type: %d id: %d\n",vpu_event_src_ch.type, vpu_event_src_ch.id); + dev_dbg(inst->dev->dev, "wave5 queue event type: %d id: %d\n",vpu_event_src_ch.type, vpu_event_src_ch.id); v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch); wave5_handle_src_buffer(inst); @@ -1028,6 +1092,7 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx); inst->state = VPU_INST_STATE_STOP; + //printk("%d wave5 state = %d\n",__LINE__, inst->state); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_start_one_frame\n", __func__); return ret; @@ -1070,11 +1135,20 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) if (initial_info.pic_width != inst->src_fmt.width || initial_info.pic_height != inst->src_fmt.height) { - wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, - initial_info.pic_height); - wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, - initial_info.pic_height); + if (inst->std == W_AVC_DEC) { + wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, + initial_info.pic_height); + wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, + initial_info.pic_height); + } else { //HEVC + wave5_update_pix_fmt_r8(&inst->src_fmt, initial_info.pic_width, + initial_info.pic_height); + wave5_update_pix_fmt_r8(&inst->dst_fmt, initial_info.pic_width, + initial_info.pic_height); + } } + inst->crop_rect.right = initial_info.pic_crop_rect.right; + inst->crop_rect.bottom = initial_info.pic_crop_rect.bottom; scalew = inst->dst_fmt.width / inst->display_fmt.width; scaleh = inst->dst_fmt.height / inst->display_fmt.height; @@ -1172,8 +1246,8 @@ static void wave5_vpu_dec_buf_queue(struct vb2_buffer *vb) struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue); dev_dbg(inst->dev->dev, "%s: type: %4u index: %4u size: ([0]=%4lu, [1]=%4lu, [2]=%4lu)\n", - __func__, vb->type, vb->index, vb2_plane_size(&vbuf->vb2_buf, 0), - vb2_plane_size(&vbuf->vb2_buf, 1), vb2_plane_size(&vbuf->vb2_buf, 2)); + __func__, vb->type, vb->index, vb2_get_plane_payload(&vbuf->vb2_buf, 0), + vb2_get_plane_payload(&vbuf->vb2_buf, 1), vb2_get_plane_payload(&vbuf->vb2_buf, 2)); v4l2_m2m_buf_queue(inst->v4l2_fh.m2m_ctx, vbuf); @@ -1215,6 +1289,7 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) { struct vpu_instance *inst = vb2_get_drv_priv(q); struct vb2_v4l2_buffer *buf; + int try_cnt = 0; bool check_cmd = TRUE; dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type); @@ -1222,7 +1297,6 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) while (check_cmd) { struct queue_status_info q_status; struct dec_output_info dec_output_info; - int try_cnt = 0; wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); @@ -1231,7 +1305,7 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) if (wave5_vpu_wait_interrupt(inst, 600) < 0){ try_cnt++; - if (try_cnt >= 100) + if (try_cnt >= 10) break; continue; } @@ -1288,6 +1362,7 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) if (inst->eos) { inst->eos = FALSE; inst->state = VPU_INST_STATE_INIT_SEQ; + //printk("wave5 state = %d\n",inst->state); } inst->queued_dst_buf_num = 0; } @@ -1336,9 +1411,11 @@ static void wave5_vpu_dec_device_run(void *priv) { struct vpu_instance *inst = priv; + wave5_handle_bitstream_buffer(inst); inst->ops->start_process(inst); inst->state = VPU_INST_STATE_PIC_RUN; + //printk("wave5 state = %d\n",inst->state); } static void wave5_vpu_dec_job_abort(void *priv) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h index 0a4dc20..dcd061b1 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h @@ -473,6 +473,7 @@ struct dec_initial_info { u32 pic_height; s32 f_rate_numerator; /* the numerator part of frame rate fraction */ s32 f_rate_denominator; /* the denominator part of frame rate fraction */ + u64 ns_per_frame; struct vpu_rect pic_crop_rect; u32 min_frame_buffer_count; /* between 1 to 16 */ u32 frame_buf_delay; @@ -1057,6 +1058,7 @@ struct vpu_instance { enum vpu_instance_state state; enum vpu_instance_type type; const struct vpu_instance_ops *ops; + struct vpu_rect crop_rect; enum wave_std std; s32 id; @@ -1073,6 +1075,7 @@ struct vpu_instance { u32 conf_win_width; u32 conf_win_height; u64 timestamp; + u64 timestamp_cnt; bool cbcr_interleave; bool nv21; bool eos; -- 2.7.4 From 24389f54f174fe64da4f681393d41e0f95a697d4 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Tue, 1 Aug 2023 14:09:12 +0800 Subject: [PATCH 07/16] Media:wave5: Fix stride mismatching of decoding frame buffers When bitstream format bitdepth > 8, stride of compressed frame map buffers shoule be recalculated. Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit a9830d5d01e9 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I58b550e525c8dde7175d09c2934f4f81e08df3fc --- drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 275db3e..f3e8124 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -958,7 +958,14 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff struct frame_buffer *frame = &inst->frame_buf[i]; struct vpu_buf *vframe = &inst->frame_vbuf[i]; - fb_stride = inst->dst_fmt.width; + if (inst->codec_info->dec_info.initial_info.luma_bitdepth > 8 || + inst->codec_info->dec_info.initial_info.chroma_bitdepth > 8) { + fb_stride = ALIGN(ALIGN(inst->dst_fmt.width, 16) * 5, 32) / 4; + fb_stride = ALIGN(fb_stride, 32); + } else { + fb_stride = inst->dst_fmt.width; + } + fb_height = ALIGN(inst->dst_fmt.height, 32); luma_size = fb_stride * fb_height; chroma_size = ALIGN(fb_stride / 2, 16) * fb_height; -- 2.7.4 From f7766ab98ce710f711846b1aa72a88526318f60a Mon Sep 17 00:00:00 2001 From: Som Qin Date: Tue, 1 Aug 2023 15:03:59 +0800 Subject: [PATCH 08/16] Media:wave5: Driver get clks from DTS instead of hard coding. Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit 167fdf2d4c34 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I31ecc8cb300d21ab95c231d14875dcac93e337a6 --- .../media/platform/chips-media/wave5/wave5-vpu.c | 38 +++++----------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c index 176bbe7..e378817 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c @@ -25,40 +25,11 @@ #define WAVE5_IS_ENC BIT(0) #define WAVE5_IS_DEC BIT(1) -struct clk_bulk_data vpu_clks[] = { - { .id = "apb_clk" }, - { .id = "axi_clk" }, - { .id = "bpu_clk" }, - { .id = "vce_clk" }, - { .id = "noc_bus" }, -}; - struct wave5_match_data { int flags; const char *fw_name; }; -static int vpu_clk_get(struct platform_device *pdev, struct vpu_device *vpu) -{ - struct device *dev = &pdev->dev; - int ret; - - vpu->clks = vpu_clks; - vpu->num_clks = ARRAY_SIZE(vpu_clks); - - vpu->resets = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(vpu->resets)) { - ret = PTR_ERR(vpu->resets); - dev_err(dev, "faied to get vpu reset controls\n"); - } - - ret = devm_clk_bulk_get(dev, vpu->num_clks, vpu->clks); - if (ret) - dev_err(dev, "faied to get vpu clk controls\n"); - - return 0; -} - int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout) { int ret; @@ -229,13 +200,20 @@ static int wave5_vpu_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, dev); dev->dev = &pdev->dev; - ret = vpu_clk_get(pdev, dev); + ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks); /* continue without clock, assume externally managed */ if (ret < 0) { dev_err(&pdev->dev, "Getting clocks, fail: %d\n", ret); return ret; } + dev->num_clks = ret; + + dev->resets = devm_reset_control_array_get_exclusive(&pdev->dev); + if (IS_ERR(dev->resets)) { + dev_err(&pdev->dev, "faied to get vpu reset controls\n"); + return -ENODEV; + } dev->sram_buf.daddr = VDI_SRAM_BASE_ADDR; dev->sram_buf.size = VDI_WAVE511_SRAM_SIZE; -- 2.7.4 From 976e12158ed88fa74dd92a1d70a38be62484ff1c Mon Sep 17 00:00:00 2001 From: Som Qin Date: Wed, 2 Aug 2023 11:38:51 +0800 Subject: [PATCH 09/16] Media:Wave5: Add contiguous planes format support (YUV420/NV12/NV21) Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit 80c6e7df80bd from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I4203a253b3c7577a5849ca2582099a2cf07985ea --- drivers/media/platform/chips-media/wave5/wave5-helper.h | 2 +- drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h index 8a8dda8..d586d62 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.h +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h @@ -11,7 +11,7 @@ #include "wave5-vpu.h" #define FMT_TYPES 2 -#define MAX_FMTS 3 +#define MAX_FMTS 6 void wave5_cleanup_instance(struct vpu_instance *inst); int wave5_vpu_release_device(struct file *filp, 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 f3e8124..5d10f3c 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -29,43 +29,43 @@ static const struct vpu_format dec_fmt_list[FMT_TYPES][MAX_FMTS] = { }, }, [VPU_FMT_TYPE_RAW] = { - /*{ - .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M, .max_width = 8192, .min_width = 8, .max_height = 4320, .min_height = 8, }, { - .v4l2_pix_fmt = V4L2_PIX_FMT_NV12, + .v4l2_pix_fmt = V4L2_PIX_FMT_NV12M, .max_width = 8192, .min_width = 8, .max_height = 4320, .min_height = 8, }, { - .v4l2_pix_fmt = V4L2_PIX_FMT_NV21, + .v4l2_pix_fmt = V4L2_PIX_FMT_NV21M, .max_width = 8192, .min_width = 8, .max_height = 4320, .min_height = 8, - },*/ + }, { - .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M, + .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420, .max_width = 8192, .min_width = 8, .max_height = 4320, .min_height = 8, }, { - .v4l2_pix_fmt = V4L2_PIX_FMT_NV12M, + .v4l2_pix_fmt = V4L2_PIX_FMT_NV12, .max_width = 8192, .min_width = 8, .max_height = 4320, .min_height = 8, }, { - .v4l2_pix_fmt = V4L2_PIX_FMT_NV21M, + .v4l2_pix_fmt = V4L2_PIX_FMT_NV21, .max_width = 8192, .min_width = 8, .max_height = 4320, -- 2.7.4 From 558180255bc2e49ee39b722bf778397c6bdd31a4 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Mon, 7 Aug 2023 15:21:30 +0800 Subject: [PATCH 10/16] Media:Wave5: Fix driver compile warning Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit 5d74ac40d250 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: If42384286243423071abcd9ab2107c0507bdc4e8 --- drivers/media/platform/chips-media/wave5/wave5-vdi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c index e2b7dab..4a0e4b8 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c @@ -14,7 +14,6 @@ #include #endif -#define VDI_SRAM_BASE_ADDR 0x00 #define VDI_SYSTEM_ENDIAN VDI_LITTLE_ENDIAN #define VDI_128BIT_BUS_SYSTEM_ENDIAN VDI_128BIT_LITTLE_ENDIAN -- 2.7.4 From 4c5ae89039866e3da630a929df9c2b81652ab28f Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 25 Aug 2023 16:13:01 +0800 Subject: [PATCH 11/16] Media: Wave5: Fix plane size mismatch Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit b4e474a223e8 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: If69aaf750c83daf21b57c459f576ee2200f9c40e --- .../media/platform/chips-media/wave5/wave5-hw.c | 24 +-- .../platform/chips-media/wave5/wave5-vpu-dec.c | 181 +++++---------------- .../platform/chips-media/wave5/wave5-vpuapi.h | 1 - 3 files changed, 47 insertions(+), 159 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c index 57bbc38..fdc5c7e 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-hw.c +++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c @@ -729,7 +729,6 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b struct vpu_buf vb_buf; u32 color_format = 0; u32 pixel_order = 1; - u32 scale_en = 0; u32 bwb_flag = (map_type == LINEAR_FRAME_MAP) ? 1 : 0; cbcr_interleave = inst->cbcr_interleave; @@ -831,15 +830,7 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b p_dec_info->vb_fbc_c_tbl[i] = vb_buf; } } - - if ((init_info->pic_width - init_info->pic_crop_rect.right != inst->display_fmt.width) || - init_info->pic_height - init_info->pic_crop_rect.bottom != inst->display_fmt.height) { - pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); - scale_en = 1; - } else { - pic_size = (init_info->pic_width << 16) | (init_info->pic_height); - scale_en = 0; - } + pic_size = (init_info->pic_width << 16) | (init_info->pic_height); // allocate task_buffer vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) + @@ -855,14 +846,7 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b p_dec_info->vb_task.daddr); vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_buf.size); } else { - if ((init_info->pic_width - init_info->pic_crop_rect.right != inst->display_fmt.width) || - init_info->pic_height - init_info->pic_crop_rect.bottom != inst->display_fmt.height) { - pic_size = (inst->display_fmt.width << 16) | (inst->display_fmt.height); - scale_en = 1; - } else { - pic_size = (init_info->pic_width << 16) | (init_info->pic_height); - scale_en = 0; - } + pic_size = (init_info->pic_width << 16) | (init_info->pic_height); } dev_dbg(inst->dev->dev, "set pic_size 0x%x\n", pic_size); endian = wave5_vdi_convert_endian(inst->dev, fb_arr[0].endian); @@ -872,15 +856,13 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b color_format = 0; reg_val = - (scale_en << 29) | (bwb_flag << 28) | (pixel_order << 23) | /* PIXEL ORDER in 128bit. first pixel in low address */ (yuv_format << 20) | (color_format << 19) | (nv21 << 17) | (cbcr_interleave << 16) | - (scale_en ? inst->display_fmt.width : fb_arr[0].stride); - //inst->display_fmt.width; + (fb_arr[0].stride); dev_dbg(inst->dev->dev, "set W5_COMMON_PIC_INFO 0x%x\n",reg_val); vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, reg_val); 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 5d10f3c..481273d 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -234,46 +234,6 @@ static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned } } -static void wave5_update_pix_fmt_r8(struct v4l2_pix_format_mplane *pix_mp, unsigned int width, - unsigned int height) -{ - switch (pix_mp->pixelformat) { - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - pix_mp->width = round_up(width, 32); - pix_mp->height = round_up(height, 8); - pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); - pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2; - break; - case V4L2_PIX_FMT_YUV420M: - pix_mp->width = round_up(width, 32); - pix_mp->height = round_up(height, 8); - pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); - pix_mp->plane_fmt[0].sizeimage = width * height; - pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2; - pix_mp->plane_fmt[1].sizeimage = width * height / 4; - pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2; - pix_mp->plane_fmt[2].sizeimage = width * height / 4; - break; - case V4L2_PIX_FMT_NV12M: - case V4L2_PIX_FMT_NV21M: - pix_mp->width = round_up(width, 32); - pix_mp->height = round_up(height, 8); - pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); - pix_mp->plane_fmt[0].sizeimage = width * height; - pix_mp->plane_fmt[1].bytesperline = round_up(width, 32); - pix_mp->plane_fmt[1].sizeimage = width * height / 2; - break; - default: - pix_mp->width = width; - pix_mp->height = height; - pix_mp->plane_fmt[0].bytesperline = 0; - pix_mp->plane_fmt[0].sizeimage = width * height; - break; - } -} - static void wave5_vpu_dec_start_decode(struct vpu_instance *inst) { struct dec_param pic_param; @@ -301,7 +261,6 @@ static void wave5_vpu_dec_start_decode(struct vpu_instance *inst) src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx); inst->state = VPU_INST_STATE_STOP; - //printk("%d wave5 state = %d\n",__LINE__, inst->state); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); } } @@ -312,7 +271,6 @@ static void wave5_vpu_dec_stop_decode(struct vpu_instance *inst) int ret; inst->state = VPU_INST_STATE_STOP; - //printk("%d wave5 state = %d\n",__LINE__, inst->state); ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0); if (ret) { @@ -337,6 +295,7 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) struct dec_output_info dec_output_info; int ret; u32 irq_status; + u32 stride, height; if (kfifo_out(&inst->irq_status, &irq_status, sizeof(int))) wave5_vpu_clear_interrupt_ex(inst, irq_status); @@ -357,8 +316,9 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) v4l2_m2m_dst_buf_remove_by_idx(inst->v4l2_fh.m2m_ctx, dec_output_info.index_frame_display); - int stride = inst->display_fmt.width; - int height =inst->display_fmt.height; + stride = dec_output_info.disp_frame.stride; + height = dec_output_info.disp_pic_height - + dec_output_info.rc_display.bottom; dev_dbg(inst->dev->dev, "%s %d disp_pic_height %u rc_display.bottom %u\n", __func__, __LINE__, dec_output_info.disp_pic_height, dec_output_info.rc_display.bottom); dev_dbg(inst->dev->dev, "%s %d stride %u height %u num %d\n", __func__, __LINE__, stride, height,inst->dst_fmt.num_planes); @@ -425,7 +385,6 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); inst->eos = TRUE; - //pr_err("wave5 queue event type: %d id: %d\n",vpu_event_eos.type, vpu_event_eos.id); v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos); v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx); @@ -498,7 +457,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo if (!vpu_fmt) { f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; - wave5_update_pix_fmt_r8(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height); + wave5_update_pix_fmt(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height); } else { int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width); int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height); @@ -506,7 +465,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt; f->fmt.pix_mp.num_planes = info->mem_planes; - wave5_update_pix_fmt_r8(&f->fmt.pix_mp, width, height); + wave5_update_pix_fmt(&f->fmt.pix_mp, width, height); } f->fmt.pix_mp.flags = 0; @@ -525,7 +484,6 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form { struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i, ret; - unsigned int scalew, scaleh; dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n", @@ -533,37 +491,26 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field); ret = wave5_vpu_dec_try_fmt_cap(file, fh, f); - if (ret) return ret; - scalew = inst->src_fmt.width / f->fmt.pix_mp.width; - scaleh = inst->src_fmt.height / f->fmt.pix_mp.height; - - //if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { - // dev_err(inst->dev->dev,"Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter. \n"); - // return -EINVAL; - //} - - inst->display_fmt.width = f->fmt.pix_mp.width; - inst->display_fmt.height = f->fmt.pix_mp.height; - inst->display_fmt.pixelformat = f->fmt.pix_mp.pixelformat; - inst->display_fmt.field = f->fmt.pix_mp.field; - inst->display_fmt.flags = f->fmt.pix_mp.flags; - inst->display_fmt.num_planes = f->fmt.pix_mp.num_planes; + inst->dst_fmt.width = f->fmt.pix_mp.width; + inst->dst_fmt.height = f->fmt.pix_mp.height; inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat; + inst->dst_fmt.field = f->fmt.pix_mp.field; + inst->dst_fmt.flags = f->fmt.pix_mp.flags; inst->dst_fmt.num_planes = f->fmt.pix_mp.num_planes; - for (i = 0; i < inst->display_fmt.num_planes; i++) { - inst->display_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; - inst->display_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; + for (i = 0; i < inst->dst_fmt.num_planes; i++) { + inst->dst_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; + inst->dst_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; } - if (inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV12 || - inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { + if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12 || + inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { inst->cbcr_interleave = true; inst->nv21 = false; - } else if (inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV21 || - inst->display_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { + } else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21 || + inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { inst->cbcr_interleave = true; inst->nv21 = true; } else { @@ -579,15 +526,15 @@ static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_form struct vpu_instance *inst = wave5_to_vpu_inst(fh); int i; - f->fmt.pix_mp.width = inst->display_fmt.width; - f->fmt.pix_mp.height = inst->display_fmt.height; - f->fmt.pix_mp.pixelformat = inst->display_fmt.pixelformat; - f->fmt.pix_mp.field = inst->display_fmt.field; - f->fmt.pix_mp.flags = inst->display_fmt.flags; - f->fmt.pix_mp.num_planes = inst->display_fmt.num_planes; + f->fmt.pix_mp.width = inst->dst_fmt.width; + f->fmt.pix_mp.height = inst->dst_fmt.height; + f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; + f->fmt.pix_mp.field = inst->dst_fmt.field; + f->fmt.pix_mp.flags = inst->dst_fmt.flags; + f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { - f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->display_fmt.plane_fmt[i].bytesperline; - f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->display_fmt.plane_fmt[i].sizeimage; + f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->dst_fmt.plane_fmt[i].bytesperline; + f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->dst_fmt.plane_fmt[i].sizeimage; } f->fmt.pix_mp.colorspace = inst->colorspace; @@ -660,7 +607,6 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); - ret = wave5_vpu_dec_try_fmt_out(file, fh, f); if (ret) return ret; @@ -682,9 +628,7 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form inst->quantization = f->fmt.pix_mp.quantization; inst->xfer_func = f->fmt.pix_mp.xfer_func; - - wave5_update_pix_fmt_r8(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); - wave5_update_pix_fmt_r8(&inst->display_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); + wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); return 0; } @@ -764,7 +708,6 @@ static int wave5_vpu_dec_decoder_cmd(struct file *file, void *fh, struct v4l2_de wave5_handle_bitstream_buffer(inst); inst->ops->start_process(inst); inst->state = VPU_INST_STATE_STOP; - //printk("%d wave5 state = %d\n",__LINE__, inst->state); ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0); if (ret) { @@ -865,7 +808,7 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff { struct vpu_instance *inst = vb2_get_drv_priv(q); struct v4l2_pix_format_mplane inst_format = - (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->display_fmt; + (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt; unsigned int i; int ret; @@ -936,7 +879,6 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff } inst->state = VPU_INST_STATE_OPEN; - //printk("wave5 state = %d\n",inst->state); if (inst->thumbnail_mode) wave5_vpu_dec_give_command(inst, ENABLE_DEC_THUMBNAIL_MODE, NULL); @@ -1005,7 +947,6 @@ free_bitstream_vbuf: static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) { struct dec_initial_info initial_info; - unsigned int scalew, scaleh; int ret = 0; memset(&initial_info, 0, sizeof(struct dec_initial_info)); @@ -1036,7 +977,6 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) initial_info.profile, initial_info.min_frame_buffer_count); inst->state = VPU_INST_STATE_INIT_SEQ; - //printk("wave5 state = %d\n",inst->state); inst->min_dst_buf_count = initial_info.min_frame_buffer_count + 1; inst->dst_buf_count = inst->min_dst_buf_count; @@ -1050,29 +990,15 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) if (initial_info.pic_width != inst->src_fmt.width || initial_info.pic_height != inst->src_fmt.height) { - if (inst->std == W_AVC_DEC) { - wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, - initial_info.pic_height); - wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, - initial_info.pic_height); - } else { //HEVC - wave5_update_pix_fmt_r8(&inst->src_fmt, initial_info.pic_width, - initial_info.pic_height); - wave5_update_pix_fmt_r8(&inst->dst_fmt, initial_info.pic_width, - initial_info.pic_height); - } + wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, + initial_info.pic_height); + wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, + initial_info.pic_height); } + inst->crop_rect.right = initial_info.pic_crop_rect.right; inst->crop_rect.bottom = initial_info.pic_crop_rect.bottom; - scalew = inst->dst_fmt.width / inst->display_fmt.width; - scaleh = inst->dst_fmt.height / inst->display_fmt.height; - - if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { - wave5_update_pix_fmt(&inst->display_fmt, inst->dst_fmt.width, - inst->dst_fmt.height); - } - dev_dbg(inst->dev->dev, "wave5 queue event type: %d id: %d\n",vpu_event_src_ch.type, vpu_event_src_ch.id); v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch); @@ -1087,7 +1013,6 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) struct dec_initial_info initial_info; struct dec_param pic_param; struct dec_output_info dec_output_info; - unsigned int scalew, scaleh; int ret = 0; u32 fail_res = 0; @@ -1099,7 +1024,6 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx); inst->state = VPU_INST_STATE_STOP; - //printk("%d wave5 state = %d\n",__LINE__, inst->state); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_start_one_frame\n", __func__); return ret; @@ -1142,29 +1066,15 @@ static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst) if (initial_info.pic_width != inst->src_fmt.width || initial_info.pic_height != inst->src_fmt.height) { - if (inst->std == W_AVC_DEC) { - wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, - initial_info.pic_height); - wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, - initial_info.pic_height); - } else { //HEVC - wave5_update_pix_fmt_r8(&inst->src_fmt, initial_info.pic_width, - initial_info.pic_height); - wave5_update_pix_fmt_r8(&inst->dst_fmt, initial_info.pic_width, - initial_info.pic_height); - } + wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width, + initial_info.pic_height); + wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width, + initial_info.pic_height); } + inst->crop_rect.right = initial_info.pic_crop_rect.right; inst->crop_rect.bottom = initial_info.pic_crop_rect.bottom; - scalew = inst->dst_fmt.width / inst->display_fmt.width; - scaleh = inst->dst_fmt.height / inst->display_fmt.height; - - if (scalew > 8 || scaleh > 8 || scalew < 1 || scaleh < 1) { - wave5_update_pix_fmt(&inst->display_fmt, inst->dst_fmt.width, - inst->dst_fmt.height); - } - v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch); wave5_handle_src_buffer(inst); @@ -1206,22 +1116,22 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) dma_addr_t buf_addr_y = 0, buf_addr_cb = 0, buf_addr_cr = 0; u32 buf_size = 0; u32 non_linear_num = inst->dst_buf_count; - u32 fb_stride = inst->display_fmt.width; - u32 luma_size = fb_stride * inst->display_fmt.height; - u32 chroma_size = (fb_stride / 2) * (inst->display_fmt.height / 2); + u32 fb_stride = inst->dst_fmt.width; + u32 luma_size = fb_stride * inst->dst_fmt.height; + u32 chroma_size = (fb_stride / 2) * (inst->dst_fmt.height / 2); - if (inst->display_fmt.num_planes == 1) { + if (inst->dst_fmt.num_planes == 1) { buf_size = vb2_plane_size(&vbuf->vb2_buf, 0); buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); buf_addr_cb = buf_addr_y + luma_size; buf_addr_cr = buf_addr_cb + chroma_size; - } else if (inst->display_fmt.num_planes == 2) { + } else if (inst->dst_fmt.num_planes == 2) { buf_size = vb2_plane_size(&vbuf->vb2_buf, 0) + vb2_plane_size(&vbuf->vb2_buf, 1); buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); buf_addr_cb = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 1); buf_addr_cr = buf_addr_cb + chroma_size; - } else if (inst->display_fmt.num_planes == 3) { + } else if (inst->dst_fmt.num_planes == 3) { buf_size = vb2_plane_size(&vbuf->vb2_buf, 0) + vb2_plane_size(&vbuf->vb2_buf, 1) + vb2_plane_size(&vbuf->vb2_buf, 2); @@ -1233,7 +1143,7 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) inst->frame_buf[vb->index + non_linear_num].buf_cb = buf_addr_cb; inst->frame_buf[vb->index + non_linear_num].buf_cr = buf_addr_cr; inst->frame_buf[vb->index + non_linear_num].size = buf_size; - inst->frame_buf[vb->index + non_linear_num].width = inst->display_fmt.width; + inst->frame_buf[vb->index + non_linear_num].width = inst->src_fmt.width; inst->frame_buf[vb->index + non_linear_num].stride = fb_stride; inst->frame_buf[vb->index + non_linear_num].map_type = LINEAR_FRAME_MAP; inst->frame_buf[vb->index + non_linear_num].update_fb_info = true; @@ -1369,7 +1279,6 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) if (inst->eos) { inst->eos = FALSE; inst->state = VPU_INST_STATE_INIT_SEQ; - //printk("wave5 state = %d\n",inst->state); } inst->queued_dst_buf_num = 0; } @@ -1422,7 +1331,6 @@ static void wave5_vpu_dec_device_run(void *priv) inst->ops->start_process(inst); inst->state = VPU_INST_STATE_PIC_RUN; - //printk("wave5 state = %d\n",inst->state); } static void wave5_vpu_dec_job_abort(void *priv) @@ -1487,7 +1395,6 @@ static int wave5_vpu_open_dec(struct file *filp) v4l2_ctrl_handler_setup(&inst->v4l2_ctrl_hdl); wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt); - memcpy((void *)&inst->display_fmt, (void *)&inst->dst_fmt, sizeof(struct v4l2_pix_format_mplane)); inst->colorspace = V4L2_COLORSPACE_REC709; inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; inst->hsv_enc = 0; diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h index dcd061b1..892eff2 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h @@ -1048,7 +1048,6 @@ struct vpu_instance { struct v4l2_pix_format_mplane src_fmt; struct v4l2_pix_format_mplane dst_fmt; - struct v4l2_pix_format_mplane display_fmt; enum v4l2_colorspace colorspace; enum v4l2_xfer_func xfer_func; enum v4l2_ycbcr_encoding ycbcr_enc; -- 2.7.4 From f3da424fb0c8374031c517a469f62cf001d5af67 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Tue, 29 Aug 2023 10:18:47 +0800 Subject: [PATCH 12/16] Media:Wave5: Fix segment fault when finish buffer Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit 9aea96f91ea6 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: Ic2bf17247ed6ec08582d5b98b4e0be24d6a07ce0 --- drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 5 +++++ 1 file changed, 5 insertions(+) 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 481273d..fda9090 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -316,6 +316,11 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) v4l2_m2m_dst_buf_remove_by_idx(inst->v4l2_fh.m2m_ctx, dec_output_info.index_frame_display); + if (!dst_buf) { + dev_dbg(inst->dev->dev,"find no dst_buf \n"); + return; + } + stride = dec_output_info.disp_frame.stride; height = dec_output_info.disp_pic_height - dec_output_info.rc_display.bottom; -- 2.7.4 From e74f882d81d52e43c7c89ea3066647ea7cedf8c5 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Wed, 30 Aug 2023 09:23:21 +0800 Subject: [PATCH 13/16] Media:Wave5: Allocate more linear buffer to avoid block in gst-play Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit a95153b6cedf from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: I526c47f67fa196e27d7e4ad5e685252e8a034989 --- drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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 fda9090..e97b3b0 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -345,11 +345,7 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) ((stride / 2) * (height / 2))); } - if (inst->timestamp) { - dst_buf->vb2_buf.timestamp = inst->timestamp; - } else { - dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; - } + dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; dst_buf->field = V4L2_FIELD_NONE; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); @@ -897,6 +893,7 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff //if (*num_buffers > inst->min_dst_buf_count && // *num_buffers < WAVE5_MAX_FBS) // inst->dst_buf_count = *num_buffers; + inst->dst_buf_count += 2; *num_buffers = inst->dst_buf_count; non_linear_num = inst->dst_buf_count; -- 2.7.4 From 7e10d91d96d4b9b51f4b43b8105a4a7ee04c157a Mon Sep 17 00:00:00 2001 From: Som Qin Date: Wed, 30 Aug 2023 14:10:50 +0800 Subject: [PATCH 14/16] Medis:wave5: Remove inexistent including File sifive_l2_cache.h is inexistent in sdk 6.1 version. Signed-off-by: Som Qin [sw0312.kim: cherry-pick the commit ed137a80cd88 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel - Change sifive cache flush function name properly] Signed-off-by: Seung-Woo Kim Change-Id: Id9d63d72fab1ab0ddeecdb46aeaa19cb0045ed36 --- drivers/media/platform/chips-media/wave5/wave5-vdi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c index 4a0e4b8..9301dd2 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c @@ -10,11 +10,11 @@ #include "wave5-vpu.h" #include "wave5-regdefine.h" #include + #ifdef CONFIG_SIFIVE_FLUSH -#include +extern void sifive_flush64_range(unsigned long start, unsigned long len); #endif - #define VDI_SYSTEM_ENDIAN VDI_LITTLE_ENDIAN #define VDI_128BIT_BUS_SYSTEM_ENDIAN VDI_128BIT_LITTLE_ENDIAN -- 2.7.4 From fdab41d2cec76e75fc65dbddb31ee32e022c8078 Mon Sep 17 00:00:00 2001 From: Samin Guo Date: Thu, 8 Jun 2023 16:01:33 +0800 Subject: [PATCH 15/16] riscv: dts: starfive: jh7110: Add vpu/jpu nodes Add vpu/jpu nodes for jh7110 SOC Signed-off-by: Samin Guo [sw0312.kim: port the commit e2d1cdfe5ff5 from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel - Port upstream jh7110 clk and sys-reset controller macro name] Signed-off-by: Seung-Woo Kim Change-Id: Iae673d805d9549ba96f3c08ee93ea69148f68e1e --- arch/riscv/boot/dts/starfive/jh7110.dtsi | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index b3fa383..c66f130 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -996,6 +996,70 @@ status = "disabled"; }; + jpu: jpu@13090000 { + compatible = "starfive,jpu"; + reg = <0x0 0x13090000 0x0 0x300>; + interrupts = <14>; + clocks = <&syscrg JH7110_SYSCLK_CODAJ12_AXI>, + <&syscrg JH7110_SYSCLK_CODAJ12_CORE>, + <&syscrg JH7110_SYSCLK_CODAJ12_APB>, + <&syscrg JH7110_SYSCLK_NOC_BUS_VDEC_AXI>; + clock-names = "axi_clk", "core_clk", + "apb_clk", "noc_bus"; + resets = <&syscrg JH7110_SYSRST_CODAJ12_AXI>, + <&syscrg JH7110_SYSRST_CODAJ12_CORE>, + <&syscrg JH7110_SYSRST_CODAJ12_APB>; + reset-names = "rst_axi", "rst_core", "rst_apb"; + power-domains = <&pwrc JH7110_PD_VDEC>; + status = "disabled"; + }; + + vpu_dec: vpu_dec@130A0000 { + compatible = "starfive,vdec"; + reg = <0x0 0x130A0000 0x0 0x10000>; + interrupts = <13>; + clocks = <&syscrg JH7110_SYSCLK_WAVE511_AXI>, + <&syscrg JH7110_SYSCLK_WAVE511_BPU>, + <&syscrg JH7110_SYSCLK_WAVE511_VCE>, + <&syscrg JH7110_SYSCLK_WAVE511_APB>, + <&syscrg JH7110_SYSCLK_NOC_BUS_VDEC_AXI>; + clock-names = "axi_clk", "bpu_clk", "vce_clk", + "apb_clk", "noc_bus"; + resets = <&syscrg JH7110_SYSRST_WAVE511_AXI>, + <&syscrg JH7110_SYSRST_WAVE511_BPU>, + <&syscrg JH7110_SYSRST_WAVE511_VCE>, + <&syscrg JH7110_SYSRST_WAVE511_APB>, + <&syscrg JH7110_SYSRST_AXIMEM0_AXI>; + reset-names = "rst_axi", "rst_bpu", "rst_vce", + "rst_apb", "rst_sram"; + starfive,vdec_noc_ctrl; + power-domains = <&pwrc JH7110_PD_VDEC>; + status = "disabled"; + }; + + vpu_enc: vpu_enc@130B0000 { + compatible = "starfive,venc"; + reg = <0x0 0x130B0000 0x0 0x10000>; + interrupts = <15>; + clocks = <&syscrg JH7110_SYSCLK_VENC_AXI>, + <&syscrg JH7110_SYSCLK_WAVE420L_BPU>, + <&syscrg JH7110_SYSCLK_WAVE420L_VCE>, + <&syscrg JH7110_SYSCLK_WAVE420L_APB>, + <&syscrg JH7110_SYSCLK_NOC_BUS_VENC_AXI>; + clock-names = "axi_clk", "bpu_clk", "vce_clk", + "apb_clk", "noc_bus"; + resets = <&syscrg JH7110_SYSRST_WAVE420L_AXI>, + <&syscrg JH7110_SYSRST_WAVE420L_BPU>, + <&syscrg JH7110_SYSRST_WAVE420L_VCE>, + <&syscrg JH7110_SYSRST_WAVE420L_APB>, + <&syscrg JH7110_SYSRST_AXIMEM1_AXI>; + reset-names = "rst_axi", "rst_bpu", "rst_vce", + "rst_apb", "rst_sram"; + starfive,venc_noc_ctrl; + power-domains = <&pwrc JH7110_PD_VENC>; + status = "disabled"; + }; + dma: dma-controller@16050000 { compatible = "starfive,jh7110-axi-dma"; reg = <0x0 0x16050000 0x0 0x10000>; -- 2.7.4 From a0668cbec05e6403fd028c9bfe813e66a9edff68 Mon Sep 17 00:00:00 2001 From: Samin Guo Date: Wed, 23 Aug 2023 10:43:54 +0800 Subject: [PATCH 16/16] riscv: dts: starfive: jh7110: add dma-coherent for vpu/jpu Use DMA-Coherent to avoid DIRECT_REMAP when allocating DMA buffers Signed-off-by: Samin Guo [sw0312.kim: cherry-pick the commit dfb44f0122ba from https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_6.1.y_devel] Signed-off-by: Seung-Woo Kim Change-Id: Ia0d3955010e963c0fb635e10081c1a2ab31155d4 --- arch/riscv/boot/dts/starfive/jh7110.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index c66f130..d24ed3b 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -998,6 +998,7 @@ jpu: jpu@13090000 { compatible = "starfive,jpu"; + dma-coherent; reg = <0x0 0x13090000 0x0 0x300>; interrupts = <14>; clocks = <&syscrg JH7110_SYSCLK_CODAJ12_AXI>, @@ -1016,6 +1017,7 @@ vpu_dec: vpu_dec@130A0000 { compatible = "starfive,vdec"; + dma-coherent; reg = <0x0 0x130A0000 0x0 0x10000>; interrupts = <13>; clocks = <&syscrg JH7110_SYSCLK_WAVE511_AXI>, @@ -1039,6 +1041,7 @@ vpu_enc: vpu_enc@130B0000 { compatible = "starfive,venc"; + dma-coherent; reg = <0x0 0x130B0000 0x0 0x10000>; interrupts = <15>; clocks = <&syscrg JH7110_SYSCLK_VENC_AXI>, -- 2.7.4