media: add wave511 v4l2 support for starfive platfrom
authorSom Qin <som.qin@starfivetech.com>
Thu, 22 Dec 2022 07:33:22 +0000 (15:33 +0800)
committerJaehoon Chung <jh80.chung@samsung.com>
Mon, 19 Feb 2024 00:14:02 +0000 (09:14 +0900)
Signed-off-by: Som Qin <som.qin@starfivetech.com>
[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 <sw0312.kim@samsung.com>
Change-Id: I170dd61340d2da9155dda478e570828347c5bdaf

drivers/media/platform/chips-media/wave5/wave5-helper.c
drivers/media/platform/chips-media/wave5/wave5-hw.c
drivers/media/platform/chips-media/wave5/wave5-vdi.c
drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
drivers/media/platform/chips-media/wave5/wave5-vpu.c
drivers/media/platform/chips-media/wave5/wave5-vpu.h
drivers/media/platform/chips-media/wave5/wave5-vpuapi.c
drivers/media/platform/chips-media/wave5/wave5-vpuapi.h

index 2851f3f..fb9c94d 100644 (file)
@@ -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);
index 25705e6..3c83286 100644 (file)
@@ -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;
index 8c7c090..ec8b6cb 100644 (file)
@@ -10,6 +10,7 @@
 #include "wave5-vpu.h"
 #include "wave5-regdefine.h"
 #include <linux/delay.h>
+#include <soc/sifive/sifive_l2_cache.h>
 
 #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;
 }
 
index f32118d..f722924 100644 (file)
@@ -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");
index 9c60216..176bbe7 100644 (file)
@@ -8,6 +8,9 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
 #include <linux/of_address.h>
 #include <linux/firmware.h>
 #include <linux/interrupt.h>
 #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);
index 7156d8c..e83c186 100644 (file)
@@ -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;
index 1458c55..5a0078a 100644 (file)
@@ -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);
index 1b3ffb7..0a4dc20 100644 (file)
@@ -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;