diff --git a/arch/riscv/configs/starfive_jh7110_defconfig b/arch/riscv/configs/starfive_jh7110_defconfig index fae319468d53..bcea0a690c2c 100644 --- a/arch/riscv/configs/starfive_jh7110_defconfig +++ b/arch/riscv/configs/starfive_jh7110_defconfig @@ -208,7 +208,7 @@ CONFIG_VIN_SENSOR_OV4689=y CONFIG_VIN_SENSOR_IMX219=y CONFIG_VIDEO_IMX708=y CONFIG_V4L_MEM2MEM_DRIVERS=y -CONFIG_VIDEO_WAVE_VPU=m +CONFIG_VIDEO_WAVE_VPU=y CONFIG_DRM_I2C_NXP_TDA998X=y CONFIG_DRM_VERISILICON=y CONFIG_STARFIVE_INNO_HDMI=y diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c index 2851f3f0b580..fb9c94d07853 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 25705e61cdb3..3c8328699201 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 8c7c090b4fc2..ec8b6cb80361 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 f32118d59fb8..f722924413b5 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 9c602168cffc..176bbe703b09 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 7156d8c3fee4..e83c186a498e 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 1458c5587dbc..5a0078a0d174 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 1b3ffb737925..0a4dc20ddec3 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;