summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Hu <andy.hu@starfivetech.com>2023-12-15 14:18:25 +0300
committerAndy Hu <andy.hu@starfivetech.com>2023-12-15 14:18:25 +0300
commit6e6b31c9199508aaf6ce0b40dff9b56f49b5b930 (patch)
tree0c893dc51b6aea9d3938276baee081023a3f84c5
parente5fa0ea74fd6a52ba65b6fb70006a92e1cbc1ad2 (diff)
parent1a82e0446fca9d5950bf83a3ad73dfbaf0dd8001 (diff)
downloadlinux-6e6b31c9199508aaf6ce0b40dff9b56f49b5b930.tar.xz
Merge tag 'JH7110_SDK_515_v5.10.2' into vf2-515-devel
-rw-r--r--arch/riscv/configs/starfive_jh7110_defconfig1
-rw-r--r--drivers/gpu/drm/verisilicon/inno_hdmi.c2
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c80
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpu.c16
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpuapi.h15
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;