sunxi-6.13: cedrus: v4l2: Add NV12,P010,YUV420 AFBC formats

dma: sun6i-dma: add sun50i-h616 support
This commit is contained in:
The-going
2025-04-08 10:10:32 +03:00
committed by Igor
parent c1290520ed
commit f2c4d417cd
8 changed files with 398 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
From f4671b6d4842701e71b6a1ba6a93fbfb9dabb188 Mon Sep 17 00:00:00 2001
From: The-going <48602507+The-going@users.noreply.github.com>
Date: Mon, 7 Apr 2025 21:32:25 +0300
Subject: dma: sun6i-dma: add sun50i-h616 support
---
drivers/dma/sun6i-dma.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 95ecb12caaa5..ae2b5509b5b4 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1243,6 +1243,28 @@ static struct sun6i_dma_config sun50i_h6_dma_cfg = {
.has_mbus_clk = true,
};
+/*
+ * The H616 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_h616_dma_cfg = {
+ .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+ .set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_h6,
+ .set_mode = sun6i_set_mode_h6,
+ .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .has_mbus_clk = true,
+};
+
/*
* The V3s have only 8 physical channels, a maximum DRQ port id of 23,
* and a total of 24 usable source and destination endpoints.
@@ -1276,6 +1298,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
{ .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg },
{ .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
+ { .compatible = "allwinner,sun50i-h616-dma", .data = &sun50i_h616_dma_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun6i_dma_match);
--
2.35.3

View File

@@ -0,0 +1,45 @@
From eae101ec576943cc34c4718b360bbe6091792e8b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sat, 7 Oct 2023 09:43:35 +0200
Subject: media: Add NV12 and P010 AFBC compressed formats
Cedrus supports AFBC compressed NV12 and P010 formats, which
considerably speed up H265 decoding. Add them.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/media/v4l2-core/v4l2-ioctl.c | 2 ++
include/uapi/linux/videodev2.h | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 0304daa8471d..6c7f3abb4959 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1546,6 +1546,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_PISP_COMP2_GBRG: descr = "PiSP 8b GBGB/RGRG mode2 compr"; break;
case V4L2_PIX_FMT_PISP_COMP2_BGGR: descr = "PiSP 8b BGBG/GRGR mode2 compr"; break;
case V4L2_PIX_FMT_PISP_COMP2_MONO: descr = "PiSP 8b monochrome mode2 compr"; break;
+ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT: descr = "YUV 4:2:0 (AFBC 16x16)"; break;
+ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT: descr = "10-bit YUV 4:2:0 (AFBC 16x16)"; break;
default:
if (fmt->description[0])
return;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index e7c4dce39007..8d423df66f61 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -688,6 +688,10 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_NV12M_8L128 v4l2_fourcc('N', 'A', '1', '2') /* Y/CbCr 4:2:0 8x128 tiles */
#define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2') /* Y/CbCr 4:2:0 10-bit 8x128 tiles */
+/* AFBC YUV formats */
+#define V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT v4l2_fourcc('A', 'S', '1', '2') /* YUV420 AFBC compressed, 16x16 macroblocks, split */
+#define V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT v4l2_fourcc('A', 'S', '0', '1') /* YUV420 10-bit AFBC compressed, 16x16 macroblocks, split */
+
/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */
#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
--
2.35.3

View File

@@ -0,0 +1,29 @@
From 80b16fcddf1837c631796c25f3123b7adbbf815a Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Tue, 4 Oct 2022 20:36:18 +0200
Subject: media: cedrus: Don't CPU map source buffers
There is no need to access source buffers via CPU, so let's disable
that. This will lower amount of virtual memory needed on 32-bit ARM
SoCs.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/staging/media/sunxi/cedrus/cedrus_video.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 77f78266f406..7f5a6a2363a5 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -580,6 +580,7 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING;
src_vq->drv_priv = ctx;
src_vq->buf_struct_size = sizeof(struct cedrus_buffer);
src_vq->ops = &cedrus_qops;
--
2.35.3

View File

@@ -0,0 +1,169 @@
From 81241983ba12f281a839a530da460088170cca2e Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sun, 8 Oct 2023 12:44:59 +0200
Subject: media: cedrus: Implement AFBC YUV420 formats for H265
AFBC output formats are more performant, since they are optimized for
more efficient memory operations and transfers.
Add support for them.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/staging/media/sunxi/cedrus/cedrus.h | 11 ++++++
.../staging/media/sunxi/cedrus/cedrus_h265.c | 3 +-
.../staging/media/sunxi/cedrus/cedrus_hw.c | 16 +++++++++
.../staging/media/sunxi/cedrus/cedrus_regs.h | 6 ++++
.../staging/media/sunxi/cedrus/cedrus_video.c | 36 +++++++++++++++++++
5 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 522c184e2afc..c7ec4dee8630 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -268,6 +268,17 @@ cedrus_is_capable(struct cedrus_ctx *ctx, unsigned int capabilities)
return (ctx->dev->capabilities & capabilities) == capabilities;
}
+static inline bool is_afbc_format(u32 format)
+{
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT:
+ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
void *cedrus_find_control_data(struct cedrus_ctx *ctx, u32 id);
u32 cedrus_get_num_of_controls(struct cedrus_ctx *ctx, u32 id);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 780da4a8b5af..1a7b0600cc51 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -120,7 +120,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
{
struct cedrus_dev *dev = ctx->dev;
dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buf, 0);
- dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buf, 1);
+ dma_addr_t dst_chroma_addr = is_afbc_format(ctx->dst_fmt.pixelformat) ?
+ 0 : cedrus_dst_buf_addr(ctx, buf, 1);
dma_addr_t mv_col_buf_addr[2] = {
cedrus_h265_frame_info_mv_col_buf_addr(buf, 0),
cedrus_h265_frame_info_mv_col_buf_addr(buf, field_pic ? 1 : 0)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 32af0e96e762..5d769a124439 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -65,6 +65,18 @@ int cedrus_engine_enable(struct cedrus_ctx *ctx)
reg |= VE_MODE_PIC_WIDTH_IS_4096;
if (ctx->src_fmt.width > 2048)
reg |= VE_MODE_PIC_WIDTH_MORE_2048;
+ /*
+ * NOTE: Not sure if RGB default color feature is part of official
+ * AFBC standard or not and if it is, which feature that is. However,
+ * in order to render it properly with display engine, default color
+ * has to be set to white there.
+ */
+ if (is_afbc_format(ctx->dst_fmt.pixelformat))
+ reg |= VE_MODE_COMPRESS_EN |
+ VE_MODE_MIN_VAL_WRAP_EN |
+ VE_MODE_RGB_DEF_COLOR_EN |
+ VE_MODE_BODYBUF_1K_ALIGNED |
+ VE_MODE_COMPRESS_MODE_AFBC;
cedrus_write(ctx->dev, VE_MODE, reg);
@@ -85,6 +97,10 @@ void cedrus_dst_format_set(struct cedrus_dev *dev,
u32 reg;
switch (fmt->pixelformat) {
+ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT:
+ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT:
+ /* format is already set in cedrus_engine_enable() */
+ break;
case V4L2_PIX_FMT_NV12:
chroma_size = ALIGN(width, 16) * ALIGN(height, 16) / 2;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 05e6cbc548ab..c3dcd93a29eb 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -35,12 +35,18 @@
#define VE_MODE 0x00
+#define VE_MODE_COMPRESS_EN BIT(29)
+#define VE_MODE_MIN_VAL_WRAP_EN BIT(27)
+#define VE_MODE_RGB_DEF_COLOR_EN BIT(26)
#define VE_MODE_PIC_WIDTH_IS_4096 BIT(22)
#define VE_MODE_PIC_WIDTH_MORE_2048 BIT(21)
#define VE_MODE_REC_WR_MODE_2MB (0x01 << 20)
#define VE_MODE_REC_WR_MODE_1MB (0x00 << 20)
#define VE_MODE_DDR_MODE_BW_128 (0x03 << 16)
#define VE_MODE_DDR_MODE_BW_256 (0x02 << 16)
+#define VE_MODE_BODYBUF_1K_ALIGNED BIT(12)
+#define VE_MODE_COMPRESS_MODE_LOSSLESS (0x00 << 4)
+#define VE_MODE_COMPRESS_MODE_AFBC (0x01 << 4)
#define VE_MODE_DISABLED (0x07 << 0)
#define VE_MODE_DEC_H265 (0x04 << 0)
#define VE_MODE_DEC_H264 (0x01 << 0)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 53ec3066274d..99011066e7d3 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -55,6 +55,22 @@ static struct cedrus_format cedrus_formats[] = {
.directions = CEDRUS_DECODE_SRC,
.capabilities = CEDRUS_CAPABILITY_VP8_DEC,
},
+ {
+ .pixelformat = V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT,
+ .directions = CEDRUS_DECODE_DST,
+ .capabilities = CEDRUS_CAPABILITY_UNTILED |
+ CEDRUS_CAPABILITY_H265_10_DEC,
+ .depth = 10,
+ .src_format = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .pixelformat = V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT,
+ .directions = CEDRUS_DECODE_DST,
+ .capabilities = CEDRUS_CAPABILITY_UNTILED |
+ CEDRUS_CAPABILITY_H265_10_DEC,
+ .depth = 8,
+ .src_format = V4L2_PIX_FMT_HEVC_SLICE,
+ },
{
.pixelformat = V4L2_PIX_FMT_NV12,
.directions = CEDRUS_DECODE_DST,
@@ -160,6 +176,26 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
sizeimage += bytesperline * height / 2;
break;
+
+ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT:
+ /* Zero bytes per line for compressed destination. */
+ bytesperline = 0;
+
+ sizeimage = DIV_ROUND_UP(width, 16) *
+ DIV_ROUND_UP(height + 4, 16) * (512 + 16) +
+ 32 + SZ_1K;
+
+ break;
+
+ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT:
+ /* Zero bytes per line for compressed destination. */
+ bytesperline = 0;
+
+ sizeimage = DIV_ROUND_UP(width, 16) *
+ DIV_ROUND_UP(height + 4, 16) * (384 + 16) +
+ 32 + SZ_1K;
+
+ break;
}
pix_fmt->width = width;
--
2.35.3

View File

@@ -0,0 +1,29 @@
From c0dffc32c3a65a1c25bf04f979faf8b6a82b88f8 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Mon, 9 Oct 2023 20:16:27 +0200
Subject: media: cedrus: Increase H6 clock rate
Vendor driver runs Cedrus at 648 MHz, supposedly to be able to decode
4k HEVC at 60 fps.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/staging/media/sunxi/cedrus/cedrus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index b91174246e58..08f8d994c99c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -648,7 +648,7 @@ static const struct cedrus_variant sun50i_h6_cedrus_variant = {
CEDRUS_CAPABILITY_H265_DEC |
CEDRUS_CAPABILITY_H265_10_DEC |
CEDRUS_CAPABILITY_VP8_DEC,
- .mod_rate = 600000000,
+ .mod_rate = 648000000,
};
static const struct of_device_id cedrus_dt_match[] = {
--
2.35.3

View File

@@ -0,0 +1,50 @@
From be75f442cae72a4e646e1f5d7374f579ee026c3d Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sat, 7 Oct 2023 09:45:25 +0200
Subject: media: cedrus: add format filtering based on depth and src format
Some Cedrus variant, like that found in H6, support special output
formats only with specific codecs, like H265.
Add extra filtering fields based on bit depth and source format.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/staging/media/sunxi/cedrus/cedrus_video.c | 7 +++++++
drivers/staging/media/sunxi/cedrus/cedrus_video.h | 2 ++
2 files changed, 9 insertions(+)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 7f5a6a2363a5..53ec3066274d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -87,6 +87,13 @@ static struct cedrus_format *cedrus_find_format(struct cedrus_ctx *ctx,
!(fmt->directions & directions))
continue;
+ if (fmt->depth && fmt->depth != ctx->bit_depth)
+ continue;
+
+ if (fmt->src_format &&
+ fmt->src_format != ctx->src_fmt.pixelformat)
+ continue;
+
if (fmt->pixelformat == pixelformat)
break;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.h b/drivers/staging/media/sunxi/cedrus/cedrus_video.h
index 8e1afc16a6a1..c8e9909ecdee 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h
@@ -20,6 +20,8 @@ struct cedrus_format {
u32 pixelformat;
u32 directions;
unsigned int capabilities;
+ unsigned int depth;
+ u32 src_format;
};
extern const struct v4l2_ioctl_ops cedrus_ioctl_ops;
--
2.35.3

View File

@@ -292,6 +292,18 @@
patches.drm/drm-panfrost-add-h616-compatible-string.patch
patches.drm/drm-panfrost-reorder-pd-clk-rst-sequence
################################################################################
#
# media patches
#
################################################################################
patches.media/media-cedrus-Don-t-CPU-map-source-buffers.patch
patches.media/media-Add-NV12-and-P010-AFBC-compressed-formats.patch
patches.media/media-cedrus-add-format-filtering-based-on-depth-and-src-format.patch
patches.media/media-cedrus-Implement-AFBC-YUV420-formats-for-H265.patch
patches.media/media-cedrus-Increase-H6-clock-rate.patch
patches.media/dma-sun6i-dma-add-sun50i-h616-support.patch
################################################################################
#
# Armbian patches

View File

@@ -0,0 +1,11 @@
#
# Automatically generated by the script mk_format_patch
#
# git@github.com:The-going/linux-sf.git
#
patches.media/media-cedrus-Don-t-CPU-map-source-buffers.patch
patches.media/media-Add-NV12-and-P010-AFBC-compressed-formats.patch
patches.media/media-cedrus-add-format-filtering-based-on-depth-and-src-format.patch
patches.media/media-cedrus-Implement-AFBC-YUV420-formats-for-H265.patch
patches.media/media-cedrus-Increase-H6-clock-rate.patch
patches.media/dma-sun6i-dma-add-sun50i-h616-support.patch