Hi, Le vendredi 07 septembre 2018 à 07:33 +0000, Priit Laes a écrit : > On Fri, Sep 07, 2018 at 12:24:38AM +0200, Paul Kocialkowski wrote: > > From: Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx> > > > > This introduces the Cedrus VPU driver that supports the VPU found in > > Allwinner SoCs, also known as Video Engine. It is implemented through > > a V4L2 M2M decoder device and a media device (used for media requests). > > So far, it only supports MPEG-2 decoding. > > > > Since this VPU is stateless, synchronization with media requests is > > required in order to ensure consistency between frame headers that > > contain metadata about the frame to process and the raw slice data that > > is used to generate the frame. > > > > This driver was made possible thanks to the long-standing effort > > carried out by the linux-sunxi community in the interest of reverse > > engineering, documenting and implementing support for the Allwinner VPU. > > > > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx> > > Acked-by: Maxime Ripard <maxime.ripard@xxxxxxxxxxx> > > --- > > [...] > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c > > new file mode 100644 > > index 000000000000..029eb1626bf4 > > --- /dev/null > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c > > @@ -0,0 +1,237 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Cedrus VPU driver > > + * > > + * Copyright (C) 2016 Florent Revest <florent.revest@xxxxxxxxxxxxxxxxxx> > > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx> > > + * Copyright (C) 2018 Bootlin > > + */ > > + > > +#include <media/videobuf2-dma-contig.h> > > + > > +#include "cedrus.h" > > +#include "cedrus_hw.h" > > +#include "cedrus_regs.h" > > + > > +/* Default MPEG-2 quantization coefficients, from the specification. */ > > + > > +static const u8 intra_quantization_matrix_default[64] = { > > + 8, 16, 16, 19, 16, 19, 22, 22, > > + 22, 22, 22, 22, 26, 24, 26, 27, > > + 27, 27, 26, 26, 26, 26, 27, 27, > > + 27, 29, 29, 29, 34, 34, 34, 29, > > + 29, 29, 27, 27, 29, 29, 32, 32, > > + 34, 34, 37, 38, 37, 35, 35, 34, > > + 35, 38, 38, 40, 40, 40, 48, 48, > > + 46, 46, 56, 56, 58, 69, 69, 83 > > +}; > > I think it should also mention that the table above is the DC > prediction table, already in the zig-zag order. Good idea, although this is certainly not worth sending a new revision for. Feel free to suggest this change on top of the series if I don't! Cheers, Paul > 8, 16, 19, 22, 26, 27, 29, 34, > 16, 16, 22, 24, 27, 29, 34, 37, > 19, 22, 26, 27, 29, 34, 34, 38, > 22, 22, 26, 27, 29, 34, 37, 40, > 22, 26, 27, 29, 32, 35, 40, 48, > 26, 27, 29, 32, 35, 40, 48, 58, > 26, 27, 29, 34, 38, 46, 56, 69, > 27, 29, 35, 38, 46, 56, 69, 83 > > See slides no 466 and 486 in following pdf: > http://iphome.hhi.de/schwarz/assets/pdfs/08_ImageCoding.pdf > > + > > +static const u8 non_intra_quantization_matrix_default[64] = { > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16, > > + 16, 16, 16, 16, 16, 16, 16, 16 > > +}; > > + > > +static enum cedrus_irq_status cedrus_mpeg2_irq_status(struct cedrus_ctx *ctx) > > +{ > > + struct cedrus_dev *dev = ctx->dev; > > + u32 reg; > > + > > + reg = cedrus_read(dev, VE_DEC_MPEG_STATUS); > > + reg &= VE_DEC_MPEG_STATUS_CHECK_MASK; > > + > > + if (!reg) > > + return CEDRUS_IRQ_NONE; > > + > > + if (reg & VE_DEC_MPEG_STATUS_CHECK_ERROR || > > + !(reg & VE_DEC_MPEG_STATUS_SUCCESS)) > > + return CEDRUS_IRQ_ERROR; > > + > > + return CEDRUS_IRQ_OK; > > +} > > + > > +static void cedrus_mpeg2_irq_clear(struct cedrus_ctx *ctx) > > +{ > > + struct cedrus_dev *dev = ctx->dev; > > + > > + cedrus_write(dev, VE_DEC_MPEG_STATUS, VE_DEC_MPEG_STATUS_CHECK_MASK); > > +} > > + > > +static void cedrus_mpeg2_irq_disable(struct cedrus_ctx *ctx) > > +{ > > + struct cedrus_dev *dev = ctx->dev; > > + u32 reg = cedrus_read(dev, VE_DEC_MPEG_CTRL); > > + > > + reg &= ~VE_DEC_MPEG_CTRL_IRQ_MASK; > > + > > + cedrus_write(dev, VE_DEC_MPEG_CTRL, reg); > > +} > > + > > +static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) > > +{ > > + const struct v4l2_ctrl_mpeg2_slice_params *slice_params; > > + const struct v4l2_mpeg2_sequence *sequence; > > + const struct v4l2_mpeg2_picture *picture; > > + const struct v4l2_ctrl_mpeg2_quantization *quantization; > > + dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr; > > + dma_addr_t fwd_luma_addr, fwd_chroma_addr; > > + dma_addr_t bwd_luma_addr, bwd_chroma_addr; > > + struct cedrus_dev *dev = ctx->dev; > > + const u8 *matrix; > > + unsigned int i; > > + u32 reg; > > + > > + slice_params = run->mpeg2.slice_params; > > + sequence = &slice_params->sequence; > > + picture = &slice_params->picture; > > + > > + quantization = run->mpeg2.quantization; > > + > > + /* Activate MPEG engine. */ > > + cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2); > > + > > + /* Set intra quantization matrix. */ > > + > > + if (quantization && quantization->load_intra_quantiser_matrix) > > + matrix = quantization->intra_quantiser_matrix; > > + else > > + matrix = intra_quantization_matrix_default; > > + > > + for (i = 0; i < 64; i++) { > > + reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]); > > + reg |= VE_DEC_MPEG_IQMINPUT_FLAG_INTRA; > > + > > + cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg); > > + } > > + > > + /* Set non-intra quantization matrix. */ > > + > > + if (quantization && quantization->load_non_intra_quantiser_matrix) > > + matrix = quantization->non_intra_quantiser_matrix; > > + else > > + matrix = non_intra_quantization_matrix_default; > > + > > + for (i = 0; i < 64; i++) { > > + reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]); > > + reg |= VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA; > > + > > + cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg); > > + } > > + > > + /* Set MPEG picture header. */ > > + > > + reg = VE_DEC_MPEG_MP12HDR_SLICE_TYPE(picture->picture_coding_type); > > + reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 0, picture->f_code[0][0]); > > + reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 1, picture->f_code[0][1]); > > + reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 0, picture->f_code[1][0]); > > + reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 1, picture->f_code[1][1]); > > + reg |= VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(picture->intra_dc_precision); > > + reg |= VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(picture->picture_structure); > > + reg |= VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(picture->top_field_first); > > + reg |= VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(picture->frame_pred_frame_dct); > > + reg |= VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(picture->concealment_motion_vectors); > > + reg |= VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(picture->q_scale_type); > > + reg |= VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(picture->intra_vlc_format); > > + reg |= VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(picture->alternate_scan); > > + reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_FORWARD_VECTOR(0); > > + reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_BACKWARD_VECTOR(0); > > + > > + cedrus_write(dev, VE_DEC_MPEG_MP12HDR, reg); > > + > > + /* Set frame dimensions. */ > > + > > + reg = VE_DEC_MPEG_PICCODEDSIZE_WIDTH(sequence->horizontal_size); > > + reg |= VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(sequence->vertical_size); > > + > > + cedrus_write(dev, VE_DEC_MPEG_PICCODEDSIZE, reg); > > + > > + reg = VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(ctx->src_fmt.width); > > + reg |= VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(ctx->src_fmt.height); > > + > > + cedrus_write(dev, VE_DEC_MPEG_PICBOUNDSIZE, reg); > > + > > + /* Forward and backward prediction reference buffers. */ > > + > > + fwd_luma_addr = cedrus_dst_buf_addr(ctx, slice_params->forward_ref_index, 0); > > + fwd_chroma_addr = cedrus_dst_buf_addr(ctx, slice_params->forward_ref_index, 1); > > + > > + cedrus_write(dev, VE_DEC_MPEG_FWD_REF_LUMA_ADDR, fwd_luma_addr); > > + cedrus_write(dev, VE_DEC_MPEG_FWD_REF_CHROMA_ADDR, fwd_chroma_addr); > > + > > + bwd_luma_addr = cedrus_dst_buf_addr(ctx, slice_params->backward_ref_index, 0); > > + bwd_chroma_addr = cedrus_dst_buf_addr(ctx, slice_params->backward_ref_index, 1); > > + > > + cedrus_write(dev, VE_DEC_MPEG_BWD_REF_LUMA_ADDR, bwd_luma_addr); > > + cedrus_write(dev, VE_DEC_MPEG_BWD_REF_CHROMA_ADDR, bwd_chroma_addr); > > + > > + /* Destination luma and chroma buffers. */ > > + > > + dst_luma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 0); > > + dst_chroma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 1); > > + > > + cedrus_write(dev, VE_DEC_MPEG_REC_LUMA, dst_luma_addr); > > + cedrus_write(dev, VE_DEC_MPEG_REC_CHROMA, dst_chroma_addr); > > + > > + /* Source offset and length in bits. */ > > + > > + cedrus_write(dev, VE_DEC_MPEG_VLD_OFFSET, slice_params->data_bit_offset); > > + > > + reg = slice_params->bit_size - slice_params->data_bit_offset; > > + cedrus_write(dev, VE_DEC_MPEG_VLD_LEN, reg); > > + > > + /* Source beginning and end addresses. */ > > + > > + src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0); > > + > > + reg = VE_DEC_MPEG_VLD_ADDR_BASE(src_buf_addr); > > + reg |= VE_DEC_MPEG_VLD_ADDR_VALID_PIC_DATA; > > + reg |= VE_DEC_MPEG_VLD_ADDR_LAST_PIC_DATA; > > + reg |= VE_DEC_MPEG_VLD_ADDR_FIRST_PIC_DATA; > > + > > + cedrus_write(dev, VE_DEC_MPEG_VLD_ADDR, reg); > > + > > + reg = src_buf_addr + DIV_ROUND_UP(slice_params->bit_size, 8); > > + cedrus_write(dev, VE_DEC_MPEG_VLD_END_ADDR, reg); > > + > > + /* Macroblock address: start at the beginning. */ > > + reg = VE_DEC_MPEG_MBADDR_Y(0) | VE_DEC_MPEG_MBADDR_X(0); > > + cedrus_write(dev, VE_DEC_MPEG_MBADDR, reg); > > + > > + /* Clear previous errors. */ > > + cedrus_write(dev, VE_DEC_MPEG_ERROR, 0); > > + > > + /* Clear correct macroblocks register. */ > > + cedrus_write(dev, VE_DEC_MPEG_CRTMBADDR, 0); > > + > > + /* Enable appropriate interruptions and components. */ > > + > > + reg = VE_DEC_MPEG_CTRL_IRQ_MASK | VE_DEC_MPEG_CTRL_MC_NO_WRITEBACK | > > + VE_DEC_MPEG_CTRL_MC_CACHE_EN; > > + > > + cedrus_write(dev, VE_DEC_MPEG_CTRL, reg); > > +} > > + > > +static void cedrus_mpeg2_trigger(struct cedrus_ctx *ctx) > > +{ > > + struct cedrus_dev *dev = ctx->dev; > > + u32 reg; > > + > > + /* Trigger MPEG engine. */ > > + reg = VE_DEC_MPEG_TRIGGER_HW_MPEG_VLD | VE_DEC_MPEG_TRIGGER_MPEG2 | > > + VE_DEC_MPEG_TRIGGER_MB_BOUNDARY; > > + > > + cedrus_write(dev, VE_DEC_MPEG_TRIGGER, reg); > > +} > > + > > +struct cedrus_dec_ops cedrus_dec_ops_mpeg2 = { > > + .irq_clear = cedrus_mpeg2_irq_clear, > > + .irq_disable = cedrus_mpeg2_irq_disable, > > + .irq_status = cedrus_mpeg2_irq_status, > > + .setup = cedrus_mpeg2_setup, > > + .trigger = cedrus_mpeg2_trigger, > > +}; > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h > > new file mode 100644 > > index 000000000000..9b14d1fb94a0 > > --- /dev/null > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h > > @@ -0,0 +1,233 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Cedrus VPU driver > > + * > > + * Copyright (c) 2013-2016 Jens Kuske <jenskuske@xxxxxxxxx> > > + * Copyright (C) 2016 Florent Revest <florent.revest@xxxxxxxxxxxxxxxxxx> > > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx> > > + */ > > + > > +#ifndef _CEDRUS_REGS_H_ > > +#define _CEDRUS_REGS_H_ > > + > > +/* > > + * Common acronyms and contractions used in register descriptions: > > + * * VLD : Variable-Length Decoder > > + * * IQ: Inverse Quantization > > + * * IDCT: Inverse Discrete Cosine Transform > > + * * MC: Motion Compensation > > + * * STCD: Start Code Detect > > + * * SDRT: Scale Down and Rotate > > + */ > > + > > +#define VE_ENGINE_DEC_MPEG 0x100 > > +#define VE_ENGINE_DEC_H264 0x200 > > + > > +#define VE_MODE 0x00 > > + > > +#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_DISABLED (0x07 << 0) > > +#define VE_MODE_DEC_H265 (0x04 << 0) > > +#define VE_MODE_DEC_H264 (0x01 << 0) > > +#define VE_MODE_DEC_MPEG (0x00 << 0) > > + > > +#define VE_PRIMARY_CHROMA_BUF_LEN 0xc4 > > +#define VE_PRIMARY_FB_LINE_STRIDE 0xc8 > > + > > +#define VE_PRIMARY_FB_LINE_STRIDE_CHROMA(s) (((s) << 16) & GENMASK(31, 16)) > > +#define VE_PRIMARY_FB_LINE_STRIDE_LUMA(s) (((s) << 0) & GENMASK(15, 0)) > > + > > +#define VE_CHROMA_BUF_LEN 0xe8 > > + > > +#define VE_SECONDARY_OUT_FMT_TILED_32_NV12 (0x00 << 30) > > +#define VE_SECONDARY_OUT_FMT_EXT (0x01 << 30) > > +#define VE_SECONDARY_OUT_FMT_YU12 (0x02 << 30) > > +#define VE_SECONDARY_OUT_FMT_YV12 (0x03 << 30) > > +#define VE_CHROMA_BUF_LEN_SDRT(l) ((l) & GENMASK(27, 0)) > > + > > +#define VE_PRIMARY_OUT_FMT 0xec > > + > > +#define VE_PRIMARY_OUT_FMT_TILED_32_NV12 (0x00 << 4) > > +#define VE_PRIMARY_OUT_FMT_TILED_128_NV12 (0x01 << 4) > > +#define VE_PRIMARY_OUT_FMT_YU12 (0x02 << 4) > > +#define VE_PRIMARY_OUT_FMT_YV12 (0x03 << 4) > > +#define VE_PRIMARY_OUT_FMT_NV12 (0x04 << 4) > > +#define VE_PRIMARY_OUT_FMT_NV21 (0x05 << 4) > > +#define VE_SECONDARY_OUT_FMT_EXT_TILED_32_NV12 (0x00 << 0) > > +#define VE_SECONDARY_OUT_FMT_EXT_TILED_128_NV12 (0x01 << 0) > > +#define VE_SECONDARY_OUT_FMT_EXT_YU12 (0x02 << 0) > > +#define VE_SECONDARY_OUT_FMT_EXT_YV12 (0x03 << 0) > > +#define VE_SECONDARY_OUT_FMT_EXT_NV12 (0x04 << 0) > > +#define VE_SECONDARY_OUT_FMT_EXT_NV21 (0x05 << 0) > > + > > +#define VE_VERSION 0xf0 > > + > > +#define VE_VERSION_SHIFT 16 > > + > > +#define VE_DEC_MPEG_MP12HDR (VE_ENGINE_DEC_MPEG + 0x00) > > + > > +#define VE_DEC_MPEG_MP12HDR_SLICE_TYPE(t) (((t) << 28) & GENMASK(30, 28)) > > +#define VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(x, y) (24 - 4 * (y) - 8 * (x)) > > +#define VE_DEC_MPEG_MP12HDR_F_CODE_MASK(x, y) \ > > + GENMASK(VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(x, y) + 3, \ > > + VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(x, y)) > > +#define VE_DEC_MPEG_MP12HDR_F_CODE(x, y, v) \ > > + (((v) << VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(x, y)) & \ > > + VE_DEC_MPEG_MP12HDR_F_CODE_MASK(x, y)) > > +#define VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(p) \ > > + (((p) << 10) & GENMASK(11, 10)) > > +#define VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(s) \ > > + (((s) << 8) & GENMASK(9, 8)) > > +#define VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(v) \ > > + ((v) ? BIT(7) : 0) > > +#define VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(v) \ > > + ((v) ? BIT(6) : 0) > > +#define VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(v) \ > > + ((v) ? BIT(5) : 0) > > +#define VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(v) \ > > + ((v) ? BIT(4) : 0) > > +#define VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(v) \ > > + ((v) ? BIT(3) : 0) > > +#define VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(v) \ > > + ((v) ? BIT(2) : 0) > > +#define VE_DEC_MPEG_MP12HDR_FULL_PEL_FORWARD_VECTOR(v) \ > > + ((v) ? BIT(1) : 0) > > +#define VE_DEC_MPEG_MP12HDR_FULL_PEL_BACKWARD_VECTOR(v) \ > > + ((v) ? BIT(0) : 0) > > + > > +#define VE_DEC_MPEG_PICCODEDSIZE (VE_ENGINE_DEC_MPEG + 0x08) > > + > > +#define VE_DEC_MPEG_PICCODEDSIZE_WIDTH(w) \ > > + ((DIV_ROUND_UP((w), 16) << 8) & GENMASK(15, 8)) > > +#define VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(h) \ > > + ((DIV_ROUND_UP((h), 16) << 0) & GENMASK(7, 0)) > > + > > +#define VE_DEC_MPEG_PICBOUNDSIZE (VE_ENGINE_DEC_MPEG + 0x0c) > > + > > +#define VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(w) (((w) << 16) & GENMASK(27, 16)) > > +#define VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(h) (((h) << 0) & GENMASK(11, 0)) > > + > > +#define VE_DEC_MPEG_MBADDR (VE_ENGINE_DEC_MPEG + 0x10) > > + > > +#define VE_DEC_MPEG_MBADDR_X(w) (((w) << 8) & GENMASK(15, 8)) > > +#define VE_DEC_MPEG_MBADDR_Y(h) (((h) << 0) & GENMASK(0, 7)) > > + > > +#define VE_DEC_MPEG_CTRL (VE_ENGINE_DEC_MPEG + 0x14) > > + > > +#define VE_DEC_MPEG_CTRL_MC_CACHE_EN BIT(31) > > +#define VE_DEC_MPEG_CTRL_SW_VLD BIT(27) > > +#define VE_DEC_MPEG_CTRL_SW_IQ_IS BIT(17) > > +#define VE_DEC_MPEG_CTRL_QP_AC_DC_OUT_EN BIT(14) > > +#define VE_DEC_MPEG_CTRL_ROTATE_SCALE_OUT_EN BIT(8) > > +#define VE_DEC_MPEG_CTRL_MC_NO_WRITEBACK BIT(7) > > +#define VE_DEC_MPEG_CTRL_ROTATE_IRQ_EN BIT(6) > > +#define VE_DEC_MPEG_CTRL_VLD_DATA_REQ_IRQ_EN BIT(5) > > +#define VE_DEC_MPEG_CTRL_ERROR_IRQ_EN BIT(4) > > +#define VE_DEC_MPEG_CTRL_FINISH_IRQ_EN BIT(3) > > +#define VE_DEC_MPEG_CTRL_IRQ_MASK \ > > + (VE_DEC_MPEG_CTRL_FINISH_IRQ_EN | VE_DEC_MPEG_CTRL_ERROR_IRQ_EN | \ > > + VE_DEC_MPEG_CTRL_VLD_DATA_REQ_IRQ_EN) > > + > > +#define VE_DEC_MPEG_TRIGGER (VE_ENGINE_DEC_MPEG + 0x18) > > + > > +#define VE_DEC_MPEG_TRIGGER_MB_BOUNDARY BIT(31) > > + > > +#define VE_DEC_MPEG_TRIGGER_CHROMA_FMT_420 (0x00 << 27) > > +#define VE_DEC_MPEG_TRIGGER_CHROMA_FMT_411 (0x01 << 27) > > +#define VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422 (0x02 << 27) > > +#define VE_DEC_MPEG_TRIGGER_CHROMA_FMT_444 (0x03 << 27) > > +#define VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422T (0x04 << 27) > > + > > +#define VE_DEC_MPEG_TRIGGER_MPEG1 (0x01 << 24) > > +#define VE_DEC_MPEG_TRIGGER_MPEG2 (0x02 << 24) > > +#define VE_DEC_MPEG_TRIGGER_JPEG (0x03 << 24) > > +#define VE_DEC_MPEG_TRIGGER_MPEG4 (0x04 << 24) > > +#define VE_DEC_MPEG_TRIGGER_VP62 (0x05 << 24) > > + > > +#define VE_DEC_MPEG_TRIGGER_VP62_AC_GET_BITS BIT(7) > > + > > +#define VE_DEC_MPEG_TRIGGER_STCD_VC1 (0x02 << 4) > > +#define VE_DEC_MPEG_TRIGGER_STCD_MPEG2 (0x01 << 4) > > +#define VE_DEC_MPEG_TRIGGER_STCD_AVC (0x00 << 4) > > + > > +#define VE_DEC_MPEG_TRIGGER_HW_MPEG_VLD (0x0f << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_JPEG_VLD (0x0e << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_MB (0x0d << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_ROTATE (0x0c << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_VP6_VLD (0x0b << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_MAF (0x0a << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_STCD_END (0x09 << 0) > > +#define VE_DEC_MPEG_TRIGGER_HW_STCD_BEGIN (0x08 << 0) > > +#define VE_DEC_MPEG_TRIGGER_SW_MC (0x07 << 0) > > +#define VE_DEC_MPEG_TRIGGER_SW_IQ (0x06 << 0) > > +#define VE_DEC_MPEG_TRIGGER_SW_IDCT (0x05 << 0) > > +#define VE_DEC_MPEG_TRIGGER_SW_SCALE (0x04 << 0) > > +#define VE_DEC_MPEG_TRIGGER_SW_VP6 (0x03 << 0) > > +#define VE_DEC_MPEG_TRIGGER_SW_VP62_AC_GET_BITS (0x02 << 0) > > + > > +#define VE_DEC_MPEG_STATUS (VE_ENGINE_DEC_MPEG + 0x1c) > > + > > +#define VE_DEC_MPEG_STATUS_START_DETECT_BUSY BIT(27) > > +#define VE_DEC_MPEG_STATUS_VP6_BIT BIT(26) > > +#define VE_DEC_MPEG_STATUS_VP6_BIT_BUSY BIT(25) > > +#define VE_DEC_MPEG_STATUS_MAF_BUSY BIT(23) > > +#define VE_DEC_MPEG_STATUS_VP6_MVP_BUSY BIT(22) > > +#define VE_DEC_MPEG_STATUS_JPEG_BIT_END BIT(21) > > +#define VE_DEC_MPEG_STATUS_JPEG_RESTART_ERROR BIT(20) > > +#define VE_DEC_MPEG_STATUS_JPEG_MARKER BIT(19) > > +#define VE_DEC_MPEG_STATUS_ROTATE_BUSY BIT(18) > > +#define VE_DEC_MPEG_STATUS_DEBLOCKING_BUSY BIT(17) > > +#define VE_DEC_MPEG_STATUS_SCALE_DOWN_BUSY BIT(16) > > +#define VE_DEC_MPEG_STATUS_IQIS_BUF_EMPTY BIT(15) > > +#define VE_DEC_MPEG_STATUS_IDCT_BUF_EMPTY BIT(14) > > +#define VE_DEC_MPEG_STATUS_VE_BUSY BIT(13) > > +#define VE_DEC_MPEG_STATUS_MC_BUSY BIT(12) > > +#define VE_DEC_MPEG_STATUS_IDCT_BUSY BIT(11) > > +#define VE_DEC_MPEG_STATUS_IQIS_BUSY BIT(10) > > +#define VE_DEC_MPEG_STATUS_DCAC_BUSY BIT(9) > > +#define VE_DEC_MPEG_STATUS_VLD_BUSY BIT(8) > > +#define VE_DEC_MPEG_STATUS_ROTATE_SUCCESS BIT(3) > > +#define VE_DEC_MPEG_STATUS_VLD_DATA_REQ BIT(2) > > +#define VE_DEC_MPEG_STATUS_ERROR BIT(1) > > +#define VE_DEC_MPEG_STATUS_SUCCESS BIT(0) > > +#define VE_DEC_MPEG_STATUS_CHECK_MASK \ > > + (VE_DEC_MPEG_STATUS_SUCCESS | VE_DEC_MPEG_STATUS_ERROR | \ > > + VE_DEC_MPEG_STATUS_VLD_DATA_REQ) > > +#define VE_DEC_MPEG_STATUS_CHECK_ERROR \ > > + (VE_DEC_MPEG_STATUS_ERROR | VE_DEC_MPEG_STATUS_VLD_DATA_REQ) > > + > > +#define VE_DEC_MPEG_VLD_ADDR (VE_ENGINE_DEC_MPEG + 0x28) > > + > > +#define VE_DEC_MPEG_VLD_ADDR_FIRST_PIC_DATA BIT(30) > > +#define VE_DEC_MPEG_VLD_ADDR_LAST_PIC_DATA BIT(29) > > +#define VE_DEC_MPEG_VLD_ADDR_VALID_PIC_DATA BIT(28) > > +#define VE_DEC_MPEG_VLD_ADDR_BASE(a) \ > > + (((a) & GENMASK(27, 4)) | (((a) >> 28) & GENMASK(3, 0))) > > + > > +#define VE_DEC_MPEG_VLD_OFFSET (VE_ENGINE_DEC_MPEG + 0x2c) > > +#define VE_DEC_MPEG_VLD_LEN (VE_ENGINE_DEC_MPEG + 0x30) > > +#define VE_DEC_MPEG_VLD_END_ADDR (VE_ENGINE_DEC_MPEG + 0x34) > > + > > +#define VE_DEC_MPEG_REC_LUMA (VE_ENGINE_DEC_MPEG + 0x48) > > +#define VE_DEC_MPEG_REC_CHROMA (VE_ENGINE_DEC_MPEG + 0x4c) > > +#define VE_DEC_MPEG_FWD_REF_LUMA_ADDR (VE_ENGINE_DEC_MPEG + 0x50) > > +#define VE_DEC_MPEG_FWD_REF_CHROMA_ADDR (VE_ENGINE_DEC_MPEG + 0x54) > > +#define VE_DEC_MPEG_BWD_REF_LUMA_ADDR (VE_ENGINE_DEC_MPEG + 0x58) > > +#define VE_DEC_MPEG_BWD_REF_CHROMA_ADDR (VE_ENGINE_DEC_MPEG + 0x5c) > > + > > +#define VE_DEC_MPEG_IQMINPUT (VE_ENGINE_DEC_MPEG + 0x80) > > + > > +#define VE_DEC_MPEG_IQMINPUT_FLAG_INTRA (0x01 << 14) > > +#define VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA (0x00 << 14) > > +#define VE_DEC_MPEG_IQMINPUT_WEIGHT(i, v) \ > > + (((v) & GENMASK(7, 0)) | (((i) << 8) & GENMASK(13, 8))) > > + > > +#define VE_DEC_MPEG_ERROR (VE_ENGINE_DEC_MPEG + 0xc4) > > +#define VE_DEC_MPEG_CRTMBADDR (VE_ENGINE_DEC_MPEG + 0xc8) > > +#define VE_DEC_MPEG_ROT_LUMA (VE_ENGINE_DEC_MPEG + 0xcc) > > +#define VE_DEC_MPEG_ROT_CHROMA (VE_ENGINE_DEC_MPEG + 0xd0) > > + > > +#endif > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c > > new file mode 100644 > > index 000000000000..bd119d2c4e1f > > --- /dev/null > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c > > @@ -0,0 +1,544 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Cedrus VPU driver > > + * > > + * Copyright (C) 2016 Florent Revest <florent.revest@xxxxxxxxxxxxxxxxxx> > > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx> > > + * Copyright (C) 2018 Bootlin > > + * > > + * Based on the vim2m driver, that is: > > + * > > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. > > + * Pawel Osciak, <pawel@xxxxxxxxxx> > > + * Marek Szyprowski, <m.szyprowski@xxxxxxxxxxx> > > + */ > > + > > +#include <media/videobuf2-dma-contig.h> > > +#include <media/v4l2-device.h> > > +#include <media/v4l2-ioctl.h> > > +#include <media/v4l2-event.h> > > +#include <media/v4l2-mem2mem.h> > > + > > +#include "cedrus.h" > > +#include "cedrus_video.h" > > +#include "cedrus_dec.h" > > +#include "cedrus_hw.h" > > + > > +#define CEDRUS_DECODE_SRC BIT(0) > > +#define CEDRUS_DECODE_DST BIT(1) > > + > > +#define CEDRUS_MIN_WIDTH 16U > > +#define CEDRUS_MIN_HEIGHT 16U > > +#define CEDRUS_MAX_WIDTH 3840U > > +#define CEDRUS_MAX_HEIGHT 2160U > > + > > +static struct cedrus_format cedrus_formats[] = { > > + { > > + .pixelformat = V4L2_PIX_FMT_MPEG2_SLICE, > > + .directions = CEDRUS_DECODE_SRC, > > + }, > > + { > > + .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, > > + .directions = CEDRUS_DECODE_DST, > > + }, > > + { > > + .pixelformat = V4L2_PIX_FMT_NV12, > > + .directions = CEDRUS_DECODE_DST, > > + .capabilities = CEDRUS_CAPABILITY_UNTILED, > > + }, > > +}; > > + > > +#define CEDRUS_FORMATS_COUNT ARRAY_SIZE(cedrus_formats) > > + > > +static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file) > > +{ > > + return container_of(file->private_data, struct cedrus_ctx, fh); > > +} > > + > > +static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions, > > + unsigned int capabilities) > > +{ > > + struct cedrus_format *fmt; > > + unsigned int i; > > + > > + for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) { > > + fmt = &cedrus_formats[i]; > > + > > + if (fmt->capabilities && (fmt->capabilities & capabilities) != > > + fmt->capabilities) > > + continue; > > + > > + if (fmt->pixelformat == pixelformat && > > + (fmt->directions & directions) != 0) > > + break; > > + } > > + > > + if (i == CEDRUS_FORMATS_COUNT) > > + return NULL; > > + > > + return &cedrus_formats[i]; > > +} > > + > > +static bool cedrus_check_format(u32 pixelformat, u32 directions, > > + unsigned int capabilities) > > +{ > > + struct cedrus_format *fmt = cedrus_find_format(pixelformat, directions, > > + capabilities); > > + > > + return fmt != NULL; > > +} > > + > > +static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) > > +{ > > + unsigned int width = pix_fmt->width; > > + unsigned int height = pix_fmt->height; > > + unsigned int sizeimage = pix_fmt->sizeimage; > > + unsigned int bytesperline = pix_fmt->bytesperline; > > + > > + pix_fmt->field = V4L2_FIELD_NONE; > > + > > + /* Limit to hardware min/max. */ > > + width = clamp(width, CEDRUS_MIN_WIDTH, CEDRUS_MAX_WIDTH); > > + height = clamp(height, CEDRUS_MIN_HEIGHT, CEDRUS_MAX_HEIGHT); > > + > > + switch (pix_fmt->pixelformat) { > > + case V4L2_PIX_FMT_MPEG2_SLICE: > > + /* Zero bytes per line for encoded source. */ > > + bytesperline = 0; > > + > > + break; > > + > > + case V4L2_PIX_FMT_SUNXI_TILED_NV12: > > + /* 32-aligned stride. */ > > + bytesperline = ALIGN(width, 32); > > + > > + /* 32-aligned height. */ > > + height = ALIGN(height, 32); > > + > > + /* Luma plane size. */ > > + sizeimage = bytesperline * height; > > + > > + /* Chroma plane size. */ > > + sizeimage += bytesperline * height / 2; > > + > > + break; > > + > > + case V4L2_PIX_FMT_NV12: > > + /* 16-aligned stride. */ > > + bytesperline = ALIGN(width, 16); > > + > > + /* 16-aligned height. */ > > + height = ALIGN(height, 16); > > + > > + /* Luma plane size. */ > > + sizeimage = bytesperline * height; > > + > > + /* Chroma plane size. */ > > + sizeimage += bytesperline * height / 2; > > + > > + break; > > + } > > + > > + pix_fmt->width = width; > > + pix_fmt->height = height; > > + > > + pix_fmt->bytesperline = bytesperline; > > + pix_fmt->sizeimage = sizeimage; > > +} > > + > > +static int cedrus_querycap(struct file *file, void *priv, > > + struct v4l2_capability *cap) > > +{ > > + strlcpy(cap->driver, CEDRUS_NAME, sizeof(cap->driver)); > > + strlcpy(cap->card, CEDRUS_NAME, sizeof(cap->card)); > > + snprintf(cap->bus_info, sizeof(cap->bus_info), > > + "platform:%s", CEDRUS_NAME); > > + > > + return 0; > > +} > > + > > +static int cedrus_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, > > + u32 direction) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + struct cedrus_dev *dev = ctx->dev; > > + unsigned int capabilities = dev->capabilities; > > + struct cedrus_format *fmt; > > + unsigned int i, index; > > + > > + /* Index among formats that match the requested direction. */ > > + index = 0; > > + > > + for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) { > > + fmt = &cedrus_formats[i]; > > + > > + if (fmt->capabilities && (fmt->capabilities & capabilities) != > > + fmt->capabilities) > > + continue; > > + > > + if (!(cedrus_formats[i].directions & direction)) > > + continue; > > + > > + if (index == f->index) > > + break; > > + > > + index++; > > + } > > + > > + /* Matched format. */ > > + if (i < CEDRUS_FORMATS_COUNT) { > > + f->pixelformat = cedrus_formats[i].pixelformat; > > + > > + return 0; > > + } > > + > > + return -EINVAL; > > +} > > + > > +static int cedrus_enum_fmt_vid_cap(struct file *file, void *priv, > > + struct v4l2_fmtdesc *f) > > +{ > > + return cedrus_enum_fmt(file, f, CEDRUS_DECODE_DST); > > +} > > + > > +static int cedrus_enum_fmt_vid_out(struct file *file, void *priv, > > + struct v4l2_fmtdesc *f) > > +{ > > + return cedrus_enum_fmt(file, f, CEDRUS_DECODE_SRC); > > +} > > + > > +static int cedrus_g_fmt_vid_cap(struct file *file, void *priv, > > + struct v4l2_format *f) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + > > + /* Fall back to dummy default by lack of hardware configuration. */ > > + if (!ctx->dst_fmt.width || !ctx->dst_fmt.height) { > > + f->fmt.pix.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12; > > + cedrus_prepare_format(&f->fmt.pix); > > + > > + return 0; > > + } > > + > > + f->fmt.pix = ctx->dst_fmt; > > + > > + return 0; > > +} > > + > > +static int cedrus_g_fmt_vid_out(struct file *file, void *priv, > > + struct v4l2_format *f) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + > > + /* Fall back to dummy default by lack of hardware configuration. */ > > + if (!ctx->dst_fmt.width || !ctx->dst_fmt.height) { > > + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; > > + f->fmt.pix.sizeimage = SZ_1K; > > + cedrus_prepare_format(&f->fmt.pix); > > + > > + return 0; > > + } > > + > > + f->fmt.pix = ctx->src_fmt; > > + > > + return 0; > > +} > > + > > +static int cedrus_try_fmt_vid_cap(struct file *file, void *priv, > > + struct v4l2_format *f) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + struct cedrus_dev *dev = ctx->dev; > > + struct v4l2_pix_format *pix_fmt = &f->fmt.pix; > > + > > + if (!cedrus_check_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST, > > + dev->capabilities)) > > + return -EINVAL; > > + > > + cedrus_prepare_format(pix_fmt); > > + > > + return 0; > > +} > > + > > +static int cedrus_try_fmt_vid_out(struct file *file, void *priv, > > + struct v4l2_format *f) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + struct cedrus_dev *dev = ctx->dev; > > + struct v4l2_pix_format *pix_fmt = &f->fmt.pix; > > + > > + if (!cedrus_check_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC, > > + dev->capabilities)) > > + return -EINVAL; > > + > > + /* Source image size has to be provided by userspace. */ > > + if (pix_fmt->sizeimage == 0) > > + return -EINVAL; > > + > > + cedrus_prepare_format(pix_fmt); > > + > > + return 0; > > +} > > + > > +static int cedrus_s_fmt_vid_cap(struct file *file, void *priv, > > + struct v4l2_format *f) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + struct cedrus_dev *dev = ctx->dev; > > + int ret; > > + > > + ret = cedrus_try_fmt_vid_cap(file, priv, f); > > + if (ret) > > + return ret; > > + > > + ctx->dst_fmt = f->fmt.pix; > > + > > + cedrus_dst_format_set(dev, &ctx->dst_fmt); > > + > > + return 0; > > +} > > + > > +static int cedrus_s_fmt_vid_out(struct file *file, void *priv, > > + struct v4l2_format *f) > > +{ > > + struct cedrus_ctx *ctx = cedrus_file2ctx(file); > > + int ret; > > + > > + ret = cedrus_try_fmt_vid_out(file, priv, f); > > + if (ret) > > + return ret; > > + > > + ctx->src_fmt = f->fmt.pix; > > + > > + /* Propagate colorspace information to capture. */ > > + ctx->dst_fmt.colorspace = f->fmt.pix.colorspace; > > + ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func; > > + ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc; > > + ctx->dst_fmt.quantization = f->fmt.pix.quantization; > > + > > + return 0; > > +} > > + > > +const struct v4l2_ioctl_ops cedrus_ioctl_ops = { > > + .vidioc_querycap = cedrus_querycap, > > + > > + .vidioc_enum_fmt_vid_cap = cedrus_enum_fmt_vid_cap, > > + .vidioc_g_fmt_vid_cap = cedrus_g_fmt_vid_cap, > > + .vidioc_try_fmt_vid_cap = cedrus_try_fmt_vid_cap, > > + .vidioc_s_fmt_vid_cap = cedrus_s_fmt_vid_cap, > > + > > + .vidioc_enum_fmt_vid_out = cedrus_enum_fmt_vid_out, > > + .vidioc_g_fmt_vid_out = cedrus_g_fmt_vid_out, > > + .vidioc_try_fmt_vid_out = cedrus_try_fmt_vid_out, > > + .vidioc_s_fmt_vid_out = cedrus_s_fmt_vid_out, > > + > > + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, > > + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, > > + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, > > + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, > > + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, > > + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, > > + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, > > + > > + .vidioc_streamon = v4l2_m2m_ioctl_streamon, > > + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, > > + > > + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, > > + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, > > +}; > > + > > +static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, > > + unsigned int *nplanes, unsigned int sizes[], > > + struct device *alloc_devs[]) > > +{ > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + struct cedrus_dev *dev = ctx->dev; > > + struct v4l2_pix_format *pix_fmt; > > + u32 directions; > > + > > + if (V4L2_TYPE_IS_OUTPUT(vq->type)) { > > + directions = CEDRUS_DECODE_SRC; > > + pix_fmt = &ctx->src_fmt; > > + } else { > > + directions = CEDRUS_DECODE_DST; > > + pix_fmt = &ctx->dst_fmt; > > + } > > + > > + if (!cedrus_check_format(pix_fmt->pixelformat, directions, > > + dev->capabilities)) > > + return -EINVAL; > > + > > + if (*nplanes) { > > + if (sizes[0] < pix_fmt->sizeimage) > > + return -EINVAL; > > + } else { > > + sizes[0] = pix_fmt->sizeimage; > > + *nplanes = 1; > > + } > > + > > + return 0; > > +} > > + > > +static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state) > > +{ > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + struct vb2_v4l2_buffer *vbuf; > > + unsigned long flags; > > + > > + for (;;) { > > + spin_lock_irqsave(&ctx->dev->irq_lock, flags); > > + > > + if (V4L2_TYPE_IS_OUTPUT(vq->type)) > > + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); > > + else > > + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); > > + > > + spin_unlock_irqrestore(&ctx->dev->irq_lock, flags); > > + > > + if (!vbuf) > > + return; > > + > > + v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, > > + &ctx->hdl); > > + v4l2_m2m_buf_done(vbuf, state); > > + } > > +} > > + > > +static int cedrus_buf_init(struct vb2_buffer *vb) > > +{ > > + struct vb2_queue *vq = vb->vb2_queue; > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + > > + if (!V4L2_TYPE_IS_OUTPUT(vq->type)) > > + ctx->dst_bufs[vb->index] = vb; > > + > > + return 0; > > +} > > + > > +static void cedrus_buf_cleanup(struct vb2_buffer *vb) > > +{ > > + struct vb2_queue *vq = vb->vb2_queue; > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + > > + if (!V4L2_TYPE_IS_OUTPUT(vq->type)) > > + ctx->dst_bufs[vb->index] = NULL; > > +} > > + > > +static int cedrus_buf_prepare(struct vb2_buffer *vb) > > +{ > > + struct vb2_queue *vq = vb->vb2_queue; > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + struct v4l2_pix_format *pix_fmt; > > + > > + if (V4L2_TYPE_IS_OUTPUT(vq->type)) > > + pix_fmt = &ctx->src_fmt; > > + else > > + pix_fmt = &ctx->dst_fmt; > > + > > + if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) > > + return -EINVAL; > > + > > + vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); > > + > > + return 0; > > +} > > + > > +static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) > > +{ > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + struct cedrus_dev *dev = ctx->dev; > > + int ret = 0; > > + > > + switch (ctx->src_fmt.pixelformat) { > > + case V4L2_PIX_FMT_MPEG2_SLICE: > > + ctx->current_codec = CEDRUS_CODEC_MPEG2; > > + break; > > + > > + default: > > + return -EINVAL; > > + } > > + > > + if (V4L2_TYPE_IS_OUTPUT(vq->type) && > > + dev->dec_ops[ctx->current_codec]->start) > > + ret = dev->dec_ops[ctx->current_codec]->start(ctx); > > + > > + if (ret) > > + cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); > > + > > + return ret; > > +} > > + > > +static void cedrus_stop_streaming(struct vb2_queue *vq) > > +{ > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); > > + struct cedrus_dev *dev = ctx->dev; > > + > > + if (V4L2_TYPE_IS_OUTPUT(vq->type) && > > + dev->dec_ops[ctx->current_codec]->stop) > > + dev->dec_ops[ctx->current_codec]->stop(ctx); > > + > > + cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR); > > +} > > + > > +static void cedrus_buf_queue(struct vb2_buffer *vb) > > +{ > > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); > > + > > + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); > > +} > > + > > +static void cedrus_buf_request_complete(struct vb2_buffer *vb) > > +{ > > + struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); > > + > > + v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); > > +} > > +static struct vb2_ops cedrus_qops = { > > + .queue_setup = cedrus_queue_setup, > > + .buf_prepare = cedrus_buf_prepare, > > + .buf_init = cedrus_buf_init, > > + .buf_cleanup = cedrus_buf_cleanup, > > + .buf_queue = cedrus_buf_queue, > > + .buf_request_complete = cedrus_buf_request_complete, > > + .start_streaming = cedrus_start_streaming, > > + .stop_streaming = cedrus_stop_streaming, > > + .wait_prepare = vb2_ops_wait_prepare, > > + .wait_finish = vb2_ops_wait_finish, > > +}; > > + > > +int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, > > + struct vb2_queue *dst_vq) > > +{ > > + struct cedrus_ctx *ctx = priv; > > + int ret; > > + > > + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; > > + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; > > + src_vq->drv_priv = ctx; > > + src_vq->buf_struct_size = sizeof(struct cedrus_buffer); > > + src_vq->min_buffers_needed = 1; > > + src_vq->ops = &cedrus_qops; > > + src_vq->mem_ops = &vb2_dma_contig_memops; > > + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; > > + src_vq->lock = &ctx->dev->dev_mutex; > > + src_vq->dev = ctx->dev->dev; > > + src_vq->supports_requests = true; > > + > > + ret = vb2_queue_init(src_vq); > > + if (ret) > > + return ret; > > + > > + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > > + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; > > + dst_vq->drv_priv = ctx; > > + dst_vq->buf_struct_size = sizeof(struct cedrus_buffer); > > + dst_vq->min_buffers_needed = 1; > > + dst_vq->ops = &cedrus_qops; > > + dst_vq->mem_ops = &vb2_dma_contig_memops; > > + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; > > + dst_vq->lock = &ctx->dev->dev_mutex; > > + dst_vq->dev = ctx->dev->dev; > > + > > + return vb2_queue_init(dst_vq); > > +} > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.h b/drivers/staging/media/sunxi/cedrus/cedrus_video.h > > new file mode 100644 > > index 000000000000..0e4f7a8cccf2 > > --- /dev/null > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h > > @@ -0,0 +1,30 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Cedrus VPU driver > > + * > > + * Copyright (C) 2016 Florent Revest <florent.revest@xxxxxxxxxxxxxxxxxx> > > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx> > > + * Copyright (C) 2018 Bootlin > > + * > > + * Based on the vim2m driver, that is: > > + * > > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. > > + * Pawel Osciak, <pawel@xxxxxxxxxx> > > + * Marek Szyprowski, <m.szyprowski@xxxxxxxxxxx> > > + */ > > + > > +#ifndef _CEDRUS_VIDEO_H_ > > +#define _CEDRUS_VIDEO_H_ > > + > > +struct cedrus_format { > > + u32 pixelformat; > > + u32 directions; > > + unsigned int capabilities; > > +}; > > + > > +extern const struct v4l2_ioctl_ops cedrus_ioctl_ops; > > + > > +int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, > > + struct vb2_queue *dst_vq); > > + > > +#endif > > -- > > 2.18.0 > > > > -- > > You received this message because you are subscribed to the Google Groups "linux-sunxi" group. > > To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@xxxxxxxxxxxxxxxx. > > For more options, visit https://groups.google.com/d/optout. -- Developer of free digital technology and hardware support. Website: https://www.paulk.fr/ Coding blog: https://code.paulk.fr/ Git repositories: https://git.paulk.fr/ https://git.code.paulk.fr/
Attachment:
signature.asc
Description: This is a digitally signed message part