181 lines
6.9 KiB
Diff
181 lines
6.9 KiB
Diff
From 62eb86473f2ccdd278983f4c6f1e41c895edc9b7 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 21:23:55 +0200
|
|
Subject: [PATCH 033/170] drv:media: cedrus: hevc: tiles hack
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 2 +
|
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 93 +++++++++++++++++--
|
|
2 files changed, 89 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index 3bc094eb4..9d34e5785 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -146,6 +146,8 @@ struct cedrus_ctx {
|
|
ssize_t mv_col_buf_unit_size;
|
|
void *neighbor_info_buf;
|
|
dma_addr_t neighbor_info_buf_addr;
|
|
+ void *entry_points_buf;
|
|
+ dma_addr_t entry_points_buf_addr;
|
|
} h265;
|
|
struct {
|
|
unsigned int last_frame_p_type;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index 44f385be9..f71ce6f87 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -329,6 +329,61 @@ static int cedrus_h265_is_low_delay(struct cedrus_run *run)
|
|
return 0;
|
|
}
|
|
|
|
+static void write_entry_point_list(struct cedrus_ctx *ctx,
|
|
+ struct cedrus_run *run,
|
|
+ unsigned int ctb_addr_x,
|
|
+ unsigned int ctb_addr_y)
|
|
+{
|
|
+ const struct v4l2_ctrl_hevc_slice_params *slice_params;
|
|
+ const struct v4l2_ctrl_hevc_pps *pps;
|
|
+ struct cedrus_dev *dev = ctx->dev;
|
|
+ int i, x, tx, y, ty;
|
|
+ u32 *entry_points;
|
|
+
|
|
+ pps = run->h265.pps;
|
|
+ slice_params = run->h265.slice_params;
|
|
+
|
|
+ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) {
|
|
+ if (x + pps->column_width_minus1[tx] + 1 > ctb_addr_x)
|
|
+ break;
|
|
+
|
|
+ x += pps->column_width_minus1[tx] + 1;
|
|
+ }
|
|
+
|
|
+ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) {
|
|
+ if (y + pps->row_height_minus1[ty] + 1 > ctb_addr_y)
|
|
+ break;
|
|
+
|
|
+ y += pps->row_height_minus1[ty] + 1;
|
|
+ }
|
|
+
|
|
+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0));
|
|
+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB,
|
|
+ ((y + pps->row_height_minus1[ty]) << 16) |
|
|
+ ((x + pps->column_width_minus1[tx]) << 0));
|
|
+
|
|
+ entry_points = ctx->codec.h265.entry_points_buf;
|
|
+ if (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) {
|
|
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++)
|
|
+ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1;
|
|
+ } else {
|
|
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) {
|
|
+ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) {
|
|
+ x = 0;
|
|
+ tx = 0;
|
|
+ y += pps->row_height_minus1[ty++] + 1;
|
|
+ } else {
|
|
+ x += pps->column_width_minus1[tx++] + 1;
|
|
+ }
|
|
+
|
|
+ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1;
|
|
+ entry_points[i * 4 + 1] = 0x0;
|
|
+ entry_points[i * 4 + 2] = (y << 16) | (x << 0);
|
|
+ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
struct cedrus_run *run)
|
|
{
|
|
@@ -340,6 +395,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
|
|
unsigned int width_in_ctb_luma, ctb_size_luma;
|
|
unsigned int log2_max_luma_coding_block_size;
|
|
+ unsigned int ctb_addr_x, ctb_addr_y;
|
|
dma_addr_t src_buf_addr;
|
|
dma_addr_t src_buf_end_addr;
|
|
u32 chroma_log2_weight_denom;
|
|
@@ -419,12 +475,19 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
|
|
|
|
/* Coding tree block address */
|
|
- reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma);
|
|
- reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma);
|
|
+ ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma;
|
|
+ ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma;
|
|
+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x);
|
|
+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y);
|
|
cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
|
|
|
|
- cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
|
|
- cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
|
|
+ if ((pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) ||
|
|
+ (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) {
|
|
+ write_entry_point_list(ctx, run, ctb_addr_x, ctb_addr_y);
|
|
+ } else {
|
|
+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
|
|
+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
|
|
+ }
|
|
|
|
/* Clear the number of correctly-decoded coding tree blocks. */
|
|
if (ctx->fh.m2m_ctx->new_frame)
|
|
@@ -528,7 +591,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED,
|
|
pps->flags);
|
|
|
|
- /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */
|
|
+ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED,
|
|
+ V4L2_HEVC_PPS_FLAG_TILES_ENABLED,
|
|
+ pps->flags);
|
|
|
|
reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED,
|
|
V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED,
|
|
@@ -606,12 +671,14 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
|
|
chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
|
|
pred_weight_table->delta_chroma_log2_weight_denom;
|
|
- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) |
|
|
+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) |
|
|
VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
|
|
VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
|
|
|
|
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
|
|
|
|
+ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8);
|
|
+
|
|
/* Decoded picture size. */
|
|
|
|
reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
|
|
@@ -706,6 +773,17 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
|
|
if (!ctx->codec.h265.neighbor_info_buf)
|
|
return -ENOMEM;
|
|
|
|
+ ctx->codec.h265.entry_points_buf =
|
|
+ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
|
|
+ &ctx->codec.h265.entry_points_buf_addr,
|
|
+ GFP_KERNEL);
|
|
+ if (!ctx->codec.h265.entry_points_buf) {
|
|
+ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
|
+ ctx->codec.h265.neighbor_info_buf,
|
|
+ ctx->codec.h265.neighbor_info_buf_addr);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -726,6 +804,9 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
|
|
ctx->codec.h265.neighbor_info_buf,
|
|
ctx->codec.h265.neighbor_info_buf_addr,
|
|
DMA_ATTR_NO_KERNEL_MAPPING);
|
|
+ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
|
|
+ ctx->codec.h265.entry_points_buf,
|
|
+ ctx->codec.h265.entry_points_buf_addr);
|
|
}
|
|
|
|
static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
|
|
--
|
|
2.35.3
|
|
|