diff options
-rw-r--r-- | arch/riscv/configs/starfive_jh7110_defconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/verisilicon/inno_hdmi.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 80 | ||||
-rw-r--r-- | drivers/media/platform/chips-media/wave5/wave5-vpu.c | 16 | ||||
-rw-r--r-- | drivers/media/platform/chips-media/wave5/wave5-vpuapi.h | 15 |
5 files changed, 105 insertions, 9 deletions
diff --git a/arch/riscv/configs/starfive_jh7110_defconfig b/arch/riscv/configs/starfive_jh7110_defconfig index 09ea78f4d188..036dcdcc6e02 100644 --- a/arch/riscv/configs/starfive_jh7110_defconfig +++ b/arch/riscv/configs/starfive_jh7110_defconfig @@ -86,6 +86,7 @@ CONFIG_BT_HCIUART=y CONFIG_BT_HCIUART_H4=y CONFIG_CFG80211=y CONFIG_MAC80211=y +CONFIG_RFKILL=y CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y CONFIG_PCI=y diff --git a/drivers/gpu/drm/verisilicon/inno_hdmi.c b/drivers/gpu/drm/verisilicon/inno_hdmi.c index 804b25cde83f..49dc56d397a3 100644 --- a/drivers/gpu/drm/verisilicon/inno_hdmi.c +++ b/drivers/gpu/drm/verisilicon/inno_hdmi.c @@ -525,6 +525,8 @@ static void inno_hdmi_encoder_enable(struct drm_encoder *encoder) if (ret < 0) return; + mdelay(10); + inno_hdmi_setup(hdmi, &hdmi->previous_mode); } 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 e97b3b022055..b5ee9f270343 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -6,6 +6,7 @@ */ #include "wave5-helper.h" +#include <soc/sifive/sifive_l2_cache.h> #define VPU_DEC_DEV_NAME "C&M Wave5 VPU decoder" #define VPU_DEC_DRV_NAME "wave5-dec" @@ -180,6 +181,8 @@ static void wave5_handle_bitstream_buffer(struct vpu_instance *inst) static void wave5_handle_src_buffer(struct vpu_instance *inst) { struct vb2_v4l2_buffer *src_buf; + int i, j, ret; + u64 flag; src_buf = v4l2_m2m_next_src_buf(inst->v4l2_fh.m2m_ctx); if (src_buf) { @@ -188,7 +191,33 @@ static void wave5_handle_src_buffer(struct vpu_instance *inst) if (vpu_buf->consumed) { dev_dbg(inst->dev->dev, "%s: already consumed buffer\n", __func__); src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx); - inst->timestamp = src_buf->vb2_buf.timestamp; + + if (!inst->monotonic_timestamp && !src_buf->vb2_buf.timestamp) { + inst->timestamp_zero_cnt++; + if (inst->timestamp_zero_cnt > 1) { + inst->monotonic_timestamp = TRUE; + } + } + + if(!inst->monotonic_timestamp) { + ret = mutex_lock_interruptible(&inst->time_stamp.lock); + if (ret) { + dev_err(inst->dev->dev, "%s: lock err\n", __func__); + return; + } + inst->time_stamp.buf[inst->time_stamp.cnt] = src_buf->vb2_buf.timestamp; + inst->time_stamp.cnt++; + + for (i = 1; i < inst->time_stamp.cnt; i++) { + flag = inst->time_stamp.buf[i]; + for (j = i - 1; j >= 0 && inst->time_stamp.buf[j] < flag ; j--) { + inst->time_stamp.buf[j + 1] = inst->time_stamp.buf[j]; + } + inst->time_stamp.buf[j + 1] = flag; + } + mutex_unlock(&inst->time_stamp.lock); + } + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); } } @@ -345,7 +374,18 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) ((stride / 2) * (height / 2))); } - dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + if (!inst->monotonic_timestamp) { + ret = mutex_lock_interruptible(&inst->time_stamp.lock); + if (ret) { + dev_err(inst->dev->dev, "%s: lock err\n", __func__); + return; + } + dst_buf->vb2_buf.timestamp = inst->time_stamp.buf[inst->time_stamp.cnt - 1]; + inst->time_stamp.cnt--; + mutex_unlock(&inst->time_stamp.lock); + } else { + dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + } dst_buf->field = V4L2_FIELD_NONE; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); @@ -380,7 +420,19 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) vb2_plane_size(&dst_buf->vb2_buf, 2)); } - dst_buf->vb2_buf.timestamp = inst->timestamp; + if (!inst->monotonic_timestamp) { + ret = mutex_lock_interruptible(&inst->time_stamp.lock); + if (ret) { + dev_err(inst->dev->dev, "%s: lock err\n", __func__); + return; + } + dst_buf->vb2_buf.timestamp = inst->time_stamp.buf[inst->time_stamp.cnt - 1]; + inst->time_stamp.cnt--; + mutex_unlock(&inst->time_stamp.lock); + } else { + dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + } + dst_buf->flags |= V4L2_BUF_FLAG_LAST; dst_buf->field = V4L2_FIELD_NONE; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); @@ -951,6 +1003,10 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) struct dec_initial_info initial_info; int ret = 0; + inst->time_stamp.cnt = 0; + mutex_init(&inst->time_stamp.lock); + memset(&inst->time_stamp.buf, 0, sizeof(MAX_TIMESTAMP_CIR_BUF)); + memset(&initial_info, 0, sizeof(struct dec_initial_info)); ret = wave5_vpu_dec_issue_seq_init(inst); @@ -1104,15 +1160,10 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue); + struct frame_buffer *frame_buf; int ret; vbuf->sequence = inst->queued_dst_buf_num++; - ret = wave5_vpu_dec_clr_disp_flag(inst, vb->index); - if (ret) { - dev_dbg(inst->dev->dev, - "%s: Clearing the display flag of buffer index: %u, fail: %d\n", - __func__, vb->index, ret); - } if (inst->state == VPU_INST_STATE_INIT_SEQ) { dma_addr_t buf_addr_y = 0, buf_addr_cb = 0, buf_addr_cr = 0; @@ -1152,6 +1203,17 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) 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); } + frame_buf = &inst->frame_buf[vb->index + inst->dst_buf_count]; + if (frame_buf->size < inst->dev->l2_cache_size) + sifive_l2_flush64_range(frame_buf->buf_y, frame_buf->size); + + ret = wave5_vpu_dec_clr_disp_flag(inst, vb->index); + if (ret) { + dev_dbg(inst->dev->dev, + "%s: Clearing the display flag of buffer index: %u, fail: %d\n", + __func__, vb->index, ret); + } + if (!vb2_is_streaming(vb->vb2_queue)) return; diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c index e378817f57a8..9aee7e90a9ac 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c @@ -169,11 +169,17 @@ err_without_release: return ret; } +static const struct of_device_id sifive_l2_ids[] = { + { .compatible = "sifive,fu740-c000-ccache" }, + { /* end of table */ }, +}; + static int wave5_vpu_probe(struct platform_device *pdev) { int ret; struct vpu_device *dev; const struct wave5_match_data *match_data; + struct device_node *np; match_data = device_get_match_data(&pdev->dev); if (!match_data) { @@ -283,6 +289,16 @@ static int wave5_vpu_probe(struct platform_device *pdev) goto err_enc_unreg; } + np = of_find_matching_node(NULL, sifive_l2_ids); + if (!np) { + dev_err(&pdev->dev, "find cache node, fail\n"); + goto err_enc_unreg; + } + + ret = of_property_read_u32(np, "cache-size", &dev->l2_cache_size); + if (ret) + dev->l2_cache_size = 0x200000; + dev_dbg(&pdev->dev, "Added wave5 driver with caps: %s %s and product code: 0x%x\n", (match_data->flags & WAVE5_IS_ENC) ? "'ENCODE'" : "", (match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : "", diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h index 892eff216aea..d7b5717fd9c1 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h @@ -43,6 +43,8 @@ enum vpu_instance_state { #define MAX_REG_FRAME (WAVE5_MAX_FBS * 2) +#define MAX_TIMESTAMP_CIR_BUF 30 + #define WAVE5_DEC_HEVC_BUF_SIZE(_w, _h) (DIV_ROUND_UP(_w, 64) * DIV_ROUND_UP(_h, 64) * 256 + 64) #define WAVE5_DEC_AVC_BUF_SIZE(_w, _h) ((((ALIGN(_w, 256) / 16) * (ALIGN(_h, 16) / 16)) + 16) * 80) #define WAVE5_DEC_VP9_BUF_SIZE(_w, _h) (((ALIGN(_w, 64) * ALIGN(_h, 64)) >> 2)) @@ -1023,6 +1025,7 @@ struct vpu_device { struct dma_vpu_buf sram_buf; void __iomem *vdb_register; u32 product_code; + u32 l2_cache_size; struct ida inst_ida; struct clk_bulk_data *clks; struct reset_control *resets; @@ -1037,6 +1040,15 @@ struct vpu_instance_ops { void (*finish_process)(struct vpu_instance *inst); }; +/* for support GStreamer ver 1.20 over + * too old frame, eos sent too early + */ +struct timestamp_circ_buf { + u64 buf[MAX_TIMESTAMP_CIR_BUF]; + struct mutex lock; + int cnt; +}; + struct vpu_instance { struct list_head list; struct v4l2_fh v4l2_fh; @@ -1074,7 +1086,10 @@ struct vpu_instance { u32 conf_win_width; u32 conf_win_height; u64 timestamp; + struct timestamp_circ_buf time_stamp; u64 timestamp_cnt; + u32 timestamp_zero_cnt; + bool monotonic_timestamp; bool cbcr_interleave; bool nv21; bool eos; |