media: add wave511 v4l2 support for starfive platfrom

Signed-off-by: Som Qin <som.qin@starfivetech.com>
This commit is contained in:
Som Qin 2022-12-22 15:33:22 +08:00 committed by Justin Hammond
parent 714ddc7310
commit bd07ca1252
9 changed files with 163 additions and 49 deletions

View file

@ -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

View 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);

View 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;

View 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;
}

View 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");

View 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>
@ -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);

View 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;

View 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);

View 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;