mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-16 04:04:06 +00:00
media: add wave511 v4l2 support for starfive platfrom
Signed-off-by: Som Qin <som.qin@starfivetech.com>
This commit is contained in:
parent
714ddc7310
commit
bd07ca1252
9 changed files with 163 additions and 49 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue