Re: [PATCH v2] media: cedrus: Add support for VP8 decoding

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 26 Jul 2020 at 16:16, Jernej Škrabec <jernej.skrabec@xxxxxxxx> wrote:
>
> Hi Ezequiel!
>
> Dne sobota, 25. julij 2020 ob 15:08:37 CEST je Ezequiel Garcia napisal(a):
> > Hi Jernej,
> >
> > As you know, I'm not familiar with this hardware,
> > but I've tried to take a detailed look anyway.
> >
>
> Thanks, any review is welcome.
>
> > The driver looks mostly good to me, I just have
> > some minor comments.
> >
> > More importantly, seems the current uAPI
> > control is supporting this platform nicely,
> > which gives us some confidence to mark it
> > as stable.
>
> Yes, it looks pretty good in that regard.
>
> >
> > Comments below.
> >
> > On Wed, 22 Jul 2020 at 17:35, Jernej Skrabec <jernej.skrabec@xxxxxxxx>
> wrote:
> > > VP8 in Cedrus shares same engine as H264.
> > >
> > > Note that it seems necessary to call bitstream parsing functions,
> > > to parse frame header, otherwise decoded image is garbage. This is
> > > contrary to what is driver supposed to do. However, values are not
> > > really used, so this might be acceptable. It's possible that bitstream
> > > parsing functions set some internal VPU state, which is later necessary
> > > for proper decoding. Biggest suspect is "VP8 probs update" trigger.
> >
> > I suggest that you also put this explanation here, as a comment
> > in the cedrus_vp8.c
>
> Ok.
>
> >
> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@xxxxxxxx>
> > > ---
> > > Changes in v2:
> > > - rebased on top of current linux-media master branch
> > >
> > >  drivers/staging/media/sunxi/cedrus/Makefile   |   3 +-
> > >  drivers/staging/media/sunxi/cedrus/cedrus.c   |   8 +
> > >  drivers/staging/media/sunxi/cedrus/cedrus.h   |  15 +
> > >  .../staging/media/sunxi/cedrus/cedrus_dec.c   |   5 +
> > >  .../staging/media/sunxi/cedrus/cedrus_hw.c    |   1 +
> > >  .../staging/media/sunxi/cedrus/cedrus_regs.h  |  80 ++
> > >  .../staging/media/sunxi/cedrus/cedrus_video.c |   9 +
> > >  .../staging/media/sunxi/cedrus/cedrus_vp8.c   | 699 ++++++++++++++++++
> > >  8 files changed, 819 insertions(+), 1 deletion(-)
> > >  create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_vp8.c
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/Makefile
> > > b/drivers/staging/media/sunxi/cedrus/Makefile index
> > > 1bce49d3e7e2..a647b3690bf8 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/Makefile
> > > +++ b/drivers/staging/media/sunxi/cedrus/Makefile
> > > @@ -2,4 +2,5 @@
> > >
> > >  obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
> > >
> > >  sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
> > >
> > > -                cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o
> > > +                cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \
> > > +                cedrus_vp8.o
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c
> > > b/drivers/staging/media/sunxi/cedrus/cedrus.c index
> > > bc27f9430eeb..b2f5f03ad4a3 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/cedrus.c
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
> > > @@ -135,6 +135,13 @@ static const struct cedrus_control cedrus_controls[]
> > > = {>
> > >                 .codec          = CEDRUS_CODEC_H265,
> > >                 .required       = false,
> > >
> > >         },
> > >
> > > +       {
> > > +               .cfg = {
> > > +                       .id             =
> > > V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, +               },
> > > +               .codec          = CEDRUS_CODEC_VP8,
> > > +               .required       = true,
> > > +       },
> > >
> > >  };
> > >
> > >  #define CEDRUS_CONTROLS_COUNT  ARRAY_SIZE(cedrus_controls)
> > >
> > > @@ -381,6 +388,7 @@ static int cedrus_probe(struct platform_device *pdev)
> > >
> > >         dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2;
> > >         dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264;
> > >         dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265;
> > >
> > > +       dev->dec_ops[CEDRUS_CODEC_VP8] = &cedrus_dec_ops_vp8;
> > >
> > >         mutex_init(&dev->dev_mutex);
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h
> > > b/drivers/staging/media/sunxi/cedrus/cedrus.h index
> > > 96765555ab8a..9f4605afa0f4 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/cedrus.h
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
> > > @@ -35,6 +35,7 @@ enum cedrus_codec {
> > >
> > >         CEDRUS_CODEC_MPEG2,
> > >         CEDRUS_CODEC_H264,
> > >         CEDRUS_CODEC_H265,
> > >
> > > +       CEDRUS_CODEC_VP8,
> > >
> > >         CEDRUS_CODEC_LAST,
> > >
> > >  };
> > >
> > > @@ -75,6 +76,10 @@ struct cedrus_h265_run {
> > >
> > >         const struct v4l2_ctrl_hevc_slice_params        *slice_params;
> > >
> > >  };
> > >
> > > +struct cedrus_vp8_run {
> > > +       const struct v4l2_ctrl_vp8_frame_header         *slice_params;
> >
> > I don't think VP8 has any concept of slice, as H264 does.
> > I think it's misleading to call this parameter as slice_params.
> >
>
> frame_info perhaps? Or frame_params?
>

Either works for me.

> > > +};
> > > +
> > >
> > >  struct cedrus_run {
> > >
> > >         struct vb2_v4l2_buffer  *src;
> > >         struct vb2_v4l2_buffer  *dst;
> > >
> > > @@ -83,6 +88,7 @@ struct cedrus_run {
> > >
> > >                 struct cedrus_h264_run  h264;
> > >                 struct cedrus_mpeg2_run mpeg2;
> > >                 struct cedrus_h265_run  h265;
> > >
> > > +               struct cedrus_vp8_run   vp8;
> > >
> > >         };
> > >
> > >  };
> > >
> > > @@ -134,6 +140,14 @@ struct cedrus_ctx {
> > >
> > >                         void            *neighbor_info_buf;
> > >                         dma_addr_t      neighbor_info_buf_addr;
> > >
> > >                 } h265;
> > >
> > > +               struct {
> > > +                       unsigned int    last_frame_p_type;
> > > +                       unsigned int    last_filter_type;
> > > +                       unsigned int    last_sharpness_level;
> > > +
> > > +                       u8              *entropy_probs_buf;
> > > +                       dma_addr_t      entropy_probs_buf_dma;
> > > +               } vp8;
> > >
> > >         } codec;
> > >
> > >  };
> > >
> > > @@ -180,6 +194,7 @@ struct cedrus_dev {
> > >
> > >  extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
> > >  extern struct cedrus_dec_ops cedrus_dec_ops_h264;
> > >  extern struct cedrus_dec_ops cedrus_dec_ops_h265;
> > >
> > > +extern struct cedrus_dec_ops cedrus_dec_ops_vp8;
> > >
> > >  static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
> > >  {
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
> > > b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c index
> > > 58c48e4fdfe9..47c079f14c74 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
> > > @@ -68,6 +68,11 @@ void cedrus_device_run(void *priv)
> > >
> > >                         V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
> > >
> > >                 break;
> > >
> > > +       case V4L2_PIX_FMT_VP8_FRAME:
> > > +               run.vp8.slice_params = cedrus_find_control_data(ctx,
> > > +                       V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER);
> > > +               break;
> > > +
> > >
> > >         default:
> > >                 break;
> > >
> > >         }
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> > > b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index
> > > 1744e6fcc999..cb8cabfc7cee 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> > > @@ -48,6 +48,7 @@ int cedrus_engine_enable(struct cedrus_ctx *ctx, enum
> > > cedrus_codec codec)>
> > >                 break;
> > >
> > >         case CEDRUS_CODEC_H264:
> > > +       case CEDRUS_CODEC_VP8:
> > I would add a comment here mentioning
> > both codecs use the same decoding mode bit.
>
> Ok.
>
> >
> > >                 reg |= VE_MODE_DEC_H264;
> > >                 break;
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
> > > b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h index
> > > 66b152f18d17..7718c561823f 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
> > > @@ -546,6 +546,7 @@
> > >
> > >  #define VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT  BIT(24)
> > >
> > >  #define VE_H264_CTRL                   0x220
> > >
> > > +#define VE_H264_CTRL_VP8                       BIT(29)
> > >
> > >  #define VE_H264_CTRL_VLD_DATA_REQ_INT          BIT(2)
> > >  #define VE_H264_CTRL_DECODE_ERR_INT            BIT(1)
> > >  #define VE_H264_CTRL_SLICE_DECODE_INT          BIT(0)
> > >
> > > @@ -555,7 +556,12 @@
> > >
> > >                                          VE_H264_CTRL_SLICE_DECODE_INT)
> > >
> > >  #define VE_H264_TRIGGER_TYPE           0x224
> > >
> > > +#define VE_H264_TRIGGER_TYPE_PROBABILITY(x)    SHIFT_AND_MASK_BITS(x, 31,
> > > 24) +#define VE_H264_TRIGGER_TYPE_BIN_LENS(x)
> > > SHIFT_AND_MASK_BITS((x) - 1, 18, 16)>
> > >  #define VE_H264_TRIGGER_TYPE_N_BITS(x)         (((x) & 0x3f) << 8)
> > >
> > > +#define VE_H264_TRIGGER_TYPE_VP8_GET_BITS      (15 << 0)
> > > +#define VE_H264_TRIGGER_TYPE_VP8_UPDATE_COEF   (14 << 0)
> > > +#define VE_H264_TRIGGER_TYPE_VP8_SLICE_DECODE  (10 << 0)
> > >
> > >  #define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE  (8 << 0)
> > >  #define VE_H264_TRIGGER_TYPE_INIT_SWDEC                (7 << 0)
> > >  #define VE_H264_TRIGGER_TYPE_FLUSH_BITS                (3 << 0)
> > >
> > > @@ -565,6 +571,7 @@
> > >
> > >  #define VE_H264_STATUS_DECODE_ERR_INT
> > >  VE_H264_CTRL_DECODE_ERR_INT
> > >  #define VE_H264_STATUS_SLICE_DECODE_INT
> > >  VE_H264_CTRL_SLICE_DECODE_INT #define VE_H264_STATUS_VLD_BUSY
> > >              BIT(8)
> > >
> > > +#define VE_H264_STATUS_VP8_UPPROB_BUSY         BIT(17)
> > >
> > >  #define VE_H264_STATUS_INT_MASK
> > >  VE_H264_CTRL_INT_MASK
> > Why not just using VE_H264_CTRL_INT_MASK?
> >
> > Having an alias looks confusing.
>
> This is not my change so I suggest to address it later.
>
> >
> > > @@ -583,10 +590,83 @@
> > >
> > >  #define VE_H264_OUTPUT_FRAME_IDX       0x24c
> > >  #define VE_H264_EXTRA_BUFFER1          0x250
> > >  #define VE_H264_EXTRA_BUFFER2          0x254
> > >
> > > +#define VE_H264_MB_ADDR                        0x260
> > > +#define VE_H264_ERROR_CASE             0x2b8
> > >
> > >  #define VE_H264_BASIC_BITS             0x2dc
> > >  #define VE_AVC_SRAM_PORT_OFFSET                0x2e0
> > >  #define VE_AVC_SRAM_PORT_DATA          0x2e4
> > >
> > > +#define VE_VP8_PPS                     0x214
> > > +#define VE_VP8_PPS_PIC_TYPE_P_FRAME            BIT(31)
> > > +#define VE_VP8_PPS_LAST_SHARPNESS_LEVEL(v)     SHIFT_AND_MASK_BITS(v, 30,
> > > 28) +#define VE_VP8_PPS_LAST_PIC_TYPE_P_FRAME       BIT(27)
> > > +#define VE_VP8_PPS_ALTREF_SIGN_BIAS            BIT(26)
> > > +#define VE_VP8_PPS_GOLDEN_SIGN_BIAS            BIT(25)
> > > +#define VE_VP8_PPS_RELOAD_ENTROPY_PROBS                BIT(24)
> > > +#define VE_VP8_PPS_REFRESH_ENTROPY_PROBS       BIT(23)
> > > +#define VE_VP8_PPS_MB_NO_COEFF_SKIP            BIT(22)
> > > +#define VE_VP8_PPS_TOKEN_PARTITION(v)          SHIFT_AND_MASK_BITS(v, 21,
> > > 20) +#define VE_VP8_PPS_MODE_REF_LF_DELTA_UPDATE    BIT(19)
> > > +#define VE_VP8_PPS_MODE_REF_LF_DELTA_ENABLE    BIT(18)
> > > +#define VE_VP8_PPS_LOOP_FILTER_LEVEL(v)
> > > SHIFT_AND_MASK_BITS(v, 17, 12) +#define VE_VP8_PPS_LOOP_FILTER_SIMPLE
> > >      BIT(11)
> > > +#define VE_VP8_PPS_SHARPNESS_LEVEL(v)          SHIFT_AND_MASK_BITS(v, 10,
> > > 8) +#define VE_VP8_PPS_LAST_LOOP_FILTER_SIMPLE     BIT(7)
> > > +#define VE_VP8_PPS_SEGMENTATION_ENABLE         BIT(6)
> > > +#define VE_VP8_PPS_MB_SEGMENT_ABS_DELTA                BIT(5)
> > > +#define VE_VP8_PPS_UPDATE_MB_SEGMENTATION_MAP  BIT(4)
> > > +#define VE_VP8_PPS_FULL_PIXEL                  BIT(3)
> > > +#define VE_VP8_PPS_BILINEAR_MC_FILTER          BIT(2)
> > > +#define VE_VP8_PPS_FILTER_TYPE_SIMPLE          BIT(1)
> > > +#define VE_VP8_PPS_LPF_DISABLE                 BIT(0)
> > > +
> > > +#define VE_VP8_QP_INDEX_DELTA          0x218
> > > +#define VE_VP8_QP_INDEX_DELTA_UVAC(v)          SHIFT_AND_MASK_BITS(v, 31,
> > > 27) +#define VE_VP8_QP_INDEX_DELTA_UVDC(v)
> > > SHIFT_AND_MASK_BITS(v, 26, 22) +#define VE_VP8_QP_INDEX_DELTA_Y2AC(v)
> > >      SHIFT_AND_MASK_BITS(v, 21, 17) +#define
> > > VE_VP8_QP_INDEX_DELTA_Y2DC(v)          SHIFT_AND_MASK_BITS(v, 16, 12)
> > > +#define VE_VP8_QP_INDEX_DELTA_Y1DC(v)          SHIFT_AND_MASK_BITS(v,
> > > 11, 7) +#define VE_VP8_QP_INDEX_DELTA_BASE_QINDEX(v)
> > > SHIFT_AND_MASK_BITS(v, 6, 0) +
> > > +#define VE_VP8_PART_SIZE_OFFSET                0x21c
> > > +#define VE_VP8_ENTROPY_PROBS_ADDR      0x250
> > > +#define VE_VP8_FIRST_DATA_PART_LEN     0x254
> > > +
> > > +#define VE_VP8_FSIZE                   0x258
> > > +#define VE_VP8_FSIZE_WIDTH(w) \
> > > +       SHIFT_AND_MASK_BITS(DIV_ROUND_UP(w, 16), 15, 8)
> > > +#define VE_VP8_FSIZE_HEIGHT(h) \
> > > +       SHIFT_AND_MASK_BITS(DIV_ROUND_UP(h, 16), 7, 0)
> > > +
> > > +#define VE_VP8_PICSIZE                 0x25c
> > > +#define VE_VP8_PICSIZE_WIDTH(w)
> > > SHIFT_AND_MASK_BITS(w, 27, 16) +#define VE_VP8_PICSIZE_HEIGHT(h)
> > >      SHIFT_AND_MASK_BITS(h, 11, 0) +
> > > +#define VE_VP8_REC_LUMA                        0x2ac
> > > +#define VE_VP8_FWD_LUMA                        0x2b0
> > > +#define VE_VP8_BWD_LUMA                        0x2b4
> > > +#define VE_VP8_REC_CHROMA              0x2d0
> > > +#define VE_VP8_FWD_CHROMA              0x2d4
> > > +#define VE_VP8_BWD_CHROMA              0x2d8
> > > +#define VE_VP8_ALT_LUMA                        0x2e8
> > > +#define VE_VP8_ALT_CHROMA              0x2ec
> > > +
> > > +#define VE_VP8_SEGMENT_FEAT_MB_LV0     0x2f0
> > > +#define VE_VP8_SEGMENT_FEAT_MB_LV1     0x2f4
> > > +
> > > +#define VE_VP8_SEGMENT3(v)                     SHIFT_AND_MASK_BITS(v, 31,
> > > 24) +#define VE_VP8_SEGMENT2(v)
> > > SHIFT_AND_MASK_BITS(v, 23, 16) +#define VE_VP8_SEGMENT1(v)
> > >      SHIFT_AND_MASK_BITS(v, 15, 8) +#define VE_VP8_SEGMENT0(v)
> > >          SHIFT_AND_MASK_BITS(v, 7, 0) +
> > > +#define VE_VP8_REF_LF_DELTA            0x2f8
> > > +#define VE_VP8_MODE_LF_DELTA           0x2fc
> > > +
> > > +#define VE_VP8_LF_DELTA3(v)                    SHIFT_AND_MASK_BITS(v, 30,
> > > 24) +#define VE_VP8_LF_DELTA2(v)
> > > SHIFT_AND_MASK_BITS(v, 22, 16) +#define VE_VP8_LF_DELTA1(v)
> > >      SHIFT_AND_MASK_BITS(v, 14, 8) +#define VE_VP8_LF_DELTA0(v)
> > >          SHIFT_AND_MASK_BITS(v, 6, 0) +
> > >
> > >  #define VE_ISP_INPUT_SIZE              0xa00
> > >  #define VE_ISP_INPUT_STRIDE            0xa04
> > >  #define VE_ISP_CTRL                    0xa08
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
> > > b/drivers/staging/media/sunxi/cedrus/cedrus_video.c index
> > > 16d82309e7b6..0212054484dd 100644
> > > --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
> > > @@ -48,6 +48,10 @@ static struct cedrus_format cedrus_formats[] = {
> > >
> > >                 .directions     = CEDRUS_DECODE_SRC,
> > >                 .capabilities   = CEDRUS_CAPABILITY_H265_DEC,
> > >
> > >         },
> > >
> > > +       {
> > > +               .pixelformat    = V4L2_PIX_FMT_VP8_FRAME,
> > > +               .directions     = CEDRUS_DECODE_SRC,
> > > +       },
> > >
> > >         {
> > >
> > >                 .pixelformat    = V4L2_PIX_FMT_SUNXI_TILED_NV12,
> > >                 .directions     = CEDRUS_DECODE_DST,
> > >
> > > @@ -110,6 +114,7 @@ void cedrus_prepare_format(struct v4l2_pix_format
> > > *pix_fmt)>
> > >         case V4L2_PIX_FMT_MPEG2_SLICE:
> > >         case V4L2_PIX_FMT_H264_SLICE:
> > >
> > >         case V4L2_PIX_FMT_HEVC_SLICE:
> > > +       case V4L2_PIX_FMT_VP8_FRAME:
> > >                 /* Zero bytes per line for encoded source. */
> > >                 bytesperline = 0;
> > >                 /* Choose some minimum size since this can't be 0 */
> > >
> > > @@ -448,6 +453,10 @@ static int cedrus_start_streaming(struct vb2_queue
> > > *vq, unsigned int count)>
> > >                 ctx->current_codec = CEDRUS_CODEC_H265;
> > >                 break;
> > >
> > > +       case V4L2_PIX_FMT_VP8_FRAME:
> > > +               ctx->current_codec = CEDRUS_CODEC_VP8;
> > > +               break;
> > > +
> > >
> > >         default:
> > >                 return -EINVAL;
> > >
> > >         }
> > >
> > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c
> > > b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c new file mode 100644
> > > index 000000000000..93beffd07c35
> > > --- /dev/null
> > > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c
> > > @@ -0,0 +1,699 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * Cedrus VPU driver
> > > + *
> > > + * Copyright (c) 2019 Jernej Skrabec <jernej.skrabec@xxxxxxxx>
> > > + */
> > > +
> > > +#include <linux/delay.h>
> > > +#include <linux/types.h>
> > > +
> > > +#include <media/videobuf2-dma-contig.h>
> > > +
> > > +#include "cedrus.h"
> > > +#include "cedrus_hw.h"
> > > +#include "cedrus_regs.h"
> > > +
> > > +#define CEDRUS_ENTROPY_PROBS_SIZE 0x2400
> > > +#define VP8_PROB_HALF 128
> > > +
> > > +static const u8 prob_table_init[] = {
> >
> > What's this prob_table_init and where
> > are the values coming from?
> >
> > Doesn't seem like coming from the spec.
>
> Well, that's good question. Actually, this structure consists from several
> arrays defined in VP8. See https://bitbucket.org/paullo612/cedarx-vp8-test/src/
> default/src/vp8.c function fill_probs_table(). It's my understanding that this
> was reverse engineered from CedarX binary library. Instead of building array
> every time codec is started, I just precomputed it. I agree that it needs some
> explanation.
>

I wonder if we can at least point out that it comes from a reverse
engineering effort.


> >
> > > +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
> > > 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xB0, 0xF6,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xDF, 0xF1, 0xFC, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xF9, 0xFD, 0xFD,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF4, 0xFC, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xEA, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xF6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xEF, 0xFD,
> > > 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xFE, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
> > > 0xFD, 0xFE, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFB, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF,
> > > 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFE, 0xFD,
> > > 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFA, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
> > > 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xD9, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xE1, 0xFC, 0xF1,
> > > 0xFD, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xEA, 0xFA, 0xF1, 0xFA, 0xFD, 0xFF, 0xFD, 0xFE, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xDF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE,
> > > 0xFD, 0xFE, 0xFE, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8,
> > > 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xF9, 0xFE, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xF7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
> > > 0xFE, 0xFD, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xBA, 0xFB, 0xFA, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA,
> > > 0xFB, 0xF4, 0xFE, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFB, 0xFB, 0xF3, 0xFD, 0xFE, 0xFF, 0xFE,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFE, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xEC, 0xFD, 0xFE,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
> > > 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xFE, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
> > > 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xF8, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFA, 0xFE, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xF9, 0xFD, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6,
> > > 0xFD, 0xFD, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFC, 0xFE, 0xFB, 0xFE, 0xFE, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFC, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xF8, 0xFE, 0xFD,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFD, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xF5, 0xFB, 0xFE, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD,
> > > 0xFD, 0xFE, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFB,
> > > 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFC, 0xFD, 0xFE, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFE, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xF9, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +       0x00, 0x00, 0x00, 0x00, 0xFA, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF, 0xFF, 0xFF, 0xFF,
> > > 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +       0xFF,
> > > 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, +
> > > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91,
> > > 0x9C, 0xA3, 0x80, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x96, 0x00, +
> > > 0x00, 0x00, 0x00, 0x00, 0x78, 0x5A, 0x4F, 0x85, 0x57, 0x55, 0x50, 0x6F, +
> > >       0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, +       0x93, 0x88, 0x12, 0x00, 0x6A, 0x91, 0x01, 0x00, 0xB3,
> > > 0x79, 0x01, 0x00, +       0xDF, 0x01, 0x22, 0x00, 0xD0, 0x01, 0x01, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x07, 0x01, 0x01, 0x8F, +       0x0E, 0x12, 0x0E, 0x6B, 0x87, 0x40,
> > > 0x39, 0x44, 0x3C, 0x38, 0x80, 0x41, +       0x9F, 0x86, 0x80, 0x22, 0xEA,
> > > 0xBC, 0x80, 0x1C, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > >       0x84, 0x02, 0x04, 0x06, 0x80, 0x81, 0x82, 0x83, 0x80, 0x02, 0x04,
> > > 0x06, +       0x81, 0x82, 0x83, 0x84, 0x80, 0x02, 0x81, 0x04, 0x82, 0x83,
> > > 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x02, 0x08, +       0x04, 0x06, 0x80, 0x81, 0x82, 0x83, 0x0A, 0x0C,
> > > 0x84, 0x85, 0x86, 0x87, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x02, 0x08, 0x04, 0x06, 0x80, 0x81, +       0x82, 0x83, 0x0A, 0x0C, 0x84,
> > > 0x85, 0x86, 0x87, 0x00, 0x00, 0x00, 0x00, +       0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +       0x83, 0x02, 0x82,
> > > 0x04, 0x80, 0x81, 0x00, 0x00, 0x80, 0x02, 0x81, 0x04, +       0x82, 0x06,
> > > 0x08, 0x0C, 0x83, 0x0A, 0x85, 0x86, 0x84, 0x0E, 0x87, 0x10, +       0x88,
> > > 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +
> > > 0x00, 0x00, 0x00, 0x00, 0x8A, 0x02, 0x8B, 0x04, 0x8C, 0x8D, 0x00, 0x00, +
> > >       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > 0x00, 0x00, +       0x87, 0x02, 0x85, 0x04, 0x86, 0x06, 0x88, 0x89,
> > > +};
> > > +
> > > +static const u8 vp8_mv_update_prob[2][19] = {
> >
> > Seems like the V4L2 VP8 uapi header should
> > #define MV_PROB_CNT 19 so you could use it through
> > the driver.
>
> Ok.
>
> >
> > Also, these look like k_mv_entropy_update_probs,
> > could you add a comment here about this?
>
> Well, this table can even go in common header... I'm not sure how many future
> codecs would need it. For now, it can stay here but maybe renaming it to
> vp8_k_mv_entropy_update_probs would be enough (instead of comment)?
>

How about both? Comments are free :-)

> >
> > > +       { 237, 246, 253, 253, 254, 254, 254, 254, 254,
> > > +         254, 254, 254, 254, 254, 250, 250, 252, 254, 254 },
> > > +       { 231, 243, 245, 253, 254, 254, 254, 254, 254,
> > > +         254, 254, 254, 254, 254, 251, 251, 254, 254, 254 }
> > > +};
> > > +
> > > +static uint8_t read_bits(struct cedrus_dev *dev, unsigned int bits_count,
> > > +                        unsigned int probability)
> > > +{
> > > +       cedrus_write(dev, VE_H264_TRIGGER_TYPE,
> > > +                    VE_H264_TRIGGER_TYPE_VP8_GET_BITS |
> > > +                    VE_H264_TRIGGER_TYPE_BIN_LENS(bits_count) |
> > > +                    VE_H264_TRIGGER_TYPE_PROBABILITY(probability));
> > > +
> > > +       while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VLD_BUSY)
> > > +               ;
> > > +
> >
> > You can abstract this as cedrus_wait_for(flag),
> > which should be based on readl_poll_timeout_atomic.
> >
> > The flag argument would be VE_H264_STATUS_VP8_UPPROB_BUSY
> > or VE_H264_STATUS_VLD_BUSY. This way it'll be cleaner
> > and you don't risk deadlocks if the hardware goes nuts.
>
> Good idea.
>
> >
> > > +       return cedrus_read(dev, VE_H264_BASIC_BITS);
> > > +}
> > > +
> > > +static void get_delta_q(struct cedrus_dev *dev)
> > > +{
> > > +       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +               read_bits(dev, 4, VP8_PROB_HALF);
> > > +               read_bits(dev, 1, VP8_PROB_HALF);
> > > +       }
> > > +}
> > > +
> > > +static void process_segmentation_info(struct cedrus_dev *dev)
> > > +{
> > > +       int update = read_bits(dev, 1, VP8_PROB_HALF);
> > > +       int i;
> > > +
> > > +       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +               read_bits(dev, 1, VP8_PROB_HALF);
> > > +
> > > +               for (i = 0; i < 4; i++)
> > > +                       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +                               read_bits(dev, 7, VP8_PROB_HALF);
> > > +                               read_bits(dev, 1, VP8_PROB_HALF);
> > > +                       }
> > > +
> > > +               for (i = 0; i < 4; i++)
> > > +                       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +                               read_bits(dev, 6, VP8_PROB_HALF);
> > > +                               read_bits(dev, 1, VP8_PROB_HALF);
> > > +                       }
> > > +       }
> > > +
> > > +       if (update)
> > > +               for (i = 0; i < 3; i++)
> > > +                       if (read_bits(dev, 1, VP8_PROB_HALF))
> > > +                               read_bits(dev, 8, VP8_PROB_HALF);
> > > +}
> > > +
> > > +static void process_ref_lf_delta_info(struct cedrus_dev *dev)
> > > +{
> > > +       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +               int i;
> > > +
> > > +               for (i = 0; i < 4; i++)
> > > +                       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +                               read_bits(dev, 6, VP8_PROB_HALF);
> > > +                               read_bits(dev, 1, VP8_PROB_HALF);
> > > +                       }
> > > +
> > > +               for (i = 0; i < 4; i++)
> > > +                       if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +                               read_bits(dev, 6, VP8_PROB_HALF);
> > > +                               read_bits(dev, 1, VP8_PROB_HALF);
> > > +                       }
> > > +       }
> > > +}
> > > +
> > > +static void process_ref_frame_info(struct cedrus_dev *dev)
> > > +{
> > > +       u8 refresh_golden_frame = read_bits(dev, 1, VP8_PROB_HALF);
> > > +       u8 refresh_alt_ref_frame = read_bits(dev, 1, VP8_PROB_HALF);
> > > +
> > > +       if (!refresh_golden_frame)
> > > +               read_bits(dev, 2, VP8_PROB_HALF);
> > > +
> > > +       if (!refresh_alt_ref_frame)
> > > +               read_bits(dev, 2, VP8_PROB_HALF);
> > > +
> > > +       read_bits(dev, 1, VP8_PROB_HALF);
> > > +       read_bits(dev, 1, VP8_PROB_HALF);
> > > +}
> > > +
> > > +static void cedrus_read_header(struct cedrus_dev *dev,
> > > +                              const struct v4l2_ctrl_vp8_frame_header
> > > *slice) +{
> > > +       int i, j;
> > > +
> > > +       if (VP8_FRAME_IS_KEY_FRAME(slice)) {
> > > +               read_bits(dev, 1, VP8_PROB_HALF);
> > > +               read_bits(dev, 1, VP8_PROB_HALF);
> > > +       }
> > > +
> > > +       if (read_bits(dev, 1, VP8_PROB_HALF))
> > > +               process_segmentation_info(dev);
> > > +
> > > +       read_bits(dev, 1, VP8_PROB_HALF);
> > > +       read_bits(dev, 6, VP8_PROB_HALF);
> > > +       read_bits(dev, 3, VP8_PROB_HALF);
> > > +
> > > +       if (read_bits(dev, 1, VP8_PROB_HALF))
> > > +               process_ref_lf_delta_info(dev);
> > > +
> > > +       read_bits(dev, 2, VP8_PROB_HALF);

Answering below's question,
I would add a comment here:

/* y_ac_qi */

> > > +       read_bits(dev, 7, VP8_PROB_HALF);
> > > +
> > > +       get_delta_q(dev);
> > > +       get_delta_q(dev);
> > > +       get_delta_q(dev);
> > > +       get_delta_q(dev);
> > > +       get_delta_q(dev);
> > > +
> >
> > for loop?
>
> Ok but would be 5 some macro? If so, what should be it's name?
>

Well, perhaps QUANT_DELTA_COUNT ?

And maybe a small comment (together with the
one above) to clarify this is just parsing
y_dc_delta, y2_dc_delta, ... and so on.

> >
> > > +       if (!VP8_FRAME_IS_KEY_FRAME(slice))
> > > +               process_ref_frame_info(dev);
> > > +
> > > +       read_bits(dev, 1, VP8_PROB_HALF);
> > > +
> > > +       if (!VP8_FRAME_IS_KEY_FRAME(slice))
> > > +               read_bits(dev, 1, VP8_PROB_HALF);
> > > +
> > > +       cedrus_write(dev, VE_H264_TRIGGER_TYPE,
> > > VE_H264_TRIGGER_TYPE_VP8_UPDATE_COEF); +       while (cedrus_read(dev,
> > > VE_H264_STATUS) & VE_H264_STATUS_VP8_UPPROB_BUSY) +               ;
> > > +
> > > +       cedrus_write(dev, VE_H264_STATUS, VE_H264_CTRL_INT_MASK);
> > > +
> >
> > This one looks like cedrus_vp8_irq_clear function, maybe just
> > call that instead.
>
> Ok.
>
> >
> > > +       if (read_bits(dev, 1, VP8_PROB_HALF))
> > > +               read_bits(dev, 8, VP8_PROB_HALF);
> > > +
> > > +       if (!VP8_FRAME_IS_KEY_FRAME(slice)) {
> > > +               read_bits(dev, 8, VP8_PROB_HALF);
> > > +               read_bits(dev, 8, VP8_PROB_HALF);
> > > +               read_bits(dev, 8, VP8_PROB_HALF);
> > > +
> > > +               if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +               }
> > > +
> > > +               if (read_bits(dev, 1, VP8_PROB_HALF)) {
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +                       read_bits(dev, 8, VP8_PROB_HALF);
> > > +               }
> > > +
> > > +               for (i = 0; i < 2; i++)
> > > +                       for (j = 0; j < 19; j++)
> > > +                               if (read_bits(dev, 1,
> > > vp8_mv_update_prob[i][j])) +
> > > read_bits(dev, 7, VP8_PROB_HALF); +       }
> > > +}
> > > +
> > > +static void cedrus_vp8_update_probs(const struct
> > > v4l2_ctrl_vp8_frame_header *slice, +                                   u8
> > > *prob_table)
> > > +{
> > > +       int i, j, k;
> > > +
> > > +       memcpy(&prob_table[0x1008], slice->entropy_header.y_mode_probs,
> > > 4);
> > > +       memcpy(&prob_table[0x1010], slice->entropy_header.uv_mode_probs,
> > > 3); +
> >
> > Use sizeof instead of hardcoding the size?
>
> Ok.
>
> >
> > > +       memcpy(&prob_table[0x1018], slice->segment_header.segment_probs,
> > > 3); +
> > > +       prob_table[0x101c] = slice->prob_skip_false;
> > > +       prob_table[0x101d] = slice->prob_intra;
> > > +       prob_table[0x101e] = slice->prob_last;
> > > +       prob_table[0x101f] = slice->prob_gf;
> > > +
> > > +       memcpy(&prob_table[0x1020], slice->entropy_header.mv_probs[0],
> > > 19);
> > > +       memcpy(&prob_table[0x1040], slice->entropy_header.mv_probs[1],
> > > 19);
> > > +
> > > +       for (i = 0; i < 4; ++i)
> > > +               for (j = 0; j < 8; ++j)
> > > +                       for (k = 0; k < 3; ++k)
> > > +                               memcpy(&prob_table[i * 512 + j * 64 + k *
> > > 16], +
> > > slice->entropy_header.coeff_probs[i][j][k], 11); +}
> > > +
> > > +static enum cedrus_irq_status
> > > +cedrus_vp8_irq_status(struct cedrus_ctx *ctx)
> > > +{
> > > +       struct cedrus_dev *dev = ctx->dev;
> > > +       u32 reg = cedrus_read(dev, VE_H264_STATUS);
> > > +
> > > +       if (reg & (VE_H264_STATUS_DECODE_ERR_INT |
> > > +                  VE_H264_STATUS_VLD_DATA_REQ_INT))
> > > +               return CEDRUS_IRQ_ERROR;
> > > +
> > > +       if (reg & VE_H264_CTRL_SLICE_DECODE_INT)
> > > +               return CEDRUS_IRQ_OK;
> > > +
> > > +       return CEDRUS_IRQ_NONE;
> > > +}
> > > +
> > > +static void cedrus_vp8_irq_clear(struct cedrus_ctx *ctx)
> > > +{
> > > +       struct cedrus_dev *dev = ctx->dev;
> > > +
> > > +       cedrus_write(dev, VE_H264_STATUS,
> > > +                    VE_H264_STATUS_INT_MASK);
> > > +}
> > > +
> > > +static void cedrus_vp8_irq_disable(struct cedrus_ctx *ctx)
> > > +{
> > > +       struct cedrus_dev *dev = ctx->dev;
> > > +       u32 reg = cedrus_read(dev, VE_H264_CTRL);
> > > +
> > > +       cedrus_write(dev, VE_H264_CTRL,
> > > +                    reg & ~VE_H264_CTRL_INT_MASK);
> > > +}
> > > +
> > > +static void cedrus_vp8_setup(struct cedrus_ctx *ctx,
> > > +                            struct cedrus_run *run)
> > > +{
> > > +       const struct v4l2_ctrl_vp8_frame_header *slice =
> > > run->vp8.slice_params; +       struct vb2_queue *cap_q =
> > > &ctx->fh.m2m_ctx->cap_q_ctx.q;
> > > +       struct vb2_buffer *src_buf = &run->src->vb2_buf;
> > > +       struct cedrus_dev *dev = ctx->dev;
> > > +       dma_addr_t luma_addr, chroma_addr;
> > > +       dma_addr_t src_buf_addr;
> > > +       int header_size;
> > > +       int qindex;
> > > +       u32 reg;
> > > +
> > > +       cedrus_engine_enable(ctx, CEDRUS_CODEC_VP8);
> > > +
> > > +       cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8);
> > > +
> > > +       cedrus_vp8_update_probs(slice, ctx->codec.vp8.entropy_probs_buf);
> > > +
> > > +       reg = slice->first_part_size * 8;
> > > +       cedrus_write(dev, VE_VP8_FIRST_DATA_PART_LEN, reg);
> > > +
> > > +       header_size = VP8_FRAME_IS_KEY_FRAME(slice) ? 10 : 3;
> > > +
> > > +       reg = slice->first_part_size + header_size;
> > > +       cedrus_write(dev, VE_VP8_PART_SIZE_OFFSET, reg);
> > > +
> > > +       reg = vb2_plane_size(src_buf, 0) * 8;
> > > +       cedrus_write(dev, VE_H264_VLD_LEN, reg);
> > > +
> > > +       /*
> > > +        * FIXME: There is a problem if frame header is skipped (adding
> > > +        * first_part_header_bits to offset). It seems that functions
> > > +        * for parsing bitstreams change internal state of VPU in some
> > > +        * way that can't be otherwise set. Maybe this can be bypassed
> > > +        * by somehow fixing probability table buffer?
> > > +        */
> > > +       reg = header_size * 8;
> > > +       cedrus_write(dev, VE_H264_VLD_OFFSET, reg);
> > > +
> > > +       src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
> > > +       cedrus_write(dev, VE_H264_VLD_END,
> > > +                    src_buf_addr + vb2_get_plane_payload(src_buf, 0));
> > > +       cedrus_write(dev, VE_H264_VLD_ADDR,
> > > +                    VE_H264_VLD_ADDR_VAL(src_buf_addr) |
> > > +                    VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
> > > +                    VE_H264_VLD_ADDR_LAST);
> > > +
> > > +       cedrus_write(dev, VE_H264_TRIGGER_TYPE,
> > > +                    VE_H264_TRIGGER_TYPE_INIT_SWDEC);
> > > +
> > > +       cedrus_write(dev, VE_VP8_ENTROPY_PROBS_ADDR,
> > > +                    ctx->codec.vp8.entropy_probs_buf_dma);
> > > +
> > > +       reg = 0;
> > > +       switch (slice->version) {
> > > +       case 1:
> > > +               reg |= VE_VP8_PPS_FILTER_TYPE_SIMPLE;
> > > +               reg |= VE_VP8_PPS_BILINEAR_MC_FILTER;
> > > +               break;
> > > +       case 2:
> > > +               reg |= VE_VP8_PPS_LPF_DISABLE;
> > > +               reg |= VE_VP8_PPS_BILINEAR_MC_FILTER;
> > > +               break;
> > > +       case 3:
> > > +               reg |= VE_VP8_PPS_LPF_DISABLE;
> > > +               reg |= VE_VP8_PPS_FULL_PIXEL;
> > > +               break;
> > > +       }
> > > +       if (slice->segment_header.flags &
> > > V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP) +               reg |=
> > > VE_VP8_PPS_UPDATE_MB_SEGMENTATION_MAP;
> > > +       if (!(slice->segment_header.flags &
> > > V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE)) +               reg |=
> > > VE_VP8_PPS_MB_SEGMENT_ABS_DELTA;
> > > +       if (slice->segment_header.flags &
> > > V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED) +               reg |=
> > > VE_VP8_PPS_SEGMENTATION_ENABLE;
> > > +       if (ctx->codec.vp8.last_filter_type)
> > > +               reg |= VE_VP8_PPS_LAST_LOOP_FILTER_SIMPLE;
> > > +       reg |=
> > > VE_VP8_PPS_SHARPNESS_LEVEL(slice->lf_header.sharpness_level); +       if
> > > (slice->lf_header.flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE) +
> > > reg |= VE_VP8_PPS_LOOP_FILTER_SIMPLE;
> > > +       reg |= VE_VP8_PPS_LOOP_FILTER_LEVEL(slice->lf_header.level);
> > > +       if (slice->lf_header.flags & V4L2_VP8_LF_HEADER_ADJ_ENABLE)
> > > +               reg |= VE_VP8_PPS_MODE_REF_LF_DELTA_ENABLE;
> > > +       if (slice->lf_header.flags & V4L2_VP8_LF_HEADER_DELTA_UPDATE)
> > > +               reg |= VE_VP8_PPS_MODE_REF_LF_DELTA_UPDATE;
> > > +       reg |= VE_VP8_PPS_TOKEN_PARTITION(ilog2(slice->num_dct_parts));
> > > +       if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF)
> > > +               reg |= VE_VP8_PPS_MB_NO_COEFF_SKIP;
> > > +       reg |= VE_VP8_PPS_RELOAD_ENTROPY_PROBS;
> > > +       if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN)
> > > +               reg |= VE_VP8_PPS_GOLDEN_SIGN_BIAS;
> > > +       if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT)
> > > +               reg |= VE_VP8_PPS_ALTREF_SIGN_BIAS;
> > > +       if (ctx->codec.vp8.last_frame_p_type)
> > > +               reg |= VE_VP8_PPS_LAST_PIC_TYPE_P_FRAME;
> > > +       reg |=
> > > VE_VP8_PPS_LAST_SHARPNESS_LEVEL(ctx->codec.vp8.last_sharpness_level); +
> > >     if (!(slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) +
> > >       reg |= VE_VP8_PPS_PIC_TYPE_P_FRAME;
> > > +       cedrus_write(dev, VE_VP8_PPS, reg);
> > > +
> > > +       cedrus_read_header(dev, slice);
> > > +
> > > +       /* reset registers changed by HW */
> > > +       cedrus_write(dev, VE_H264_CUR_MB_NUM, 0);
> > > +       cedrus_write(dev, VE_H264_MB_ADDR, 0);
> > > +       cedrus_write(dev, VE_H264_ERROR_CASE, 0);
> > > +
> > > +       reg = 0;
> > > +       reg |=
> > > VE_VP8_QP_INDEX_DELTA_UVAC(slice->quant_header.uv_ac_delta);
> > > +       reg |=
> > > VE_VP8_QP_INDEX_DELTA_UVDC(slice->quant_header.uv_dc_delta);
> > > +       reg |=
> > > VE_VP8_QP_INDEX_DELTA_Y2AC(slice->quant_header.y2_ac_delta);
> > > +       reg |=
> > > VE_VP8_QP_INDEX_DELTA_Y2DC(slice->quant_header.y2_dc_delta);
> > > +       reg |= VE_VP8_QP_INDEX_DELTA_Y1DC(slice->quant_header.y_dc_delta);
> > > +       reg |=
> > > VE_VP8_QP_INDEX_DELTA_BASE_QINDEX(slice->quant_header.y_ac_qi); +
> > > cedrus_write(dev, VE_VP8_QP_INDEX_DELTA, reg);
> > > +
> > > +       reg = 0;
> > > +       reg |= VE_VP8_FSIZE_WIDTH(slice->width);
> > > +       reg |= VE_VP8_FSIZE_HEIGHT(slice->height);
> > > +       cedrus_write(dev, VE_VP8_FSIZE, reg);
> > > +
> > > +       reg = 0;
> > > +       reg |= VE_VP8_PICSIZE_WIDTH(slice->width);
> > > +       reg |= VE_VP8_PICSIZE_HEIGHT(slice->height);
> > > +       cedrus_write(dev, VE_VP8_PICSIZE, reg);
> > > +
> > > +       reg = 0;
> > > +       reg |= VE_VP8_SEGMENT3(slice->segment_header.quant_update[3]);
> > > +       reg |= VE_VP8_SEGMENT2(slice->segment_header.quant_update[2]);
> > > +       reg |= VE_VP8_SEGMENT1(slice->segment_header.quant_update[1]);
> > > +       reg |= VE_VP8_SEGMENT0(slice->segment_header.quant_update[0]);
> > > +       cedrus_write(dev, VE_VP8_SEGMENT_FEAT_MB_LV0, reg);
> > > +
> > > +       reg = 0;
> > > +       reg |= VE_VP8_SEGMENT3(slice->segment_header.lf_update[3]);
> > > +       reg |= VE_VP8_SEGMENT2(slice->segment_header.lf_update[2]);
> > > +       reg |= VE_VP8_SEGMENT1(slice->segment_header.lf_update[1]);
> > > +       reg |= VE_VP8_SEGMENT0(slice->segment_header.lf_update[0]);
> > > +       cedrus_write(dev, VE_VP8_SEGMENT_FEAT_MB_LV1, reg);
> > > +
> > > +       reg = 0;
> > > +       reg |= VE_VP8_LF_DELTA3(slice->lf_header.ref_frm_delta[3]);
> > > +       reg |= VE_VP8_LF_DELTA2(slice->lf_header.ref_frm_delta[2]);
> > > +       reg |= VE_VP8_LF_DELTA1(slice->lf_header.ref_frm_delta[1]);
> > > +       reg |= VE_VP8_LF_DELTA0(slice->lf_header.ref_frm_delta[0]);
> > > +       cedrus_write(dev, VE_VP8_REF_LF_DELTA, reg);
> > > +
> > > +       reg = 0;
> > > +       reg |= VE_VP8_LF_DELTA3(slice->lf_header.mb_mode_delta[3]);
> > > +       reg |= VE_VP8_LF_DELTA2(slice->lf_header.mb_mode_delta[2]);
> > > +       reg |= VE_VP8_LF_DELTA1(slice->lf_header.mb_mode_delta[1]);
> > > +       reg |= VE_VP8_LF_DELTA0(slice->lf_header.mb_mode_delta[0]);
> > > +       cedrus_write(dev, VE_VP8_MODE_LF_DELTA, reg);
> > > +
> > > +       luma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 0);
> > > +       chroma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index,
> > > 1);
> > > +       cedrus_write(dev, VE_VP8_REC_LUMA, luma_addr);
> > > +       cedrus_write(dev, VE_VP8_REC_CHROMA, chroma_addr);
> > > +
> > > +       qindex = vb2_find_timestamp(cap_q, slice->last_frame_ts, 0);
> > > +       if (qindex >= 0) {
> > > +               luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0);
> > > +               chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1);
> > > +               cedrus_write(dev, VE_VP8_FWD_LUMA, luma_addr);
> > > +               cedrus_write(dev, VE_VP8_FWD_CHROMA, chroma_addr);
> > > +       } else {
> > > +               cedrus_write(dev, VE_VP8_FWD_LUMA, 0);
> > > +               cedrus_write(dev, VE_VP8_FWD_CHROMA, 0);
> > > +       }
> > > +
> > > +       qindex = vb2_find_timestamp(cap_q, slice->golden_frame_ts, 0);
> > > +       if (qindex >= 0) {
> > > +               luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0);
> > > +               chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1);
> > > +               cedrus_write(dev, VE_VP8_BWD_LUMA, luma_addr);
> > > +               cedrus_write(dev, VE_VP8_BWD_CHROMA, chroma_addr);
> > > +       } else {
> > > +               cedrus_write(dev, VE_VP8_BWD_LUMA, 0);
> > > +               cedrus_write(dev, VE_VP8_BWD_CHROMA, 0);
> > > +       }
> > > +
> > > +       qindex = vb2_find_timestamp(cap_q, slice->alt_frame_ts, 0);
> > > +       if (qindex >= 0) {
> > > +               luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0);
> > > +               chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1);
> > > +               cedrus_write(dev, VE_VP8_ALT_LUMA, luma_addr);
> > > +               cedrus_write(dev, VE_VP8_ALT_CHROMA, chroma_addr);
> > > +       } else {
> > > +               cedrus_write(dev, VE_VP8_ALT_LUMA, 0);
> > > +               cedrus_write(dev, VE_VP8_ALT_CHROMA, 0);
> > > +       }
> > > +
> > > +       cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8 |
> > > +                    VE_H264_CTRL_DECODE_ERR_INT |
> > > +                    VE_H264_CTRL_SLICE_DECODE_INT);
> > > +
> > > +       if (slice->lf_header.level) {
> > > +               ctx->codec.vp8.last_filter_type =
> > > +                       !!(slice->lf_header.flags &
> > > V4L2_VP8_LF_FILTER_TYPE_SIMPLE); +
> > > ctx->codec.vp8.last_frame_p_type =
> > > +                       !VP8_FRAME_IS_KEY_FRAME(slice);
> > > +               ctx->codec.vp8.last_sharpness_level =
> > > +                       slice->lf_header.sharpness_level;
> > > +       }
> > > +}
> > > +
> > > +static int cedrus_vp8_start(struct cedrus_ctx *ctx)
> > > +{
> > > +       struct cedrus_dev *dev = ctx->dev;
> > > +
> > > +       ctx->codec.vp8.entropy_probs_buf =
> > > +               dma_alloc_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE,
> > > +                                  &ctx->codec.vp8.entropy_probs_buf_dma,
> > > +                                  GFP_KERNEL);
> > > +       if (!ctx->codec.vp8.entropy_probs_buf)
> > > +               return -ENOMEM;
> > > +
> > > +       memcpy(&ctx->codec.vp8.entropy_probs_buf[2048],
> >
> > I think this 2048 offset, deserves a small comment, if possible.
>
> Not sure what to put into the comment, really. This part has no documentation
> and it was deduced from reverse engineered code. Except maybe "Load default
> entropy probabilities"?
>

Well, even a small comment mentioning this comes from reverse
engineering and we have no documentation, would at least
clarify we are not being intentionally obscure.

> >
> > That's it. Looks mostly good!
>
> Thanks for review.
>

No problem.

Thanks,
Ezequiel

> Best regards,
> Jernej
>
> >
> > Thanks,
> > Ezequiel
>
>
>
>





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux