mirror of
https://github.com/libretro/Lakka-LibreELEC.git
synced 2024-12-16 07:58:51 +00:00
170 lines
6.2 KiB
Diff
170 lines
6.2 KiB
Diff
From eaa6dd41f9c4c9a12d7f81a6ead80cc5d7146afa Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
|
Date: Sun, 8 Oct 2023 12:44:59 +0200
|
|
Subject: [PATCH 17/23] 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 16c822637dc6..2372fafab475 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 b696bf884cbd..ac0a88d47e10 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 75b6f2e85a5f..a61b30946204 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.42.0
|
|
|