mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-08-03 16:07:51 +00:00
Allwinner: linux: Update cedrus patches
This commit is contained in:
parent
649a235353
commit
a1babd4b34
@ -6,8 +6,8 @@ Subject: [PATCH] media: cedrus: hevc: Improve buffer management
|
|||||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||||
---
|
---
|
||||||
drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +-
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +-
|
||||||
.../staging/media/sunxi/cedrus/cedrus_h265.c | 117 ++++++++++--------
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 116 ++++++++++--------
|
||||||
2 files changed, 69 insertions(+), 57 deletions(-)
|
2 files changed, 68 insertions(+), 57 deletions(-)
|
||||||
|
|
||||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||||
index c9ec43be260f..6fa2df354cbf 100644
|
index c9ec43be260f..6fa2df354cbf 100644
|
||||||
@ -37,10 +37,10 @@ index c9ec43be260f..6fa2df354cbf 100644
|
|||||||
dma_addr_t neighbor_info_buf_addr;
|
dma_addr_t neighbor_info_buf_addr;
|
||||||
void *entry_points_buf;
|
void *entry_points_buf;
|
||||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||||
index 3b355de4c097..9e21a40867d7 100644
|
index 3b355de4c097..802b85434949 100644
|
||||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||||
@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
|
@@ -91,26 +91,65 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
|
||||||
|
|
||||||
static inline dma_addr_t
|
static inline dma_addr_t
|
||||||
cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
|
cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
|
||||||
@ -66,19 +66,18 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
+ return 0;
|
+ return 0;
|
||||||
+
|
+
|
||||||
+ if (!cedrus_buf->codec.h265.mv_col_buf_size) {
|
+ if (!cedrus_buf->codec.h265.mv_col_buf_size) {
|
||||||
+ unsigned int ctb_size_luma, width_in_ctb_luma;
|
|
||||||
+ unsigned int log2_max_luma_coding_block_size;
|
+ unsigned int log2_max_luma_coding_block_size;
|
||||||
|
+ unsigned int ctb_size_luma;
|
||||||
+
|
+
|
||||||
+ log2_max_luma_coding_block_size =
|
+ log2_max_luma_coding_block_size =
|
||||||
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
|
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
|
||||||
+ sps->log2_diff_max_min_luma_coding_block_size;
|
+ sps->log2_diff_max_min_luma_coding_block_size;
|
||||||
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
|
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
|
||||||
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples,
|
|
||||||
+ ctb_size_luma);
|
|
||||||
+
|
+
|
||||||
+ cedrus_buf->codec.h265.mv_col_buf_size = ALIGN(width_in_ctb_luma *
|
+ cedrus_buf->codec.h265.mv_col_buf_size =
|
||||||
|
+ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma) *
|
||||||
+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) *
|
+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) *
|
||||||
+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024);
|
+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
|
||||||
+
|
+
|
||||||
+ cedrus_buf->codec.h265.mv_col_buf =
|
+ cedrus_buf->codec.h265.mv_col_buf =
|
||||||
+ dma_alloc_coherent(ctx->dev->dev,
|
+ dma_alloc_coherent(ctx->dev->dev,
|
||||||
@ -115,7 +114,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
};
|
};
|
||||||
u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
|
u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
|
||||||
VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
|
VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
|
||||||
@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
|
@@ -134,7 +173,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
|
||||||
|
|
||||||
static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
|
static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
|
||||||
const struct v4l2_hevc_dpb_entry *dpb,
|
const struct v4l2_hevc_dpb_entry *dpb,
|
||||||
@ -125,7 +124,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
{
|
{
|
||||||
struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
|
struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
|
||||||
V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||||
@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
|
@@ -149,7 +189,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
|
||||||
|
|
||||||
cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
|
cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
|
||||||
pic_order_cnt,
|
pic_order_cnt,
|
||||||
@ -134,7 +133,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,36 +427,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
@@ -386,36 +426,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||||
width_in_ctb_luma =
|
width_in_ctb_luma =
|
||||||
DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
||||||
|
|
||||||
@ -171,7 +170,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
/* Activate H265 engine. */
|
/* Activate H265 engine. */
|
||||||
cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
|
cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
|
||||||
|
|
||||||
@@ -669,7 +680,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
@@ -669,7 +679,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||||
|
|
||||||
/* Write decoded picture buffer in pic list. */
|
/* Write decoded picture buffer in pic list. */
|
||||||
cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
|
cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
|
||||||
@ -180,7 +179,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
|
|
||||||
/* Output frame. */
|
/* Output frame. */
|
||||||
|
|
||||||
@@ -680,7 +691,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
@@ -680,7 +690,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||||
cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
|
cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
|
||||||
slice_params->pic_struct != 0,
|
slice_params->pic_struct != 0,
|
||||||
pic_order_cnt,
|
pic_order_cnt,
|
||||||
@ -189,7 +188,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
|
|
||||||
cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
|
cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
|
||||||
|
|
||||||
@@ -729,9 +740,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
|
@@ -729,9 +739,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cedrus_dev *dev = ctx->dev;
|
struct cedrus_dev *dev = ctx->dev;
|
||||||
|
|
||||||
@ -199,7 +198,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
ctx->codec.h265.neighbor_info_buf =
|
ctx->codec.h265.neighbor_info_buf =
|
||||||
dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
||||||
&ctx->codec.h265.neighbor_info_buf_addr,
|
&ctx->codec.h265.neighbor_info_buf_addr,
|
||||||
@@ -757,14 +765,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
|
@@ -757,14 +764,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cedrus_dev *dev = ctx->dev;
|
struct cedrus_dev *dev = ctx->dev;
|
||||||
|
|
||||||
@ -214,7 +213,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
||||||
ctx->codec.h265.neighbor_info_buf,
|
ctx->codec.h265.neighbor_info_buf,
|
||||||
ctx->codec.h265.neighbor_info_buf_addr);
|
ctx->codec.h265.neighbor_info_buf_addr);
|
||||||
@@ -780,6 +780,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
|
@@ -780,6 +779,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
|
||||||
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
|
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +230,7 @@ index 3b355de4c097..9e21a40867d7 100644
|
|||||||
struct cedrus_dec_ops cedrus_dec_ops_h265 = {
|
struct cedrus_dec_ops cedrus_dec_ops_h265 = {
|
||||||
.irq_clear = cedrus_h265_irq_clear,
|
.irq_clear = cedrus_h265_irq_clear,
|
||||||
.irq_disable = cedrus_h265_irq_disable,
|
.irq_disable = cedrus_h265_irq_disable,
|
||||||
@@ -788,4 +798,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = {
|
@@ -788,4 +797,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = {
|
||||||
.start = cedrus_h265_start,
|
.start = cedrus_h265_start,
|
||||||
.stop = cedrus_h265_stop,
|
.stop = cedrus_h265_stop,
|
||||||
.trigger = cedrus_h265_trigger,
|
.trigger = cedrus_h265_trigger,
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 9 Feb 2022 19:03:06 +0100
|
||||||
|
Subject: [PATCH] media: cedrus: Fix H265 aux buffer size
|
||||||
|
|
||||||
|
Neighbour info buffer size needs to be 794 kiB in size on H6. This is
|
||||||
|
actually mentioned in comment, but smaller size is used nevertheless.
|
||||||
|
|
||||||
|
Increase buffer size to conform H6 needs. Since increase is not that big
|
||||||
|
in absolute numbers, it doesn't make sense to complicate logic for older
|
||||||
|
generations.
|
||||||
|
|
||||||
|
Bug was discovered using iommu, which reported access error when trying
|
||||||
|
to play H265 video.
|
||||||
|
|
||||||
|
Fixes: 86caab29da78 ("media: cedrus: Add HEVC/H.265 decoding support")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||||
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||||
|
@@ -23,7 +23,7 @@
|
||||||
|
* Subsequent BSP implementations seem to double the neighbor info buffer size
|
||||||
|
* for the H6 SoC, which may be related to 10 bit H265 support.
|
||||||
|
*/
|
||||||
|
-#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K)
|
||||||
|
+#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (794 * SZ_1K)
|
||||||
|
#define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K)
|
||||||
|
#define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160
|
||||||
|
|
@ -0,0 +1,113 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Tue, 1 Feb 2022 19:14:18 +0100
|
||||||
|
Subject: [PATCH] media: cedrus: Add watchdog for job completion
|
||||||
|
|
||||||
|
Currently, if job is not completed for whatever reason, userspace
|
||||||
|
application can hang on ioctl and thus become unkillable.
|
||||||
|
|
||||||
|
In order to prevent that, implement watchdog, which will complete job
|
||||||
|
after 2 seconds with error state.
|
||||||
|
|
||||||
|
Concept is borrowed from hantro driver.
|
||||||
|
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/staging/media/sunxi/cedrus/cedrus.c | 2 ++
|
||||||
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 3 +++
|
||||||
|
.../staging/media/sunxi/cedrus/cedrus_dec.c | 4 +++
|
||||||
|
.../staging/media/sunxi/cedrus/cedrus_hw.c | 25 +++++++++++++++++++
|
||||||
|
.../staging/media/sunxi/cedrus/cedrus_hw.h | 2 ++
|
||||||
|
5 files changed, 36 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||||
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||||
|
@@ -476,6 +476,8 @@ static int cedrus_probe(struct platform_
|
||||||
|
|
||||||
|
mutex_init(&dev->dev_mutex);
|
||||||
|
|
||||||
|
+ INIT_DELAYED_WORK(&dev->watchdog_work, cedrus_watchdog);
|
||||||
|
+
|
||||||
|
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to register V4L2 device\n");
|
||||||
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||||
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
#include <media/videobuf2-dma-contig.h>
|
||||||
|
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
+#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#define CEDRUS_NAME "cedrus"
|
||||||
|
|
||||||
|
@@ -199,6 +200,8 @@ struct cedrus_dev {
|
||||||
|
struct reset_control *rstc;
|
||||||
|
|
||||||
|
unsigned int capabilities;
|
||||||
|
+
|
||||||
|
+ struct delayed_work watchdog_work;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
|
||||||
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
||||||
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
||||||
|
@@ -93,4 +93,8 @@ void cedrus_device_run(void *priv)
|
||||||
|
v4l2_ctrl_request_complete(src_req, &ctx->hdl);
|
||||||
|
|
||||||
|
dev->dec_ops[ctx->current_codec]->trigger(ctx);
|
||||||
|
+
|
||||||
|
+ /* Start the watchdog timer. */
|
||||||
|
+ schedule_delayed_work(&dev->watchdog_work,
|
||||||
|
+ msecs_to_jiffies(2000));
|
||||||
|
}
|
||||||
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||||
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||||
|
@@ -117,6 +117,13 @@ static irqreturn_t cedrus_irq(int irq, v
|
||||||
|
enum vb2_buffer_state state;
|
||||||
|
enum cedrus_irq_status status;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * If cancel_delayed_work returns false it means watchdog already
|
||||||
|
+ * executed and finished the job.
|
||||||
|
+ */
|
||||||
|
+ if (!cancel_delayed_work(&dev->watchdog_work))
|
||||||
|
+ return IRQ_HANDLED;
|
||||||
|
+
|
||||||
|
ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
|
||||||
|
if (!ctx) {
|
||||||
|
v4l2_err(&dev->v4l2_dev,
|
||||||
|
@@ -142,6 +149,24 @@ static irqreturn_t cedrus_irq(int irq, v
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void cedrus_watchdog(struct work_struct *work)
|
||||||
|
+{
|
||||||
|
+ struct cedrus_dev *dev;
|
||||||
|
+ struct cedrus_ctx *ctx;
|
||||||
|
+
|
||||||
|
+ dev = container_of(to_delayed_work(work),
|
||||||
|
+ struct cedrus_dev, watchdog_work);
|
||||||
|
+
|
||||||
|
+ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
|
||||||
|
+ if (!ctx)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ v4l2_err(&dev->v4l2_dev, "frame processing timed out!\n");
|
||||||
|
+ reset_control_reset(dev->rstc);
|
||||||
|
+ v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx,
|
||||||
|
+ VB2_BUF_STATE_ERROR);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int cedrus_hw_suspend(struct device *device)
|
||||||
|
{
|
||||||
|
struct cedrus_dev *dev = dev_get_drvdata(device);
|
||||||
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||||
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||||
|
@@ -28,4 +28,6 @@ int cedrus_hw_resume(struct device *devi
|
||||||
|
int cedrus_hw_probe(struct cedrus_dev *dev);
|
||||||
|
void cedrus_hw_remove(struct cedrus_dev *dev);
|
||||||
|
|
||||||
|
+void cedrus_watchdog(struct work_struct *work);
|
||||||
|
+
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user