diff options
Diffstat (limited to 'drivers/staging/media/sunxi/cedrus/cedrus_h265.c')
-rw-r--r-- | drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 100 |
1 files changed, 86 insertions, 14 deletions
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c index ef0311a16d01..8829a7bab07e 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c @@ -238,6 +238,69 @@ static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) } } +static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, + struct cedrus_run *run) +{ + const struct v4l2_ctrl_hevc_scaling_matrix *scaling; + struct cedrus_dev *dev = ctx->dev; + u32 i, j, k, val; + + scaling = run->h265.scaling_matrix; + + cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0, + (scaling->scaling_list_dc_coef_32x32[1] << 24) | + (scaling->scaling_list_dc_coef_32x32[0] << 16) | + (scaling->scaling_list_dc_coef_16x16[1] << 8) | + (scaling->scaling_list_dc_coef_16x16[0] << 0)); + + cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1, + (scaling->scaling_list_dc_coef_16x16[5] << 24) | + (scaling->scaling_list_dc_coef_16x16[4] << 16) | + (scaling->scaling_list_dc_coef_16x16[3] << 8) | + (scaling->scaling_list_dc_coef_16x16[2] << 0)); + + cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS); + + for (i = 0; i < 6; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k += 4) { + val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) | + ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) | + ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) | + scaling->scaling_list_8x8[i][j + k * 8]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } + + for (i = 0; i < 2; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k += 4) { + val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) | + ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) | + ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) | + scaling->scaling_list_32x32[i][j + k * 8]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } + + for (i = 0; i < 6; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k += 4) { + val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) | + ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) | + ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) | + scaling->scaling_list_16x16[i][j + k * 8]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } + + for (i = 0; i < 6; i++) + for (j = 0; j < 4; j++) { + val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) | + ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) | + ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) | + scaling->scaling_list_4x4[i][j]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } +} + static void cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) { @@ -287,11 +350,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, ctx->codec.h265.mv_col_buf_size = num_buffers * ctx->codec.h265.mv_col_buf_unit_size; + /* Buffer is never accessed by CPU, so we can skip kernel mapping. */ ctx->codec.h265.mv_col_buf = - dma_alloc_coherent(dev->dev, - ctx->codec.h265.mv_col_buf_size, - &ctx->codec.h265.mv_col_buf_addr, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, + ctx->codec.h265.mv_col_buf_size, + &ctx->codec.h265.mv_col_buf_addr, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h265.mv_col_buf) { ctx->codec.h265.mv_col_buf_size = 0; // TODO: Abort the process here. @@ -527,7 +591,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, /* Scaling list. */ - reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; + if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) { + cedrus_h265_write_scaling_list(ctx, run); + reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED; + } else { + reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; + } cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); /* Neightbor information address. */ @@ -599,10 +668,11 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) /* The buffer size is calculated at setup time. */ ctx->codec.h265.mv_col_buf_size = 0; + /* Buffer is never accessed by CPU, so we can skip kernel mapping. */ ctx->codec.h265.neighbor_info_buf = - dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - &ctx->codec.h265.neighbor_info_buf_addr, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + &ctx->codec.h265.neighbor_info_buf_addr, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h265.neighbor_info_buf) return -ENOMEM; @@ -614,16 +684,18 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) struct cedrus_dev *dev = ctx->dev; if (ctx->codec.h265.mv_col_buf_size > 0) { - dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, - ctx->codec.h265.mv_col_buf, - ctx->codec.h265.mv_col_buf_addr); + dma_free_attrs(dev->dev, ctx->codec.h265.mv_col_buf_size, + ctx->codec.h265.mv_col_buf, + ctx->codec.h265.mv_col_buf_addr, + DMA_ATTR_NO_KERNEL_MAPPING); ctx->codec.h265.mv_col_buf_size = 0; } - dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h265.neighbor_info_buf, - ctx->codec.h265.neighbor_info_buf_addr); + dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr, + DMA_ATTR_NO_KERNEL_MAPPING); } static void cedrus_h265_trigger(struct cedrus_ctx *ctx) |