Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,70 @@
# SPDX-License-Identifier: GPL-2.0-only
comment "Verisilicon media platform drivers"
config VIDEO_HANTRO
tristate "Hantro VPU driver"
depends on ARCH_MXC || ARCH_ROCKCHIP || ARCH_AT91 || ARCH_SUNXI || ARCH_STM32 || COMPILE_TEST
depends on V4L_MEM2MEM_DRIVERS
depends on VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
select V4L2_MEM2MEM_DEV
select V4L2_H264
select V4L2_JPEG_HELPER
select V4L2_VP9
help
Support for the Hantro IP based Video Processing Units present on
Rockchip, NXP i.MX8M and STM32MP25 SoCs, which accelerate video
and image encoding and decoding.
To compile this driver as a module, choose M here: the module
will be called hantro-vpu.
config VIDEO_HANTRO_HEVC_RFC
bool "Use reference frame compression for HEVC"
depends on VIDEO_HANTRO
default n
help
Enable the reference frame compression feature for the HEVC codec.
It will use more memory but save bandwidth on memory bus.
config VIDEO_HANTRO_IMX8M
bool "Hantro VPU i.MX8M support"
depends on VIDEO_HANTRO
depends on ARCH_MXC || COMPILE_TEST
default y
help
Enable support for i.MX8M SoCs.
config VIDEO_HANTRO_SAMA5D4
bool "Hantro VDEC SAMA5D4 support"
depends on VIDEO_HANTRO
depends on ARCH_AT91 || COMPILE_TEST
default y
help
Enable support for Microchip SAMA5D4 SoCs.
config VIDEO_HANTRO_ROCKCHIP
bool "Hantro VPU Rockchip support"
depends on VIDEO_HANTRO
depends on ARCH_ROCKCHIP || COMPILE_TEST
default y
help
Enable support for RK3288, RK3328, and RK3399 SoCs.
config VIDEO_HANTRO_SUNXI
bool "Hantro VPU Allwinner support"
depends on VIDEO_HANTRO
depends on ARCH_SUNXI || COMPILE_TEST
default y
help
Enable support for H6 SoC.
config VIDEO_HANTRO_STM32MP25
bool "Hantro STM32MP25 support"
depends on VIDEO_HANTRO
depends on ARCH_STM32 || COMPILE_TEST
default y
help
Enable support for STM32MP25 SoCs.
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_HANTRO) += hantro-vpu.o
hantro-vpu-y += \
hantro_drv.o \
hantro_v4l2.o \
hantro_postproc.o \
hantro_h1_jpeg_enc.o \
hantro_g1.o \
hantro_g1_h264_dec.o \
hantro_g1_mpeg2_dec.o \
hantro_g1_vp8_dec.o \
hantro_g2.o \
hantro_g2_hevc_dec.o \
hantro_g2_vp9_dec.o \
hantro_jpeg.o \
hantro_h264.o \
hantro_hevc.o \
hantro_mpeg2.o \
hantro_vp8.o \
hantro_vp9.o
hantro-vpu-$(CONFIG_VIDEO_HANTRO_IMX8M) += \
imx8m_vpu_hw.o
hantro-vpu-$(CONFIG_VIDEO_HANTRO_SAMA5D4) += \
sama5d4_vdec_hw.o
hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \
rockchip_vpu2_hw_jpeg_enc.o \
rockchip_vpu2_hw_h264_dec.o \
rockchip_vpu2_hw_mpeg2_dec.o \
rockchip_vpu2_hw_vp8_dec.o \
rockchip_vpu981_hw_av1_dec.o \
rockchip_av1_filmgrain.o \
rockchip_av1_entropymode.o \
rockchip_vpu_hw.o
hantro-vpu-$(CONFIG_VIDEO_HANTRO_SUNXI) += \
sunxi_vpu_hw.o
hantro-vpu-$(CONFIG_VIDEO_HANTRO_STM32MP25) += \
stm32mp25_vpu_hw.o
@@ -0,0 +1,510 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VPU codec driver
*
* Copyright 2018 Google LLC.
* Tomasz Figa <tfiga@chromium.org>
*
* Based on s5p-mfc driver by Samsung Electronics Co., Ltd.
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
*/
#ifndef HANTRO_H_
#define HANTRO_H_
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <linux/wait.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
#include "hantro_hw.h"
struct hantro_ctx;
struct hantro_codec_ops;
struct hantro_postproc_ops;
#define HANTRO_JPEG_ENCODER BIT(0)
#define HANTRO_ENCODERS 0x0000ffff
#define HANTRO_MPEG2_DECODER BIT(16)
#define HANTRO_VP8_DECODER BIT(17)
#define HANTRO_H264_DECODER BIT(18)
#define HANTRO_HEVC_DECODER BIT(19)
#define HANTRO_VP9_DECODER BIT(20)
#define HANTRO_AV1_DECODER BIT(21)
#define HANTRO_DECODERS 0xffff0000
/**
* struct hantro_irq - irq handler and name
*
* @name: irq name for device tree lookup
* @handler: interrupt handler
*/
struct hantro_irq {
const char *name;
irqreturn_t (*handler)(int irq, void *priv);
};
/**
* struct hantro_variant - information about VPU hardware variant
*
* @enc_offset: Offset from VPU base to encoder registers.
* @dec_offset: Offset from VPU base to decoder registers.
* @enc_fmts: Encoder formats.
* @num_enc_fmts: Number of encoder formats.
* @dec_fmts: Decoder formats.
* @num_dec_fmts: Number of decoder formats.
* @postproc_fmts: Post-processor formats.
* @num_postproc_fmts: Number of post-processor formats.
* @postproc_ops: Post-processor ops.
* @codec: Supported codecs
* @codec_ops: Codec ops.
* @init: Initialize hardware, optional.
* @runtime_resume: reenable hardware after power gating, optional.
* @irqs: array of irq names and interrupt handlers
* @num_irqs: number of irqs in the array
* @clk_names: array of clock names
* @num_clocks: number of clocks in the array
* @reg_names: array of register range names
* @num_regs: number of register range names in the array
* @double_buffer: core needs double buffering
* @legacy_regs: core uses legacy register set
* @late_postproc: postproc must be set up at the end of the job
* @shared_devices: an array of device ids that cannot run concurrently
*/
struct hantro_variant {
unsigned int enc_offset;
unsigned int dec_offset;
const struct hantro_fmt *enc_fmts;
unsigned int num_enc_fmts;
const struct hantro_fmt *dec_fmts;
unsigned int num_dec_fmts;
const struct hantro_fmt *postproc_fmts;
unsigned int num_postproc_fmts;
const struct hantro_postproc_ops *postproc_ops;
unsigned int codec;
const struct hantro_codec_ops *codec_ops;
int (*init)(struct hantro_dev *vpu);
int (*runtime_resume)(struct hantro_dev *vpu);
const struct hantro_irq *irqs;
int num_irqs;
const char * const *clk_names;
int num_clocks;
const char * const *reg_names;
int num_regs;
unsigned int double_buffer : 1;
unsigned int legacy_regs : 1;
unsigned int late_postproc : 1;
const struct of_device_id *shared_devices;
};
/**
* enum hantro_codec_mode - codec operating mode.
* @HANTRO_MODE_NONE: No operating mode. Used for RAW video formats.
* @HANTRO_MODE_JPEG_ENC: JPEG encoder.
* @HANTRO_MODE_H264_DEC: H264 decoder.
* @HANTRO_MODE_MPEG2_DEC: MPEG-2 decoder.
* @HANTRO_MODE_VP8_DEC: VP8 decoder.
* @HANTRO_MODE_HEVC_DEC: HEVC decoder.
* @HANTRO_MODE_VP9_DEC: VP9 decoder.
* @HANTRO_MODE_AV1_DEC: AV1 decoder
*/
enum hantro_codec_mode {
HANTRO_MODE_NONE = -1,
HANTRO_MODE_JPEG_ENC,
HANTRO_MODE_H264_DEC,
HANTRO_MODE_MPEG2_DEC,
HANTRO_MODE_VP8_DEC,
HANTRO_MODE_HEVC_DEC,
HANTRO_MODE_VP9_DEC,
HANTRO_MODE_AV1_DEC,
};
/*
* struct hantro_ctrl - helper type to declare supported controls
* @codec: codec id this control belong to (HANTRO_JPEG_ENCODER, etc.)
* @cfg: control configuration
*/
struct hantro_ctrl {
unsigned int codec;
struct v4l2_ctrl_config cfg;
};
/*
* struct hantro_func - Hantro VPU functionality
*
* @id: processing functionality ID (can be
* %MEDIA_ENT_F_PROC_VIDEO_ENCODER or
* %MEDIA_ENT_F_PROC_VIDEO_DECODER)
* @vdev: &struct video_device that exposes the encoder or
* decoder functionality
* @source_pad: &struct media_pad with the source pad.
* @sink: &struct media_entity pointer with the sink entity
* @sink_pad: &struct media_pad with the sink pad.
* @proc: &struct media_entity pointer with the M2M device itself.
* @proc_pads: &struct media_pad with the @proc pads.
* @intf_devnode: &struct media_intf devnode pointer with the interface
* with controls the M2M device.
*
* Contains everything needed to attach the video device to the media device.
*/
struct hantro_func {
unsigned int id;
struct video_device vdev;
struct media_pad source_pad;
struct media_entity sink;
struct media_pad sink_pad;
struct media_entity proc;
struct media_pad proc_pads[2];
struct media_intf_devnode *intf_devnode;
};
static inline struct hantro_func *
hantro_vdev_to_func(struct video_device *vdev)
{
return container_of(vdev, struct hantro_func, vdev);
}
/**
* struct hantro_dev - driver data
* @v4l2_dev: V4L2 device to register video devices for.
* @m2m_dev: mem2mem device associated to this device.
* @mdev: media device associated to this device.
* @encoder: encoder functionality.
* @decoder: decoder functionality.
* @pdev: Pointer to VPU platform device.
* @dev: Pointer to device for convenient logging using
* dev_ macros.
* @clocks: Array of clock handles.
* @resets: Array of reset handles.
* @reg_bases: Mapped addresses of VPU registers.
* @enc_base: Mapped address of VPU encoder register for convenience.
* @dec_base: Mapped address of VPU decoder register for convenience.
* @ctrl_base: Mapped address of VPU control block.
* @vpu_mutex: Mutex to synchronize V4L2 calls.
* @irqlock: Spinlock to synchronize access to data structures
* shared with interrupt handlers.
* @variant: Hardware variant-specific parameters.
* @watchdog_work: Delayed work for hardware timeout handling.
*/
struct hantro_dev {
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
struct media_device mdev;
struct hantro_func *encoder;
struct hantro_func *decoder;
struct platform_device *pdev;
struct device *dev;
struct clk_bulk_data *clocks;
struct reset_control *resets;
void __iomem **reg_bases;
void __iomem *enc_base;
void __iomem *dec_base;
void __iomem *ctrl_base;
struct mutex vpu_mutex; /* video_device lock */
spinlock_t irqlock;
const struct hantro_variant *variant;
struct delayed_work watchdog_work;
};
/**
* struct hantro_ctx - Context (instance) private data.
*
* @dev: VPU driver data to which the context belongs.
* @fh: V4L2 file handler.
* @is_encoder: Decoder or encoder context?
*
* @sequence_cap: Sequence counter for capture queue
* @sequence_out: Sequence counter for output queue
*
* @vpu_src_fmt: Descriptor of active source format.
* @src_fmt: V4L2 pixel format of active source format.
* @vpu_dst_fmt: Descriptor of active destination format.
* @dst_fmt: V4L2 pixel format of active destination format.
* @ref_fmt: V4L2 pixel format of the reference frames format.
*
* @ctrl_handler: Control handler used to register controls.
* @jpeg_quality: User-specified JPEG compression quality.
* @bit_depth: Bit depth of current frame
* @need_postproc: Set to true if the bitstream features require to
* use the post-processor.
*
* @codec_ops: Set of operations related to codec mode.
* @postproc: Post-processing context.
* @h264_dec: H.264-decoding context.
* @mpeg2_dec: MPEG-2-decoding context.
* @vp8_dec: VP8-decoding context.
* @hevc_dec: HEVC-decoding context.
* @vp9_dec: VP9-decoding context.
* @av1_dec: AV1-decoding context.
*/
struct hantro_ctx {
struct hantro_dev *dev;
struct v4l2_fh fh;
bool is_encoder;
u32 sequence_cap;
u32 sequence_out;
const struct hantro_fmt *vpu_src_fmt;
struct v4l2_pix_format_mplane src_fmt;
const struct hantro_fmt *vpu_dst_fmt;
struct v4l2_pix_format_mplane dst_fmt;
struct v4l2_pix_format_mplane ref_fmt;
struct v4l2_ctrl_handler ctrl_handler;
int jpeg_quality;
int bit_depth;
const struct hantro_codec_ops *codec_ops;
struct hantro_postproc_ctx postproc;
bool need_postproc;
/* Specific for particular codec modes. */
union {
struct hantro_h264_dec_hw_ctx h264_dec;
struct hantro_mpeg2_dec_hw_ctx mpeg2_dec;
struct hantro_vp8_dec_hw_ctx vp8_dec;
struct hantro_hevc_dec_hw_ctx hevc_dec;
struct hantro_vp9_dec_hw_ctx vp9_dec;
struct hantro_av1_dec_hw_ctx av1_dec;
};
};
/**
* struct hantro_fmt - information about supported video formats.
* @name: Human readable name of the format.
* @fourcc: FourCC code of the format. See V4L2_PIX_FMT_*.
* @codec_mode: Codec mode related to this format. See
* enum hantro_codec_mode.
* @header_size: Optional header size. Currently used by JPEG encoder.
* @max_depth: Maximum depth, for bitstream formats
* @enc_fmt: Format identifier for encoder registers.
* @frmsize: Supported range of frame sizes (only for bitstream formats).
* @postprocessed: Indicates if this format needs the post-processor.
* @match_depth: Indicates if format bit depth must match video bit depth
*/
struct hantro_fmt {
char *name;
u32 fourcc;
enum hantro_codec_mode codec_mode;
int header_size;
int max_depth;
enum hantro_enc_fmt enc_fmt;
struct v4l2_frmsize_stepwise frmsize;
bool postprocessed;
bool match_depth;
};
struct hantro_reg {
u32 base;
u32 shift;
u32 mask;
};
struct hantro_postproc_regs {
struct hantro_reg pipeline_en;
struct hantro_reg max_burst;
struct hantro_reg clk_gate;
struct hantro_reg out_swap32;
struct hantro_reg out_endian;
struct hantro_reg out_luma_base;
struct hantro_reg input_width;
struct hantro_reg input_height;
struct hantro_reg output_width;
struct hantro_reg output_height;
struct hantro_reg input_fmt;
struct hantro_reg output_fmt;
struct hantro_reg orig_width;
struct hantro_reg display_width;
struct hantro_reg input_width_ext;
struct hantro_reg input_height_ext;
};
struct hantro_vp9_decoded_buffer_info {
/* Info needed when the decoded frame serves as a reference frame. */
unsigned short width;
unsigned short height;
size_t chroma_offset;
size_t mv_offset;
u32 bit_depth : 4;
};
struct hantro_av1_decoded_buffer_info {
/* Info needed when the decoded frame serves as a reference frame. */
size_t chroma_offset;
size_t mv_offset;
};
struct hantro_decoded_buffer {
/* Must be the first field in this struct. */
struct v4l2_m2m_buffer base;
union {
struct hantro_vp9_decoded_buffer_info vp9;
struct hantro_av1_decoded_buffer_info av1;
};
};
/* Logging helpers */
/**
* DOC: hantro_debug: Module parameter to control level of debugging messages.
*
* Level of debugging messages can be controlled by bits of
* module parameter called "debug". Meaning of particular
* bits is as follows:
*
* bit 0 - global information: mode, size, init, release
* bit 1 - each run start/result information
* bit 2 - contents of small controls from userspace
* bit 3 - contents of big controls from userspace
* bit 4 - detail fmt, ctrl, buffer q/dq information
* bit 5 - detail function enter/leave trace information
* bit 6 - register write/read information
*/
extern int hantro_debug;
#define vpu_debug(level, fmt, args...) \
do { \
if (hantro_debug & BIT(level)) \
pr_info("%s:%d: " fmt, \
__func__, __LINE__, ##args); \
} while (0)
#define vpu_err(fmt, args...) \
pr_err("%s:%d: " fmt, __func__, __LINE__, ##args)
/* Structure access helpers. */
static __always_inline struct hantro_ctx *file_to_ctx(struct file *filp)
{
return container_of(file_to_v4l2_fh(filp), struct hantro_ctx, fh);
}
/* Register accessors. */
static __always_inline void vepu_write_relaxed(struct hantro_dev *vpu,
u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel_relaxed(val, vpu->enc_base + reg);
}
static __always_inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel(val, vpu->enc_base + reg);
}
static __always_inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
{
u32 val = readl(vpu->enc_base + reg);
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
return val;
}
static __always_inline void vdpu_write_relaxed(struct hantro_dev *vpu,
u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel_relaxed(val, vpu->dec_base + reg);
}
static __always_inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel(val, vpu->dec_base + reg);
}
static __always_inline void hantro_write_addr(struct hantro_dev *vpu,
unsigned long offset,
dma_addr_t addr)
{
vdpu_write(vpu, addr & 0xffffffff, offset);
}
static __always_inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
{
u32 val = readl(vpu->dec_base + reg);
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
return val;
}
static __always_inline u32 vdpu_read_mask(struct hantro_dev *vpu,
const struct hantro_reg *reg,
u32 val)
{
u32 v;
v = vdpu_read(vpu, reg->base);
v &= ~(reg->mask << reg->shift);
v |= ((val & reg->mask) << reg->shift);
return v;
}
static __always_inline void hantro_reg_write(struct hantro_dev *vpu,
const struct hantro_reg *reg,
u32 val)
{
vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
}
static __always_inline void hantro_reg_write_relaxed(struct hantro_dev *vpu,
const struct hantro_reg *reg,
u32 val)
{
vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
}
void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id);
dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts);
static inline struct vb2_v4l2_buffer *
hantro_get_src_buf(struct hantro_ctx *ctx)
{
return v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
}
static inline struct vb2_v4l2_buffer *
hantro_get_dst_buf(struct hantro_ctx *ctx)
{
return v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
}
bool hantro_needs_postproc(const struct hantro_ctx *ctx,
const struct hantro_fmt *fmt);
dma_addr_t
hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
static inline dma_addr_t
hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
{
if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
return vb2_dma_contig_plane_dma_addr(vb, 0);
}
static inline struct hantro_decoded_buffer *
vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
{
return container_of(buf, struct hantro_decoded_buffer, base.vb.vb2_buf);
}
void hantro_postproc_disable(struct hantro_ctx *ctx);
void hantro_postproc_enable(struct hantro_ctx *ctx);
int hantro_postproc_init(struct hantro_ctx *ctx);
void hantro_postproc_free(struct hantro_ctx *ctx);
int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
struct v4l2_frmsizeenum *fsize);
#endif /* HANTRO_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
* Jeffy Chen <jeffy.chen@rock-chips.com>
* Copyright (C) 2019 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
* Copyright (C) 2021 Collabora Ltd, Emil Velikov <emil.velikov@collabora.com>
*/
#include "hantro.h"
#include "hantro_g1_regs.h"
irqreturn_t hantro_g1_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
enum vb2_buffer_state state;
u32 status;
status = vdpu_read(vpu, G1_REG_INTERRUPT);
state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
vdpu_write(vpu, 0, G1_REG_INTERRUPT);
vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
hantro_irq_done(vpu, state);
return IRQ_HANDLED;
}
void hantro_g1_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT);
vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
vdpu_write(vpu, 1, G1_REG_SOFT_RESET);
}
@@ -0,0 +1,284 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Rockchip RK3288 VPU codec driver
*
* Copyright (c) 2014 Rockchip Electronics Co., Ltd.
* Hertz Wong <hertz.wong@rock-chips.com>
* Herman Chen <herman.chen@rock-chips.com>
*
* Copyright (C) 2014 Google, Inc.
* Tomasz Figa <tfiga@chromium.org>
*/
#include <linux/types.h>
#include <linux/sort.h>
#include <media/v4l2-mem2mem.h>
#include "hantro_g1_regs.h"
#include "hantro_hw.h"
#include "hantro_v4l2.h"
static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
struct hantro_dev *vpu = ctx->dev;
u32 reg;
/* Decoder control register 0. */
reg = G1_REG_DEC_CTRL0_DEC_AXI_AUTO;
if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
reg |= G1_REG_DEC_CTRL0_SEQ_MBAFF_E;
if (sps->profile_idc > 66) {
reg |= G1_REG_DEC_CTRL0_PICORD_COUNT_E;
if (dec_param->nal_ref_idc)
reg |= G1_REG_DEC_CTRL0_WRITE_MVS_E;
}
if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD ||
dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC))
reg |= G1_REG_DEC_CTRL0_PIC_INTERLACE_E;
if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)
reg |= G1_REG_DEC_CTRL0_PIC_FIELDMODE_E;
if (!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD))
reg |= G1_REG_DEC_CTRL0_PIC_TOPFIELD_E;
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0);
/* Decoder control register 1. */
reg = G1_REG_DEC_CTRL1_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)) |
G1_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) |
G1_REG_DEC_CTRL1_REF_FRAMES(sps->max_num_ref_frames);
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL1);
/* Decoder control register 2. */
reg = G1_REG_DEC_CTRL2_CH_QP_OFFSET(pps->chroma_qp_index_offset) |
G1_REG_DEC_CTRL2_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset);
if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)
reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E;
if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
reg |= G1_REG_DEC_CTRL2_FIELDPIC_FLAG_E;
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2);
/* Decoder control register 3. */
reg = G1_REG_DEC_CTRL3_START_CODE_E |
G1_REG_DEC_CTRL3_INIT_QP(pps->pic_init_qp_minus26 + 26) |
G1_REG_DEC_CTRL3_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL3);
/* Decoder control register 4. */
reg = G1_REG_DEC_CTRL4_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) |
G1_REG_DEC_CTRL4_FRAMENUM(dec_param->frame_num) |
G1_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc);
if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
reg |= G1_REG_DEC_CTRL4_CABAC_E;
if (sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)
reg |= G1_REG_DEC_CTRL4_DIR_8X8_INFER_E;
if (sps->profile_idc >= 100 && sps->chroma_format_idc == 0)
reg |= G1_REG_DEC_CTRL4_BLACKWHITE_E;
if (pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED)
reg |= G1_REG_DEC_CTRL4_WEIGHT_PRED_E;
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4);
/* Decoder control register 5. */
reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) |
G1_REG_DEC_CTRL5_IDR_PIC_ID(dec_param->idr_pic_id);
if (pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)
reg |= G1_REG_DEC_CTRL5_CONST_INTRA_E;
if (pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)
reg |= G1_REG_DEC_CTRL5_FILT_CTRL_PRES;
if (pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT)
reg |= G1_REG_DEC_CTRL5_RDPIC_CNT_PRES;
if (pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE)
reg |= G1_REG_DEC_CTRL5_8X8TRANS_FLAG_E;
if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC)
reg |= G1_REG_DEC_CTRL5_IDR_PIC_E;
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL5);
/* Decoder control register 6. */
reg = G1_REG_DEC_CTRL6_PPS_ID(pps->pic_parameter_set_id) |
G1_REG_DEC_CTRL6_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) |
G1_REG_DEC_CTRL6_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) |
G1_REG_DEC_CTRL6_POC_LENGTH(dec_param->pic_order_cnt_bit_size);
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL6);
/* Error concealment register. */
vdpu_write_relaxed(vpu, 0, G1_REG_ERR_CONC);
/* Prediction filter tap register. */
vdpu_write_relaxed(vpu,
G1_REG_PRED_FLT_PRED_BC_TAP_0_0(1) |
G1_REG_PRED_FLT_PRED_BC_TAP_0_1(-5 & 0x3ff) |
G1_REG_PRED_FLT_PRED_BC_TAP_0_2(20),
G1_REG_PRED_FLT);
/* Reference picture buffer control register. */
vdpu_write_relaxed(vpu, 0, G1_REG_REF_BUF_CTRL);
/* Reference picture buffer control register 2. */
vdpu_write_relaxed(vpu, G1_REG_REF_BUF_CTRL2_APF_THRESHOLD(8),
G1_REG_REF_BUF_CTRL2);
}
static void set_ref(struct hantro_ctx *ctx)
{
const struct v4l2_h264_reference *b0_reflist, *b1_reflist, *p_reflist;
struct hantro_dev *vpu = ctx->dev;
int reg_num;
u32 reg;
int i;
vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF);
vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF);
/*
* Set up reference frame picture numbers.
*
* Each G1_REG_REF_PIC(x) register contains numbers of two
* subsequential reference pictures.
*/
for (i = 0; i < HANTRO_H264_DPB_SIZE; i += 2) {
reg = G1_REG_REF_PIC_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, i)) |
G1_REG_REF_PIC_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, i + 1));
vdpu_write_relaxed(vpu, reg, G1_REG_REF_PIC(i / 2));
}
b0_reflist = ctx->h264_dec.reflists.b0;
b1_reflist = ctx->h264_dec.reflists.b1;
p_reflist = ctx->h264_dec.reflists.p;
/*
* Each G1_REG_BD_REF_PIC(x) register contains three entries
* of each forward and backward picture list.
*/
reg_num = 0;
for (i = 0; i < 15; i += 3) {
reg = G1_REG_BD_REF_PIC_BINIT_RLIST_F0(b0_reflist[i].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_F1(b0_reflist[i + 1].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_F2(b0_reflist[i + 2].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B0(b1_reflist[i].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B1(b1_reflist[i + 1].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B2(b1_reflist[i + 2].index);
vdpu_write_relaxed(vpu, reg, G1_REG_BD_REF_PIC(reg_num++));
}
/*
* G1_REG_BD_P_REF_PIC register contains last entries (index 15)
* of forward and backward reference picture lists and first 4 entries
* of P forward picture list.
*/
reg = G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(b0_reflist[15].index) |
G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(b1_reflist[15].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(p_reflist[0].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(p_reflist[1].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(p_reflist[2].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(p_reflist[3].index);
vdpu_write_relaxed(vpu, reg, G1_REG_BD_P_REF_PIC);
/*
* Each G1_REG_FWD_PIC(x) register contains six consecutive
* entries of P forward picture list, starting from index 4.
*/
reg_num = 0;
for (i = 4; i < HANTRO_H264_DPB_SIZE; i += 6) {
reg = G1_REG_FWD_PIC_PINIT_RLIST_F0(p_reflist[i].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F1(p_reflist[i + 1].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F2(p_reflist[i + 2].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F3(p_reflist[i + 3].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F4(p_reflist[i + 4].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F5(p_reflist[i + 5].index);
vdpu_write_relaxed(vpu, reg, G1_REG_FWD_PIC(reg_num++));
}
/* Set up addresses of DPB buffers. */
for (i = 0; i < HANTRO_H264_DPB_SIZE; i++) {
dma_addr_t dma_addr = hantro_h264_get_ref_buf(ctx, i);
vdpu_write_relaxed(vpu, dma_addr, G1_REG_ADDR_REF(i));
}
}
static void set_buffers(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
struct vb2_v4l2_buffer *dst_buf;
struct hantro_dev *vpu = ctx->dev;
dma_addr_t src_dma, dst_dma;
size_t offset = 0;
/* Source (stream) buffer. */
src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
vdpu_write_relaxed(vpu, src_dma, G1_REG_ADDR_STR);
/* Destination (decoded frame) buffer. */
dst_buf = hantro_get_dst_buf(ctx);
dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
/* Adjust dma addr to start at second line for bottom field */
if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
offset = ALIGN(ctx->src_fmt.width, MB_DIM);
vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DST);
/* Higher profiles require DMV buffer appended to reference frames. */
if (ctrls->sps->profile_idc > 66 && ctrls->decode->nal_ref_idc) {
unsigned int bytes_per_mb = 384;
/* DMV buffer for monochrome start directly after Y-plane */
if (ctrls->sps->profile_idc >= 100 &&
ctrls->sps->chroma_format_idc == 0)
bytes_per_mb = 256;
offset = bytes_per_mb * MB_WIDTH(ctx->src_fmt.width) *
MB_HEIGHT(ctx->src_fmt.height);
/*
* DMV buffer is split in two for field encoded frames,
* adjust offset for bottom field
*/
if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
offset += 32 * MB_WIDTH(ctx->src_fmt.width) *
MB_HEIGHT(ctx->src_fmt.height);
vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DIR_MV);
}
/* Auxiliary buffer prepared in hantro_h264_dec_init(). */
vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, G1_REG_ADDR_QTABLE);
}
int hantro_g1_h264_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf;
int ret;
/* Prepare the H264 decoder context. */
ret = hantro_h264_dec_prepare_run(ctx);
if (ret)
return ret;
/* Configure hardware registers. */
src_buf = hantro_get_src_buf(ctx);
set_params(ctx, src_buf);
set_ref(ctx);
set_buffers(ctx, src_buf);
hantro_end_prepare_run(ctx);
/* Start decoding! */
vdpu_write_relaxed(vpu,
G1_REG_CONFIG_DEC_AXI_RD_ID(0xffu) |
G1_REG_CONFIG_DEC_TIMEOUT_E |
G1_REG_CONFIG_DEC_OUT_ENDIAN |
G1_REG_CONFIG_DEC_STRENDIAN_E |
G1_REG_CONFIG_DEC_MAX_BURST(16) |
G1_REG_CONFIG_DEC_OUTSWAP32_E |
G1_REG_CONFIG_DEC_INSWAP32_E |
G1_REG_CONFIG_DEC_STRSWAP32_E |
G1_REG_CONFIG_DEC_CLK_GATE_E,
G1_REG_CONFIG);
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT);
return 0;
}
@@ -0,0 +1,240 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*/
#include <linux/unaligned.h>
#include <linux/bitfield.h>
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
#include "hantro_g1_regs.h"
#define G1_SWREG(nr) ((nr) * 4)
#define G1_REG_RLC_VLC_BASE G1_SWREG(12)
#define G1_REG_DEC_OUT_BASE G1_SWREG(13)
#define G1_REG_REFER0_BASE G1_SWREG(14)
#define G1_REG_REFER1_BASE G1_SWREG(15)
#define G1_REG_REFER2_BASE G1_SWREG(16)
#define G1_REG_REFER3_BASE G1_SWREG(17)
#define G1_REG_QTABLE_BASE G1_SWREG(40)
#define G1_REG_DEC_AXI_RD_ID(v) (((v) << 24) & GENMASK(31, 24))
#define G1_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(23) : 0)
#define G1_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(22) : 0)
#define G1_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(21) : 0)
#define G1_REG_DEC_INSWAP32_E(v) ((v) ? BIT(20) : 0)
#define G1_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(19) : 0)
#define G1_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(18) : 0)
#define G1_REG_DEC_LATENCY(v) (((v) << 11) & GENMASK(16, 11))
#define G1_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(10) : 0)
#define G1_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(9) : 0)
#define G1_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(8) : 0)
#define G1_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(6) : 0)
#define G1_REG_DEC_SCMD_DIS(v) ((v) ? BIT(5) : 0)
#define G1_REG_DEC_MAX_BURST(v) (((v) << 0) & GENMASK(4, 0))
#define G1_REG_DEC_MODE(v) (((v) << 28) & GENMASK(31, 28))
#define G1_REG_RLC_MODE_E(v) ((v) ? BIT(27) : 0)
#define G1_REG_PIC_INTERLACE_E(v) ((v) ? BIT(23) : 0)
#define G1_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(22) : 0)
#define G1_REG_PIC_B_E(v) ((v) ? BIT(21) : 0)
#define G1_REG_PIC_INTER_E(v) ((v) ? BIT(20) : 0)
#define G1_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(19) : 0)
#define G1_REG_FWD_INTERLACE_E(v) ((v) ? BIT(18) : 0)
#define G1_REG_FILTERING_DIS(v) ((v) ? BIT(14) : 0)
#define G1_REG_WRITE_MVS_E(v) ((v) ? BIT(12) : 0)
#define G1_REG_DEC_AXI_WR_ID(v) (((v) << 0) & GENMASK(7, 0))
#define G1_REG_PIC_MB_WIDTH(v) (((v) << 23) & GENMASK(31, 23))
#define G1_REG_PIC_MB_HEIGHT_P(v) (((v) << 11) & GENMASK(18, 11))
#define G1_REG_ALT_SCAN_E(v) ((v) ? BIT(6) : 0)
#define G1_REG_TOPFIELDFIRST_E(v) ((v) ? BIT(5) : 0)
#define G1_REG_STRM_START_BIT(v) (((v) << 26) & GENMASK(31, 26))
#define G1_REG_QSCALE_TYPE(v) ((v) ? BIT(24) : 0)
#define G1_REG_CON_MV_E(v) ((v) ? BIT(4) : 0)
#define G1_REG_INTRA_DC_PREC(v) (((v) << 2) & GENMASK(3, 2))
#define G1_REG_INTRA_VLC_TAB(v) ((v) ? BIT(1) : 0)
#define G1_REG_FRAME_PRED_DCT(v) ((v) ? BIT(0) : 0)
#define G1_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25))
#define G1_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0))
#define G1_REG_ALT_SCAN_FLAG_E(v) ((v) ? BIT(19) : 0)
#define G1_REG_FCODE_FWD_HOR(v) (((v) << 15) & GENMASK(18, 15))
#define G1_REG_FCODE_FWD_VER(v) (((v) << 11) & GENMASK(14, 11))
#define G1_REG_FCODE_BWD_HOR(v) (((v) << 7) & GENMASK(10, 7))
#define G1_REG_FCODE_BWD_VER(v) (((v) << 3) & GENMASK(6, 3))
#define G1_REG_MV_ACCURACY_FWD(v) ((v) ? BIT(2) : 0)
#define G1_REG_MV_ACCURACY_BWD(v) ((v) ? BIT(1) : 0)
#define G1_REG_STARTMB_X(v) (((v) << 23) & GENMASK(31, 23))
#define G1_REG_STARTMB_Y(v) (((v) << 15) & GENMASK(22, 15))
#define G1_REG_APF_THRESHOLD(v) (((v) << 0) & GENMASK(13, 0))
static void
hantro_g1_mpeg2_dec_set_quantisation(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
struct v4l2_ctrl_mpeg2_quantisation *q;
q = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_MPEG2_QUANTISATION);
hantro_mpeg2_dec_copy_qtable(ctx->mpeg2_dec.qtable.cpu, q);
vdpu_write_relaxed(vpu, ctx->mpeg2_dec.qtable.dma, G1_REG_QTABLE_BASE);
}
static void
hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx,
struct vb2_buffer *src_buf,
struct vb2_buffer *dst_buf,
const struct v4l2_ctrl_mpeg2_sequence *seq,
const struct v4l2_ctrl_mpeg2_picture *pic)
{
dma_addr_t forward_addr = 0, backward_addr = 0;
dma_addr_t current_addr, addr;
switch (pic->picture_coding_type) {
case V4L2_MPEG2_PIC_CODING_TYPE_B:
backward_addr = hantro_get_ref(ctx, pic->backward_ref_ts);
fallthrough;
case V4L2_MPEG2_PIC_CODING_TYPE_P:
forward_addr = hantro_get_ref(ctx, pic->forward_ref_ts);
}
/* Source bitstream buffer */
addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
vdpu_write_relaxed(vpu, addr, G1_REG_RLC_VLC_BASE);
/* Destination frame buffer */
addr = hantro_get_dec_buf_addr(ctx, dst_buf);
current_addr = addr;
if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD)
addr += ALIGN(ctx->dst_fmt.width, 16);
vdpu_write_relaxed(vpu, addr, G1_REG_DEC_OUT_BASE);
if (!forward_addr)
forward_addr = current_addr;
if (!backward_addr)
backward_addr = current_addr;
/* Set forward ref frame (top/bottom field) */
if (pic->picture_structure == V4L2_MPEG2_PIC_FRAME ||
pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B ||
(pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD &&
pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST) ||
(pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD &&
!(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST))) {
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER1_BASE);
} else if (pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) {
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, current_addr, G1_REG_REFER1_BASE);
} else if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD) {
vdpu_write_relaxed(vpu, current_addr, G1_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER1_BASE);
}
/* Set backward ref frame (top/bottom field) */
vdpu_write_relaxed(vpu, backward_addr, G1_REG_REFER2_BASE);
vdpu_write_relaxed(vpu, backward_addr, G1_REG_REFER3_BASE);
}
int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
const struct v4l2_ctrl_mpeg2_sequence *seq;
const struct v4l2_ctrl_mpeg2_picture *pic;
u32 reg;
src_buf = hantro_get_src_buf(ctx);
dst_buf = hantro_get_dst_buf(ctx);
/* Apply request controls if any */
hantro_start_prepare_run(ctx);
seq = hantro_get_ctrl(ctx,
V4L2_CID_STATELESS_MPEG2_SEQUENCE);
pic = hantro_get_ctrl(ctx,
V4L2_CID_STATELESS_MPEG2_PICTURE);
reg = G1_REG_DEC_AXI_RD_ID(0) |
G1_REG_DEC_TIMEOUT_E(1) |
G1_REG_DEC_STRSWAP32_E(1) |
G1_REG_DEC_STRENDIAN_E(1) |
G1_REG_DEC_INSWAP32_E(1) |
G1_REG_DEC_OUTSWAP32_E(1) |
G1_REG_DEC_DATA_DISC_E(0) |
G1_REG_DEC_LATENCY(0) |
G1_REG_DEC_CLK_GATE_E(1) |
G1_REG_DEC_IN_ENDIAN(1) |
G1_REG_DEC_OUT_ENDIAN(1) |
G1_REG_DEC_ADV_PRE_DIS(0) |
G1_REG_DEC_SCMD_DIS(0) |
G1_REG_DEC_MAX_BURST(16);
vdpu_write_relaxed(vpu, reg, G1_SWREG(2));
reg = G1_REG_DEC_MODE(5) |
G1_REG_RLC_MODE_E(0) |
G1_REG_PIC_INTERLACE_E(!(seq->flags & V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE)) |
G1_REG_PIC_FIELDMODE_E(pic->picture_structure != V4L2_MPEG2_PIC_FRAME) |
G1_REG_PIC_B_E(pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B) |
G1_REG_PIC_INTER_E(pic->picture_coding_type != V4L2_MPEG2_PIC_CODING_TYPE_I) |
G1_REG_PIC_TOPFIELD_E(pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) |
G1_REG_FWD_INTERLACE_E(0) |
G1_REG_FILTERING_DIS(1) |
G1_REG_WRITE_MVS_E(0) |
G1_REG_DEC_AXI_WR_ID(0);
vdpu_write_relaxed(vpu, reg, G1_SWREG(3));
reg = G1_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->dst_fmt.width)) |
G1_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->dst_fmt.height)) |
G1_REG_ALT_SCAN_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
G1_REG_TOPFIELDFIRST_E(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
vdpu_write_relaxed(vpu, reg, G1_SWREG(4));
reg = G1_REG_STRM_START_BIT(0) |
G1_REG_QSCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE) |
G1_REG_CON_MV_E(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV) |
G1_REG_INTRA_DC_PREC(pic->intra_dc_precision) |
G1_REG_INTRA_VLC_TAB(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC) |
G1_REG_FRAME_PRED_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
vdpu_write_relaxed(vpu, reg, G1_SWREG(5));
reg = G1_REG_INIT_QP(1) |
G1_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
vdpu_write_relaxed(vpu, reg, G1_SWREG(6));
reg = G1_REG_ALT_SCAN_FLAG_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
G1_REG_FCODE_FWD_HOR(pic->f_code[0][0]) |
G1_REG_FCODE_FWD_VER(pic->f_code[0][1]) |
G1_REG_FCODE_BWD_HOR(pic->f_code[1][0]) |
G1_REG_FCODE_BWD_VER(pic->f_code[1][1]) |
G1_REG_MV_ACCURACY_FWD(1) |
G1_REG_MV_ACCURACY_BWD(1);
vdpu_write_relaxed(vpu, reg, G1_SWREG(18));
reg = G1_REG_STARTMB_X(0) |
G1_REG_STARTMB_Y(0);
vdpu_write_relaxed(vpu, reg, G1_SWREG(48));
reg = G1_REG_APF_THRESHOLD(8);
vdpu_write_relaxed(vpu, reg, G1_SWREG(55));
hantro_g1_mpeg2_dec_set_quantisation(vpu, ctx);
hantro_g1_mpeg2_dec_set_buffers(vpu, ctx, &src_buf->vb2_buf,
&dst_buf->vb2_buf,
seq, pic);
hantro_end_prepare_run(ctx);
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT);
return 0;
}
@@ -0,0 +1,356 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VPU codec driver
*
* Copyright 2018 Google LLC.
* Tomasz Figa <tfiga@chromium.org>
*/
#ifndef HANTRO_G1_REGS_H_
#define HANTRO_G1_REGS_H_
#define G1_SWREG(nr) ((nr) * 4)
/* Decoder registers. */
#define G1_REG_INTERRUPT 0x004
#define G1_REG_INTERRUPT_DEC_PIC_INF BIT(24)
#define G1_REG_INTERRUPT_DEC_TIMEOUT BIT(18)
#define G1_REG_INTERRUPT_DEC_SLICE_INT BIT(17)
#define G1_REG_INTERRUPT_DEC_ERROR_INT BIT(16)
#define G1_REG_INTERRUPT_DEC_ASO_INT BIT(15)
#define G1_REG_INTERRUPT_DEC_BUFFER_INT BIT(14)
#define G1_REG_INTERRUPT_DEC_BUS_INT BIT(13)
#define G1_REG_INTERRUPT_DEC_RDY_INT BIT(12)
#define G1_REG_INTERRUPT_DEC_IRQ BIT(8)
#define G1_REG_INTERRUPT_DEC_IRQ_DIS BIT(4)
#define G1_REG_INTERRUPT_DEC_E BIT(0)
#define G1_REG_CONFIG 0x008
#define G1_REG_CONFIG_DEC_AXI_RD_ID(x) (((x) & 0xff) << 24)
#define G1_REG_CONFIG_DEC_TIMEOUT_E BIT(23)
#define G1_REG_CONFIG_DEC_STRSWAP32_E BIT(22)
#define G1_REG_CONFIG_DEC_STRENDIAN_E BIT(21)
#define G1_REG_CONFIG_DEC_INSWAP32_E BIT(20)
#define G1_REG_CONFIG_DEC_OUTSWAP32_E BIT(19)
#define G1_REG_CONFIG_DEC_DATA_DISC_E BIT(18)
#define G1_REG_CONFIG_TILED_MODE_MSB BIT(17)
#define G1_REG_CONFIG_DEC_OUT_TILED_E BIT(17)
#define G1_REG_CONFIG_DEC_LATENCY(x) (((x) & 0x3f) << 11)
#define G1_REG_CONFIG_DEC_CLK_GATE_E BIT(10)
#define G1_REG_CONFIG_DEC_IN_ENDIAN BIT(9)
#define G1_REG_CONFIG_DEC_OUT_ENDIAN BIT(8)
#define G1_REG_CONFIG_PRIORITY_MODE(x) (((x) & 0x7) << 5)
#define G1_REG_CONFIG_TILED_MODE_LSB BIT(7)
#define G1_REG_CONFIG_DEC_ADV_PRE_DIS BIT(6)
#define G1_REG_CONFIG_DEC_SCMD_DIS BIT(5)
#define G1_REG_CONFIG_DEC_MAX_BURST(x) (((x) & 0x1f) << 0)
#define G1_REG_DEC_CTRL0 0x00c
#define G1_REG_DEC_CTRL0_DEC_MODE(x) (((x) & 0xf) << 28)
#define G1_REG_DEC_CTRL0_RLC_MODE_E BIT(27)
#define G1_REG_DEC_CTRL0_SKIP_MODE BIT(26)
#define G1_REG_DEC_CTRL0_DIVX3_E BIT(25)
#define G1_REG_DEC_CTRL0_PJPEG_E BIT(24)
#define G1_REG_DEC_CTRL0_PIC_INTERLACE_E BIT(23)
#define G1_REG_DEC_CTRL0_PIC_FIELDMODE_E BIT(22)
#define G1_REG_DEC_CTRL0_PIC_B_E BIT(21)
#define G1_REG_DEC_CTRL0_PIC_INTER_E BIT(20)
#define G1_REG_DEC_CTRL0_PIC_TOPFIELD_E BIT(19)
#define G1_REG_DEC_CTRL0_FWD_INTERLACE_E BIT(18)
#define G1_REG_DEC_CTRL0_SORENSON_E BIT(17)
#define G1_REG_DEC_CTRL0_REF_TOPFIELD_E BIT(16)
#define G1_REG_DEC_CTRL0_DEC_OUT_DIS BIT(15)
#define G1_REG_DEC_CTRL0_FILTERING_DIS BIT(14)
#define G1_REG_DEC_CTRL0_WEBP_E BIT(13)
#define G1_REG_DEC_CTRL0_MVC_E BIT(13)
#define G1_REG_DEC_CTRL0_PIC_FIXED_QUANT BIT(13)
#define G1_REG_DEC_CTRL0_WRITE_MVS_E BIT(12)
#define G1_REG_DEC_CTRL0_REFTOPFIRST_E BIT(11)
#define G1_REG_DEC_CTRL0_SEQ_MBAFF_E BIT(10)
#define G1_REG_DEC_CTRL0_PICORD_COUNT_E BIT(9)
#define G1_REG_DEC_CTRL0_DEC_AHB_HLOCK_E BIT(8)
#define G1_REG_DEC_CTRL0_DEC_AXI_WR_ID(x) (((x) & 0xff) << 0)
/* Setting AXI ID to 0xff to get auto generated ID to avoid possible conflicts */
#define G1_REG_DEC_CTRL0_DEC_AXI_AUTO G1_REG_DEC_CTRL0_DEC_AXI_WR_ID(0xff)
#define G1_REG_DEC_CTRL1 0x010
#define G1_REG_DEC_CTRL1_PIC_MB_WIDTH(x) (((x) & 0x1ff) << 23)
#define G1_REG_DEC_CTRL1_MB_WIDTH_OFF(x) (((x) & 0xf) << 19)
#define G1_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(x) (((x) & 0xff) << 11)
#define G1_REG_DEC_CTRL1_MB_HEIGHT_OFF(x) (((x) & 0xf) << 7)
#define G1_REG_DEC_CTRL1_ALT_SCAN_E BIT(6)
#define G1_REG_DEC_CTRL1_TOPFIELDFIRST_E BIT(5)
#define G1_REG_DEC_CTRL1_REF_FRAMES(x) (((x) & 0x1f) << 0)
#define G1_REG_DEC_CTRL1_PIC_MB_W_EXT(x) (((x) & 0x7) << 3)
#define G1_REG_DEC_CTRL1_PIC_MB_H_EXT(x) (((x) & 0x7) << 0)
#define G1_REG_DEC_CTRL1_PIC_REFER_FLAG BIT(0)
#define G1_REG_DEC_CTRL2 0x014
#define G1_REG_DEC_CTRL2_STRM_START_BIT(x) (((x) & 0x3f) << 26)
#define G1_REG_DEC_CTRL2_SYNC_MARKER_E BIT(25)
#define G1_REG_DEC_CTRL2_TYPE1_QUANT_E BIT(24)
#define G1_REG_DEC_CTRL2_CH_QP_OFFSET(x) (((x) & 0x1f) << 19)
#define G1_REG_DEC_CTRL2_CH_QP_OFFSET2(x) (((x) & 0x1f) << 14)
#define G1_REG_DEC_CTRL2_FIELDPIC_FLAG_E BIT(0)
#define G1_REG_DEC_CTRL2_INTRADC_VLC_THR(x) (((x) & 0x7) << 16)
#define G1_REG_DEC_CTRL2_VOP_TIME_INCR(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL2_DQ_PROFILE BIT(24)
#define G1_REG_DEC_CTRL2_DQBI_LEVEL BIT(23)
#define G1_REG_DEC_CTRL2_RANGE_RED_FRM_E BIT(22)
#define G1_REG_DEC_CTRL2_FAST_UVMC_E BIT(20)
#define G1_REG_DEC_CTRL2_TRANSDCTAB BIT(17)
#define G1_REG_DEC_CTRL2_TRANSACFRM(x) (((x) & 0x3) << 15)
#define G1_REG_DEC_CTRL2_TRANSACFRM2(x) (((x) & 0x3) << 13)
#define G1_REG_DEC_CTRL2_MB_MODE_TAB(x) (((x) & 0x7) << 10)
#define G1_REG_DEC_CTRL2_MVTAB(x) (((x) & 0x7) << 7)
#define G1_REG_DEC_CTRL2_CBPTAB(x) (((x) & 0x7) << 4)
#define G1_REG_DEC_CTRL2_2MV_BLK_PAT_TAB(x) (((x) & 0x3) << 2)
#define G1_REG_DEC_CTRL2_4MV_BLK_PAT_TAB(x) (((x) & 0x3) << 0)
#define G1_REG_DEC_CTRL2_QSCALE_TYPE BIT(24)
#define G1_REG_DEC_CTRL2_CON_MV_E BIT(4)
#define G1_REG_DEC_CTRL2_INTRA_DC_PREC(x) (((x) & 0x3) << 2)
#define G1_REG_DEC_CTRL2_INTRA_VLC_TAB BIT(1)
#define G1_REG_DEC_CTRL2_FRAME_PRED_DCT BIT(0)
#define G1_REG_DEC_CTRL2_JPEG_QTABLES(x) (((x) & 0x3) << 11)
#define G1_REG_DEC_CTRL2_JPEG_MODE(x) (((x) & 0x7) << 8)
#define G1_REG_DEC_CTRL2_JPEG_FILRIGHT_E BIT(7)
#define G1_REG_DEC_CTRL2_JPEG_STREAM_ALL BIT(6)
#define G1_REG_DEC_CTRL2_CR_AC_VLCTABLE BIT(5)
#define G1_REG_DEC_CTRL2_CB_AC_VLCTABLE BIT(4)
#define G1_REG_DEC_CTRL2_CR_DC_VLCTABLE BIT(3)
#define G1_REG_DEC_CTRL2_CB_DC_VLCTABLE BIT(2)
#define G1_REG_DEC_CTRL2_CR_DC_VLCTABLE3 BIT(1)
#define G1_REG_DEC_CTRL2_CB_DC_VLCTABLE3 BIT(0)
#define G1_REG_DEC_CTRL2_STRM1_START_BIT(x) (((x) & 0x3f) << 18)
#define G1_REG_DEC_CTRL2_HUFFMAN_E BIT(17)
#define G1_REG_DEC_CTRL2_MULTISTREAM_E BIT(16)
#define G1_REG_DEC_CTRL2_BOOLEAN_VALUE(x) (((x) & 0xff) << 8)
#define G1_REG_DEC_CTRL2_BOOLEAN_RANGE(x) (((x) & 0xff) << 0)
#define G1_REG_DEC_CTRL2_ALPHA_OFFSET(x) (((x) & 0x1f) << 5)
#define G1_REG_DEC_CTRL2_BETA_OFFSET(x) (((x) & 0x1f) << 0)
#define G1_REG_DEC_CTRL3 0x018
#define G1_REG_DEC_CTRL3_START_CODE_E BIT(31)
#define G1_REG_DEC_CTRL3_INIT_QP(x) (((x) & 0x3f) << 25)
#define G1_REG_DEC_CTRL3_CH_8PIX_ILEAV_E BIT(24)
#define G1_REG_DEC_CTRL3_STREAM_LEN_EXT(x) (((x) & 0xff) << 24)
#define G1_REG_DEC_CTRL3_STREAM_LEN(x) (((x) & 0xffffff) << 0)
#define G1_REG_DEC_CTRL4 0x01c
#define G1_REG_DEC_CTRL4_CABAC_E BIT(31)
#define G1_REG_DEC_CTRL4_BLACKWHITE_E BIT(30)
#define G1_REG_DEC_CTRL4_DIR_8X8_INFER_E BIT(29)
#define G1_REG_DEC_CTRL4_WEIGHT_PRED_E BIT(28)
#define G1_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(x) (((x) & 0x3) << 26)
#define G1_REG_DEC_CTRL4_AVS_H264_H_EXT BIT(25)
#define G1_REG_DEC_CTRL4_FRAMENUM_LEN(x) (((x) & 0x1f) << 16)
#define G1_REG_DEC_CTRL4_FRAMENUM(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL4_BITPLANE0_E BIT(31)
#define G1_REG_DEC_CTRL4_BITPLANE1_E BIT(30)
#define G1_REG_DEC_CTRL4_BITPLANE2_E BIT(29)
#define G1_REG_DEC_CTRL4_ALT_PQUANT(x) (((x) & 0x1f) << 24)
#define G1_REG_DEC_CTRL4_DQ_EDGES(x) (((x) & 0xf) << 20)
#define G1_REG_DEC_CTRL4_TTMBF BIT(19)
#define G1_REG_DEC_CTRL4_PQINDEX(x) (((x) & 0x1f) << 14)
#define G1_REG_DEC_CTRL4_VC1_HEIGHT_EXT BIT(13)
#define G1_REG_DEC_CTRL4_BILIN_MC_E BIT(12)
#define G1_REG_DEC_CTRL4_UNIQP_E BIT(11)
#define G1_REG_DEC_CTRL4_HALFQP_E BIT(10)
#define G1_REG_DEC_CTRL4_TTFRM(x) (((x) & 0x3) << 8)
#define G1_REG_DEC_CTRL4_2ND_BYTE_EMUL_E BIT(7)
#define G1_REG_DEC_CTRL4_DQUANT_E BIT(6)
#define G1_REG_DEC_CTRL4_VC1_ADV_E BIT(5)
#define G1_REG_DEC_CTRL4_PJPEG_FILDOWN_E BIT(26)
#define G1_REG_DEC_CTRL4_PJPEG_WDIV8 BIT(25)
#define G1_REG_DEC_CTRL4_PJPEG_HDIV8 BIT(24)
#define G1_REG_DEC_CTRL4_PJPEG_AH(x) (((x) & 0xf) << 20)
#define G1_REG_DEC_CTRL4_PJPEG_AL(x) (((x) & 0xf) << 16)
#define G1_REG_DEC_CTRL4_PJPEG_SS(x) (((x) & 0xff) << 8)
#define G1_REG_DEC_CTRL4_PJPEG_SE(x) (((x) & 0xff) << 0)
#define G1_REG_DEC_CTRL4_DCT1_START_BIT(x) (((x) & 0x3f) << 26)
#define G1_REG_DEC_CTRL4_DCT2_START_BIT(x) (((x) & 0x3f) << 20)
#define G1_REG_DEC_CTRL4_CH_MV_RES BIT(13)
#define G1_REG_DEC_CTRL4_INIT_DC_MATCH0(x) (((x) & 0x7) << 9)
#define G1_REG_DEC_CTRL4_INIT_DC_MATCH1(x) (((x) & 0x7) << 6)
#define G1_REG_DEC_CTRL4_VP7_VERSION BIT(5)
#define G1_REG_DEC_CTRL5 0x020
#define G1_REG_DEC_CTRL5_CONST_INTRA_E BIT(31)
#define G1_REG_DEC_CTRL5_FILT_CTRL_PRES BIT(30)
#define G1_REG_DEC_CTRL5_RDPIC_CNT_PRES BIT(29)
#define G1_REG_DEC_CTRL5_8X8TRANS_FLAG_E BIT(28)
#define G1_REG_DEC_CTRL5_REFPIC_MK_LEN(x) (((x) & 0x7ff) << 17)
#define G1_REG_DEC_CTRL5_IDR_PIC_E BIT(16)
#define G1_REG_DEC_CTRL5_IDR_PIC_ID(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL5_MV_SCALEFACTOR(x) (((x) & 0xff) << 24)
#define G1_REG_DEC_CTRL5_REF_DIST_FWD(x) (((x) & 0x1f) << 19)
#define G1_REG_DEC_CTRL5_REF_DIST_BWD(x) (((x) & 0x1f) << 14)
#define G1_REG_DEC_CTRL5_LOOP_FILT_LIMIT(x) (((x) & 0xf) << 14)
#define G1_REG_DEC_CTRL5_VARIANCE_TEST_E BIT(13)
#define G1_REG_DEC_CTRL5_MV_THRESHOLD(x) (((x) & 0x7) << 10)
#define G1_REG_DEC_CTRL5_VAR_THRESHOLD(x) (((x) & 0x3ff) << 0)
#define G1_REG_DEC_CTRL5_DIVX_IDCT_E BIT(8)
#define G1_REG_DEC_CTRL5_DIVX3_SLICE_SIZE(x) (((x) & 0xff) << 0)
#define G1_REG_DEC_CTRL5_PJPEG_REST_FREQ(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL5_RV_PROFILE(x) (((x) & 0x3) << 30)
#define G1_REG_DEC_CTRL5_RV_OSV_QUANT(x) (((x) & 0x3) << 28)
#define G1_REG_DEC_CTRL5_RV_FWD_SCALE(x) (((x) & 0x3fff) << 14)
#define G1_REG_DEC_CTRL5_RV_BWD_SCALE(x) (((x) & 0x3fff) << 0)
#define G1_REG_DEC_CTRL5_INIT_DC_COMP0(x) (((x) & 0xffff) << 16)
#define G1_REG_DEC_CTRL5_INIT_DC_COMP1(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL6 0x024
#define G1_REG_DEC_CTRL6_PPS_ID(x) (((x) & 0xff) << 24)
#define G1_REG_DEC_CTRL6_REFIDX1_ACTIVE(x) (((x) & 0x1f) << 19)
#define G1_REG_DEC_CTRL6_REFIDX0_ACTIVE(x) (((x) & 0x1f) << 14)
#define G1_REG_DEC_CTRL6_POC_LENGTH(x) (((x) & 0xff) << 0)
#define G1_REG_DEC_CTRL6_ICOMP0_E BIT(24)
#define G1_REG_DEC_CTRL6_ISCALE0(x) (((x) & 0xff) << 16)
#define G1_REG_DEC_CTRL6_ISHIFT0(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL6_STREAM1_LEN(x) (((x) & 0xffffff) << 0)
#define G1_REG_DEC_CTRL6_PIC_SLICE_AM(x) (((x) & 0x1fff) << 0)
#define G1_REG_DEC_CTRL6_COEFFS_PART_AM(x) (((x) & 0xf) << 24)
#define G1_REG_FWD_PIC(i) (0x028 + ((i) * 0x4))
#define G1_REG_FWD_PIC_PINIT_RLIST_F5(x) (((x) & 0x1f) << 25)
#define G1_REG_FWD_PIC_PINIT_RLIST_F4(x) (((x) & 0x1f) << 20)
#define G1_REG_FWD_PIC_PINIT_RLIST_F3(x) (((x) & 0x1f) << 15)
#define G1_REG_FWD_PIC_PINIT_RLIST_F2(x) (((x) & 0x1f) << 10)
#define G1_REG_FWD_PIC_PINIT_RLIST_F1(x) (((x) & 0x1f) << 5)
#define G1_REG_FWD_PIC_PINIT_RLIST_F0(x) (((x) & 0x1f) << 0)
#define G1_REG_FWD_PIC1_ICOMP1_E BIT(24)
#define G1_REG_FWD_PIC1_ISCALE1(x) (((x) & 0xff) << 16)
#define G1_REG_FWD_PIC1_ISHIFT1(x) (((x) & 0xffff) << 0)
#define G1_REG_FWD_PIC1_SEGMENT_BASE(x) ((x) << 0)
#define G1_REG_FWD_PIC1_SEGMENT_UPD_E BIT(1)
#define G1_REG_FWD_PIC1_SEGMENT_E BIT(0)
#define G1_REG_DEC_CTRL7 0x02c
#define G1_REG_DEC_CTRL7_PINIT_RLIST_F15(x) (((x) & 0x1f) << 25)
#define G1_REG_DEC_CTRL7_PINIT_RLIST_F14(x) (((x) & 0x1f) << 20)
#define G1_REG_DEC_CTRL7_PINIT_RLIST_F13(x) (((x) & 0x1f) << 15)
#define G1_REG_DEC_CTRL7_PINIT_RLIST_F12(x) (((x) & 0x1f) << 10)
#define G1_REG_DEC_CTRL7_PINIT_RLIST_F11(x) (((x) & 0x1f) << 5)
#define G1_REG_DEC_CTRL7_PINIT_RLIST_F10(x) (((x) & 0x1f) << 0)
#define G1_REG_DEC_CTRL7_ICOMP2_E BIT(24)
#define G1_REG_DEC_CTRL7_ISCALE2(x) (((x) & 0xff) << 16)
#define G1_REG_DEC_CTRL7_ISHIFT2(x) (((x) & 0xffff) << 0)
#define G1_REG_DEC_CTRL7_DCT3_START_BIT(x) (((x) & 0x3f) << 24)
#define G1_REG_DEC_CTRL7_DCT4_START_BIT(x) (((x) & 0x3f) << 18)
#define G1_REG_DEC_CTRL7_DCT5_START_BIT(x) (((x) & 0x3f) << 12)
#define G1_REG_DEC_CTRL7_DCT6_START_BIT(x) (((x) & 0x3f) << 6)
#define G1_REG_DEC_CTRL7_DCT7_START_BIT(x) (((x) & 0x3f) << 0)
#define G1_REG_ADDR_STR 0x030
#define G1_REG_ADDR_DST 0x034
#define G1_REG_ADDR_REF(i) (0x038 + ((i) * 0x4))
#define G1_REG_ADDR_REF_FIELD_E BIT(1)
#define G1_REG_ADDR_REF_TOPC_E BIT(0)
#define G1_REG_REF_PIC(i) (0x078 + ((i) * 0x4))
#define G1_REG_REF_PIC_FILT_TYPE_E BIT(31)
#define G1_REG_REF_PIC_FILT_SHARPNESS(x) (((x) & 0x7) << 28)
#define G1_REG_REF_PIC_MB_ADJ_0(x) (((x) & 0x7f) << 21)
#define G1_REG_REF_PIC_MB_ADJ_1(x) (((x) & 0x7f) << 14)
#define G1_REG_REF_PIC_MB_ADJ_2(x) (((x) & 0x7f) << 7)
#define G1_REG_REF_PIC_MB_ADJ_3(x) (((x) & 0x7f) << 0)
#define G1_REG_REF_PIC_REFER1_NBR(x) (((x) & 0xffff) << 16)
#define G1_REG_REF_PIC_REFER0_NBR(x) (((x) & 0xffff) << 0)
#define G1_REG_REF_PIC_LF_LEVEL_0(x) (((x) & 0x3f) << 18)
#define G1_REG_REF_PIC_LF_LEVEL_1(x) (((x) & 0x3f) << 12)
#define G1_REG_REF_PIC_LF_LEVEL_2(x) (((x) & 0x3f) << 6)
#define G1_REG_REF_PIC_LF_LEVEL_3(x) (((x) & 0x3f) << 0)
#define G1_REG_REF_PIC_QUANT_DELTA_0(x) (((x) & 0x1f) << 27)
#define G1_REG_REF_PIC_QUANT_DELTA_1(x) (((x) & 0x1f) << 22)
#define G1_REG_REF_PIC_QUANT_0(x) (((x) & 0x7ff) << 11)
#define G1_REG_REF_PIC_QUANT_1(x) (((x) & 0x7ff) << 0)
#define G1_REG_LT_REF 0x098
#define G1_REG_VALID_REF 0x09c
#define G1_REG_ADDR_QTABLE 0x0a0
#define G1_REG_ADDR_DIR_MV 0x0a4
#define G1_REG_BD_REF_PIC(i) (0x0a8 + ((i) * 0x4))
#define G1_REG_BD_REF_PIC_BINIT_RLIST_B2(x) (((x) & 0x1f) << 25)
#define G1_REG_BD_REF_PIC_BINIT_RLIST_F2(x) (((x) & 0x1f) << 20)
#define G1_REG_BD_REF_PIC_BINIT_RLIST_B1(x) (((x) & 0x1f) << 15)
#define G1_REG_BD_REF_PIC_BINIT_RLIST_F1(x) (((x) & 0x1f) << 10)
#define G1_REG_BD_REF_PIC_BINIT_RLIST_B0(x) (((x) & 0x1f) << 5)
#define G1_REG_BD_REF_PIC_BINIT_RLIST_F0(x) (((x) & 0x1f) << 0)
#define G1_REG_BD_REF_PIC_PRED_TAP_2_M1(x) (((x) & 0x3) << 10)
#define G1_REG_BD_REF_PIC_PRED_TAP_2_4(x) (((x) & 0x3) << 8)
#define G1_REG_BD_REF_PIC_PRED_TAP_4_M1(x) (((x) & 0x3) << 6)
#define G1_REG_BD_REF_PIC_PRED_TAP_4_4(x) (((x) & 0x3) << 4)
#define G1_REG_BD_REF_PIC_PRED_TAP_6_M1(x) (((x) & 0x3) << 2)
#define G1_REG_BD_REF_PIC_PRED_TAP_6_4(x) (((x) & 0x3) << 0)
#define G1_REG_BD_REF_PIC_QUANT_DELTA_2(x) (((x) & 0x1f) << 27)
#define G1_REG_BD_REF_PIC_QUANT_DELTA_3(x) (((x) & 0x1f) << 22)
#define G1_REG_BD_REF_PIC_QUANT_2(x) (((x) & 0x7ff) << 11)
#define G1_REG_BD_REF_PIC_QUANT_3(x) (((x) & 0x7ff) << 0)
#define G1_REG_BD_P_REF_PIC 0x0bc
#define G1_REG_BD_P_REF_PIC_QUANT_DELTA_4(x) (((x) & 0x1f) << 27)
#define G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(x) (((x) & 0x1f) << 25)
#define G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(x) (((x) & 0x1f) << 20)
#define G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(x) (((x) & 0x1f) << 15)
#define G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(x) (((x) & 0x1f) << 10)
#define G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(x) (((x) & 0x1f) << 5)
#define G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(x) (((x) & 0x1f) << 0)
#define G1_REG_ERR_CONC 0x0c0
#define G1_REG_ERR_CONC_STARTMB_X(x) (((x) & 0x1ff) << 23)
#define G1_REG_ERR_CONC_STARTMB_Y(x) (((x) & 0xff) << 15)
#define G1_REG_PRED_FLT 0x0c4
#define G1_REG_PRED_FLT_PRED_BC_TAP_0_0(x) (((x) & 0x3ff) << 22)
#define G1_REG_PRED_FLT_PRED_BC_TAP_0_1(x) (((x) & 0x3ff) << 12)
#define G1_REG_PRED_FLT_PRED_BC_TAP_0_2(x) (((x) & 0x3ff) << 2)
#define G1_REG_REF_BUF_CTRL 0x0cc
#define G1_REG_REF_BUF_CTRL_REFBU_E BIT(31)
#define G1_REG_REF_BUF_CTRL_REFBU_THR(x) (((x) & 0xfff) << 19)
#define G1_REG_REF_BUF_CTRL_REFBU_PICID(x) (((x) & 0x1f) << 14)
#define G1_REG_REF_BUF_CTRL_REFBU_EVAL_E BIT(13)
#define G1_REG_REF_BUF_CTRL_REFBU_FPARMOD_E BIT(12)
#define G1_REG_REF_BUF_CTRL_REFBU_Y_OFFSET(x) (((x) & 0x1ff) << 0)
#define G1_REG_REF_BUF_CTRL2 0x0dc
#define G1_REG_REF_BUF_CTRL2_REFBU2_BUF_E BIT(31)
#define G1_REG_REF_BUF_CTRL2_REFBU2_THR(x) (((x) & 0xfff) << 19)
#define G1_REG_REF_BUF_CTRL2_REFBU2_PICID(x) (((x) & 0x1f) << 14)
#define G1_REG_REF_BUF_CTRL2_APF_THRESHOLD(x) (((x) & 0x3fff) << 0)
#define G1_REG_SOFT_RESET 0x194
/* Post-processor registers. */
#define G1_REG_PP_INTERRUPT G1_SWREG(60)
#define G1_REG_PP_READY_IRQ BIT(12)
#define G1_REG_PP_IRQ BIT(8)
#define G1_REG_PP_IRQ_DIS BIT(4)
#define G1_REG_PP_PIPELINE_EN BIT(1)
#define G1_REG_PP_EXTERNAL_TRIGGER BIT(0)
#define G1_REG_PP_DEV_CONFIG G1_SWREG(61)
#define G1_REG_PP_AXI_RD_ID(v) (((v) << 24) & GENMASK(31, 24))
#define G1_REG_PP_AXI_WR_ID(v) (((v) << 16) & GENMASK(23, 16))
#define G1_REG_PP_INSWAP32_E(v) ((v) ? BIT(10) : 0)
#define G1_REG_PP_DATA_DISC_E(v) ((v) ? BIT(9) : 0)
#define G1_REG_PP_CLK_GATE_E(v) ((v) ? BIT(8) : 0)
#define G1_REG_PP_IN_ENDIAN(v) ((v) ? BIT(7) : 0)
#define G1_REG_PP_OUT_ENDIAN(v) ((v) ? BIT(6) : 0)
#define G1_REG_PP_OUTSWAP32_E(v) ((v) ? BIT(5) : 0)
#define G1_REG_PP_MAX_BURST(v) (((v) << 0) & GENMASK(4, 0))
#define G1_REG_PP_IN_LUMA_BASE G1_SWREG(63)
#define G1_REG_PP_IN_CB_BASE G1_SWREG(64)
#define G1_REG_PP_IN_CR_BASE G1_SWREG(65)
#define G1_REG_PP_OUT_LUMA_BASE G1_SWREG(66)
#define G1_REG_PP_OUT_CHROMA_BASE G1_SWREG(67)
#define G1_REG_PP_CONTRAST_ADJUST G1_SWREG(68)
#define G1_REG_PP_COLOR_CONVERSION G1_SWREG(69)
#define G1_REG_PP_COLOR_CONVERSION0 G1_SWREG(70)
#define G1_REG_PP_COLOR_CONVERSION1 G1_SWREG(71)
#define G1_REG_PP_INPUT_SIZE G1_SWREG(72)
#define G1_REG_PP_INPUT_SIZE_HEIGHT(v) (((v) << 9) & GENMASK(16, 9))
#define G1_REG_PP_INPUT_SIZE_WIDTH(v) (((v) << 0) & GENMASK(8, 0))
#define G1_REG_PP_SCALING0 G1_SWREG(79)
#define G1_REG_PP_PADD_R(v) (((v) << 23) & GENMASK(27, 23))
#define G1_REG_PP_PADD_G(v) (((v) << 18) & GENMASK(22, 18))
#define G1_REG_PP_RANGEMAP_Y(v) ((v) ? BIT(31) : 0)
#define G1_REG_PP_RANGEMAP_C(v) ((v) ? BIT(30) : 0)
#define G1_REG_PP_YCBCR_RANGE(v) ((v) ? BIT(29) : 0)
#define G1_REG_PP_RGB_16(v) ((v) ? BIT(28) : 0)
#define G1_REG_PP_SCALING1 G1_SWREG(80)
#define G1_REG_PP_PADD_B(v) (((v) << 18) & GENMASK(22, 18))
#define G1_REG_PP_MASK_R G1_SWREG(82)
#define G1_REG_PP_MASK_G G1_SWREG(83)
#define G1_REG_PP_MASK_B G1_SWREG(84)
#define G1_REG_PP_CONTROL G1_SWREG(85)
#define G1_REG_PP_CONTROL_IN_FMT(v) (((v) << 29) & GENMASK(31, 29))
#define G1_REG_PP_CONTROL_OUT_FMT(v) (((v) << 26) & GENMASK(28, 26))
#define G1_REG_PP_CONTROL_OUT_HEIGHT(v) (((v) << 15) & GENMASK(25, 15))
#define G1_REG_PP_CONTROL_OUT_WIDTH(v) (((v) << 4) & GENMASK(14, 4))
#define G1_REG_PP_MASK1_ORIG_WIDTH G1_SWREG(88)
#define G1_REG_PP_ORIG_WIDTH(v) (((v) << 23) & GENMASK(31, 23))
#define G1_REG_PP_DISPLAY_WIDTH_IN_EXT G1_SWREG(92)
#define G1_REG_PP_FUSE G1_SWREG(99)
#endif /* HANTRO_G1_REGS_H_ */
@@ -0,0 +1,511 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VP8 codec driver
*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
* ZhiChao Yu <zhichao.yu@rock-chips.com>
*
* Copyright (C) 2019 Google, Inc.
* Tomasz Figa <tfiga@chromium.org>
*/
#include <media/v4l2-mem2mem.h>
#include "hantro_hw.h"
#include "hantro.h"
#include "hantro_g1_regs.h"
/* DCT partition base address regs */
static const struct hantro_reg vp8_dec_dct_base[8] = {
{ G1_REG_ADDR_STR, 0, 0xffffffff },
{ G1_REG_ADDR_REF(8), 0, 0xffffffff },
{ G1_REG_ADDR_REF(9), 0, 0xffffffff },
{ G1_REG_ADDR_REF(10), 0, 0xffffffff },
{ G1_REG_ADDR_REF(11), 0, 0xffffffff },
{ G1_REG_ADDR_REF(12), 0, 0xffffffff },
{ G1_REG_ADDR_REF(14), 0, 0xffffffff },
{ G1_REG_ADDR_REF(15), 0, 0xffffffff },
};
/* Loop filter level regs */
static const struct hantro_reg vp8_dec_lf_level[4] = {
{ G1_REG_REF_PIC(2), 18, 0x3f },
{ G1_REG_REF_PIC(2), 12, 0x3f },
{ G1_REG_REF_PIC(2), 6, 0x3f },
{ G1_REG_REF_PIC(2), 0, 0x3f },
};
/* Macroblock loop filter level adjustment regs */
static const struct hantro_reg vp8_dec_mb_adj[4] = {
{ G1_REG_REF_PIC(0), 21, 0x7f },
{ G1_REG_REF_PIC(0), 14, 0x7f },
{ G1_REG_REF_PIC(0), 7, 0x7f },
{ G1_REG_REF_PIC(0), 0, 0x7f },
};
/* Reference frame adjustment regs */
static const struct hantro_reg vp8_dec_ref_adj[4] = {
{ G1_REG_REF_PIC(1), 21, 0x7f },
{ G1_REG_REF_PIC(1), 14, 0x7f },
{ G1_REG_REF_PIC(1), 7, 0x7f },
{ G1_REG_REF_PIC(1), 0, 0x7f },
};
/* Quantizer */
static const struct hantro_reg vp8_dec_quant[4] = {
{ G1_REG_REF_PIC(3), 11, 0x7ff },
{ G1_REG_REF_PIC(3), 0, 0x7ff },
{ G1_REG_BD_REF_PIC(4), 11, 0x7ff },
{ G1_REG_BD_REF_PIC(4), 0, 0x7ff },
};
/* Quantizer delta regs */
static const struct hantro_reg vp8_dec_quant_delta[5] = {
{ G1_REG_REF_PIC(3), 27, 0x1f },
{ G1_REG_REF_PIC(3), 22, 0x1f },
{ G1_REG_BD_REF_PIC(4), 27, 0x1f },
{ G1_REG_BD_REF_PIC(4), 22, 0x1f },
{ G1_REG_BD_P_REF_PIC, 27, 0x1f },
};
/* DCT partition start bits regs */
static const struct hantro_reg vp8_dec_dct_start_bits[8] = {
{ G1_REG_DEC_CTRL2, 26, 0x3f }, { G1_REG_DEC_CTRL4, 26, 0x3f },
{ G1_REG_DEC_CTRL4, 20, 0x3f }, { G1_REG_DEC_CTRL7, 24, 0x3f },
{ G1_REG_DEC_CTRL7, 18, 0x3f }, { G1_REG_DEC_CTRL7, 12, 0x3f },
{ G1_REG_DEC_CTRL7, 6, 0x3f }, { G1_REG_DEC_CTRL7, 0, 0x3f },
};
/* Precision filter tap regs */
static const struct hantro_reg vp8_dec_pred_bc_tap[8][4] = {
{
{ G1_REG_PRED_FLT, 22, 0x3ff },
{ G1_REG_PRED_FLT, 12, 0x3ff },
{ G1_REG_PRED_FLT, 2, 0x3ff },
{ G1_REG_REF_PIC(4), 22, 0x3ff },
},
{
{ G1_REG_REF_PIC(4), 12, 0x3ff },
{ G1_REG_REF_PIC(4), 2, 0x3ff },
{ G1_REG_REF_PIC(5), 22, 0x3ff },
{ G1_REG_REF_PIC(5), 12, 0x3ff },
},
{
{ G1_REG_REF_PIC(5), 2, 0x3ff },
{ G1_REG_REF_PIC(6), 22, 0x3ff },
{ G1_REG_REF_PIC(6), 12, 0x3ff },
{ G1_REG_REF_PIC(6), 2, 0x3ff },
},
{
{ G1_REG_REF_PIC(7), 22, 0x3ff },
{ G1_REG_REF_PIC(7), 12, 0x3ff },
{ G1_REG_REF_PIC(7), 2, 0x3ff },
{ G1_REG_LT_REF, 22, 0x3ff },
},
{
{ G1_REG_LT_REF, 12, 0x3ff },
{ G1_REG_LT_REF, 2, 0x3ff },
{ G1_REG_VALID_REF, 22, 0x3ff },
{ G1_REG_VALID_REF, 12, 0x3ff },
},
{
{ G1_REG_VALID_REF, 2, 0x3ff },
{ G1_REG_BD_REF_PIC(0), 22, 0x3ff },
{ G1_REG_BD_REF_PIC(0), 12, 0x3ff },
{ G1_REG_BD_REF_PIC(0), 2, 0x3ff },
},
{
{ G1_REG_BD_REF_PIC(1), 22, 0x3ff },
{ G1_REG_BD_REF_PIC(1), 12, 0x3ff },
{ G1_REG_BD_REF_PIC(1), 2, 0x3ff },
{ G1_REG_BD_REF_PIC(2), 22, 0x3ff },
},
{
{ G1_REG_BD_REF_PIC(2), 12, 0x3ff },
{ G1_REG_BD_REF_PIC(2), 2, 0x3ff },
{ G1_REG_BD_REF_PIC(3), 22, 0x3ff },
{ G1_REG_BD_REF_PIC(3), 12, 0x3ff },
},
};
/*
* Set loop filters
*/
static void cfg_lf(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
const struct v4l2_vp8_segment *seg = &hdr->segment;
const struct v4l2_vp8_loop_filter *lf = &hdr->lf;
struct hantro_dev *vpu = ctx->dev;
unsigned int i;
u32 reg;
if (!(seg->flags & V4L2_VP8_SEGMENT_FLAG_ENABLED)) {
hantro_reg_write(vpu, &vp8_dec_lf_level[0], lf->level);
} else if (seg->flags & V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE) {
for (i = 0; i < 4; i++) {
u32 lf_level = clamp(lf->level + seg->lf_update[i],
0, 63);
hantro_reg_write(vpu, &vp8_dec_lf_level[i], lf_level);
}
} else {
for (i = 0; i < 4; i++)
hantro_reg_write(vpu, &vp8_dec_lf_level[i],
seg->lf_update[i]);
}
reg = G1_REG_REF_PIC_FILT_SHARPNESS(lf->sharpness_level);
if (lf->flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE)
reg |= G1_REG_REF_PIC_FILT_TYPE_E;
vdpu_write_relaxed(vpu, reg, G1_REG_REF_PIC(0));
if (lf->flags & V4L2_VP8_LF_ADJ_ENABLE) {
for (i = 0; i < 4; i++) {
hantro_reg_write(vpu, &vp8_dec_mb_adj[i],
lf->mb_mode_delta[i]);
hantro_reg_write(vpu, &vp8_dec_ref_adj[i],
lf->ref_frm_delta[i]);
}
}
}
/*
* Set quantization parameters
*/
static void cfg_qp(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
const struct v4l2_vp8_quantization *q = &hdr->quant;
const struct v4l2_vp8_segment *seg = &hdr->segment;
struct hantro_dev *vpu = ctx->dev;
unsigned int i;
if (!(seg->flags & V4L2_VP8_SEGMENT_FLAG_ENABLED)) {
hantro_reg_write(vpu, &vp8_dec_quant[0], q->y_ac_qi);
} else if (seg->flags & V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE) {
for (i = 0; i < 4; i++) {
u32 quant = clamp(q->y_ac_qi + seg->quant_update[i],
0, 127);
hantro_reg_write(vpu, &vp8_dec_quant[i], quant);
}
} else {
for (i = 0; i < 4; i++)
hantro_reg_write(vpu, &vp8_dec_quant[i],
seg->quant_update[i]);
}
hantro_reg_write(vpu, &vp8_dec_quant_delta[0], q->y_dc_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[1], q->y2_dc_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[2], q->y2_ac_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[3], q->uv_dc_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[4], q->uv_ac_delta);
}
/*
* set control partition and DCT partition regs
*
* VP8 frame stream data layout:
*
* first_part_size parttion_sizes[0]
* ^ ^
* src_dma | |
* ^ +--------+------+ +-----+-----+
* | | control part | | |
* +--------+----------------+------------------+-----------+-----+-----------+
* | tag 3B | extra 7B | hdr | mb_data | DCT sz | DCT part0 | ... | DCT partn |
* +--------+-----------------------------------+-----------+-----+-----------+
* | | | |
* v +----+---+ v
* mb_start | src_dma_end
* v
* DCT size part
* (num_dct-1)*3B
* Note:
* 1. only key-frames have extra 7-bytes
* 2. all offsets are base on src_dma
* 3. number of DCT parts is 1, 2, 4 or 8
* 4. the addresses set to the VPU must be 64-bits aligned
*/
static void cfg_parts(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *vb2_src;
u32 first_part_offset = V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) ? 10 : 3;
u32 mb_size, mb_offset_bytes, mb_offset_bits, mb_start_bits;
u32 dct_size_part_size, dct_part_offset;
struct hantro_reg reg;
dma_addr_t src_dma;
u32 dct_part_total_len = 0;
u32 count = 0;
unsigned int i;
vb2_src = hantro_get_src_buf(ctx);
src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0);
/*
* Calculate control partition mb data info
* @first_part_header_bits: bits offset of mb data from first
* part start pos
* @mb_offset_bits: bits offset of mb data from src_dma
* base addr
* @mb_offset_byte: bytes offset of mb data from src_dma
* base addr
* @mb_start_bits: bits offset of mb data from mb data
* 64bits alignment addr
*/
mb_offset_bits = first_part_offset * 8 +
hdr->first_part_header_bits + 8;
mb_offset_bytes = mb_offset_bits / 8;
mb_start_bits = mb_offset_bits -
(mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) * 8;
mb_size = hdr->first_part_size -
(mb_offset_bytes - first_part_offset) +
(mb_offset_bytes & DEC_8190_ALIGN_MASK);
/* Macroblock data aligned base addr */
vdpu_write_relaxed(vpu, (mb_offset_bytes & (~DEC_8190_ALIGN_MASK))
+ src_dma, G1_REG_ADDR_REF(13));
/* Macroblock data start bits */
reg.base = G1_REG_DEC_CTRL2;
reg.mask = 0x3f;
reg.shift = 18;
hantro_reg_write(vpu, &reg, mb_start_bits);
/* Macroblock aligned data length */
reg.base = G1_REG_DEC_CTRL6;
reg.mask = 0x3fffff;
reg.shift = 0;
hantro_reg_write(vpu, &reg, mb_size + 1);
/*
* Calculate DCT partition info
* @dct_size_part_size: Containing sizes of DCT part, every DCT part
* has 3 bytes to store its size, except the last
* DCT part
* @dct_part_offset: bytes offset of DCT parts from src_dma base addr
* @dct_part_total_len: total size of all DCT parts
*/
dct_size_part_size = (hdr->num_dct_parts - 1) * 3;
dct_part_offset = first_part_offset + hdr->first_part_size;
for (i = 0; i < hdr->num_dct_parts; i++)
dct_part_total_len += hdr->dct_part_sizes[i];
dct_part_total_len += dct_size_part_size;
dct_part_total_len += (dct_part_offset & DEC_8190_ALIGN_MASK);
/* Number of DCT partitions */
reg.base = G1_REG_DEC_CTRL6;
reg.mask = 0xf;
reg.shift = 24;
hantro_reg_write(vpu, &reg, hdr->num_dct_parts - 1);
/* DCT partition length */
vdpu_write_relaxed(vpu,
G1_REG_DEC_CTRL3_STREAM_LEN(dct_part_total_len),
G1_REG_DEC_CTRL3);
/* DCT partitions base address */
for (i = 0; i < hdr->num_dct_parts; i++) {
u32 byte_offset = dct_part_offset + dct_size_part_size + count;
u32 base_addr = byte_offset + src_dma;
hantro_reg_write(vpu, &vp8_dec_dct_base[i],
base_addr & (~DEC_8190_ALIGN_MASK));
hantro_reg_write(vpu, &vp8_dec_dct_start_bits[i],
(byte_offset & DEC_8190_ALIGN_MASK) * 8);
count += hdr->dct_part_sizes[i];
}
}
/*
* prediction filter taps
* normal 6-tap filters
*/
static void cfg_tap(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_reg reg;
u32 val = 0;
int i, j;
reg.base = G1_REG_BD_REF_PIC(3);
reg.mask = 0xf;
if ((hdr->version & 0x03) != 0)
return; /* Tap filter not used. */
for (i = 0; i < 8; i++) {
val = (hantro_vp8_dec_mc_filter[i][0] << 2) |
hantro_vp8_dec_mc_filter[i][5];
for (j = 0; j < 4; j++)
hantro_reg_write(vpu, &vp8_dec_pred_bc_tap[i][j],
hantro_vp8_dec_mc_filter[i][j + 1]);
switch (i) {
case 2:
reg.shift = 8;
break;
case 4:
reg.shift = 4;
break;
case 6:
reg.shift = 0;
break;
default:
continue;
}
hantro_reg_write(vpu, &reg, val);
}
}
static void cfg_ref(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr,
struct vb2_v4l2_buffer *vb2_dst)
{
struct hantro_dev *vpu = ctx->dev;
dma_addr_t ref;
ref = hantro_get_ref(ctx, hdr->last_frame_ts);
if (!ref) {
vpu_debug(0, "failed to find last frame ts=%llu\n",
hdr->last_frame_ts);
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
}
vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(0));
ref = hantro_get_ref(ctx, hdr->golden_frame_ts);
if (!ref && hdr->golden_frame_ts)
vpu_debug(0, "failed to find golden frame ts=%llu\n",
hdr->golden_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN)
ref |= G1_REG_ADDR_REF_TOPC_E;
vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(4));
ref = hantro_get_ref(ctx, hdr->alt_frame_ts);
if (!ref && hdr->alt_frame_ts)
vpu_debug(0, "failed to find alt frame ts=%llu\n",
hdr->alt_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT)
ref |= G1_REG_ADDR_REF_TOPC_E;
vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(5));
}
static void cfg_buffers(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr,
struct vb2_v4l2_buffer *vb2_dst)
{
const struct v4l2_vp8_segment *seg = &hdr->segment;
struct hantro_dev *vpu = ctx->dev;
dma_addr_t dst_dma;
u32 reg;
/* Set probability table buffer address */
vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma,
G1_REG_ADDR_QTABLE);
/* Set segment map address */
reg = G1_REG_FWD_PIC1_SEGMENT_BASE(ctx->vp8_dec.segment_map.dma);
if (seg->flags & V4L2_VP8_SEGMENT_FLAG_ENABLED) {
reg |= G1_REG_FWD_PIC1_SEGMENT_E;
if (seg->flags & V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP)
reg |= G1_REG_FWD_PIC1_SEGMENT_UPD_E;
}
vdpu_write_relaxed(vpu, reg, G1_REG_FWD_PIC(0));
dst_dma = hantro_get_dec_buf_addr(ctx, &vb2_dst->vb2_buf);
vdpu_write_relaxed(vpu, dst_dma, G1_REG_ADDR_DST);
}
int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp8_frame *hdr;
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *vb2_dst;
size_t height = ctx->dst_fmt.height;
size_t width = ctx->dst_fmt.width;
u32 mb_width, mb_height;
u32 reg;
hantro_start_prepare_run(ctx);
hdr = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_VP8_FRAME);
if (WARN_ON(!hdr))
return -EINVAL;
/* Reset segment_map buffer in keyframe */
if (V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) && ctx->vp8_dec.segment_map.cpu)
memset(ctx->vp8_dec.segment_map.cpu, 0,
ctx->vp8_dec.segment_map.size);
hantro_vp8_prob_update(ctx, hdr);
reg = G1_REG_CONFIG_DEC_TIMEOUT_E |
G1_REG_CONFIG_DEC_STRENDIAN_E |
G1_REG_CONFIG_DEC_INSWAP32_E |
G1_REG_CONFIG_DEC_STRSWAP32_E |
G1_REG_CONFIG_DEC_OUTSWAP32_E |
G1_REG_CONFIG_DEC_CLK_GATE_E |
G1_REG_CONFIG_DEC_IN_ENDIAN |
G1_REG_CONFIG_DEC_OUT_ENDIAN |
G1_REG_CONFIG_DEC_MAX_BURST(16);
vdpu_write_relaxed(vpu, reg, G1_REG_CONFIG);
reg = G1_REG_DEC_CTRL0_DEC_MODE(10) |
G1_REG_DEC_CTRL0_DEC_AXI_AUTO;
if (!V4L2_VP8_FRAME_IS_KEY_FRAME(hdr))
reg |= G1_REG_DEC_CTRL0_PIC_INTER_E;
if (!(hdr->flags & V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF))
reg |= G1_REG_DEC_CTRL0_SKIP_MODE;
if (hdr->lf.level == 0)
reg |= G1_REG_DEC_CTRL0_FILTERING_DIS;
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0);
/* Frame dimensions */
mb_width = MB_WIDTH(width);
mb_height = MB_HEIGHT(height);
reg = G1_REG_DEC_CTRL1_PIC_MB_WIDTH(mb_width) |
G1_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(mb_height) |
G1_REG_DEC_CTRL1_PIC_MB_W_EXT(mb_width >> 9) |
G1_REG_DEC_CTRL1_PIC_MB_H_EXT(mb_height >> 8);
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL1);
/* Boolean decoder */
reg = G1_REG_DEC_CTRL2_BOOLEAN_RANGE(hdr->coder_state.range)
| G1_REG_DEC_CTRL2_BOOLEAN_VALUE(hdr->coder_state.value);
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2);
reg = 0;
if (hdr->version != 3)
reg |= G1_REG_DEC_CTRL4_VC1_HEIGHT_EXT;
if (hdr->version & 0x3)
reg |= G1_REG_DEC_CTRL4_BILIN_MC_E;
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4);
cfg_lf(ctx, hdr);
cfg_qp(ctx, hdr);
cfg_parts(ctx, hdr);
cfg_tap(ctx, hdr);
vb2_dst = hantro_get_dst_buf(ctx);
cfg_ref(ctx, hdr, vb2_dst);
cfg_buffers(ctx, hdr, vb2_dst);
hantro_end_prepare_run(ctx);
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT);
return 0;
}
@@ -0,0 +1,137 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2021 Collabora Ltd, Andrzej Pietrasiewicz <andrzej.p@collabora.com>
*/
#include <linux/delay.h>
#include "hantro_hw.h"
#include "hantro_g2_regs.h"
#define G2_ALIGN 16
static bool hantro_g2_active(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
u32 status;
status = vdpu_read(vpu, G2_REG_INTERRUPT);
return (status & G2_REG_INTERRUPT_DEC_E);
}
/**
* hantro_g2_reset:
* @ctx: the hantro context
*
* Emulates a reset using Hantro abort function. Failing this procedure would
* results in programming a running IP which leads to CPU hang.
*
* Using a hard reset procedure instead is prefferred.
*/
void hantro_g2_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
u32 status;
status = vdpu_read(vpu, G2_REG_INTERRUPT);
if (status & G2_REG_INTERRUPT_DEC_E) {
dev_warn_ratelimited(vpu->dev, "device still running, aborting");
status |= G2_REG_INTERRUPT_DEC_ABORT_E | G2_REG_INTERRUPT_DEC_IRQ_DIS;
vdpu_write(vpu, status, G2_REG_INTERRUPT);
do {
mdelay(1);
} while (hantro_g2_active(ctx));
}
}
irqreturn_t hantro_g2_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
u32 status;
status = vdpu_read(vpu, G2_REG_INTERRUPT);
if (!(status & G2_REG_INTERRUPT_DEC_IRQ))
return IRQ_NONE;
hantro_reg_write(vpu, &g2_dec_irq, 0);
hantro_reg_write(vpu, &g2_dec_int_stat, 0);
hantro_reg_write(vpu, &g2_clk_gate_e, 1);
if (status & G2_REG_INTERRUPT_DEC_RDY_INT) {
hantro_irq_done(vpu, VB2_BUF_STATE_DONE);
return IRQ_HANDLED;
}
if (status & G2_REG_INTERRUPT_DEC_ABORT_INT) {
/* disabled on abort, though lets be safe and handle it */
dev_warn_ratelimited(vpu->dev, "decode operation aborted.");
return IRQ_HANDLED;
}
if (status & G2_REG_INTERRUPT_DEC_LAST_SLICE_INT)
dev_warn_ratelimited(vpu->dev, "not all macroblocks were decoded.");
if (status & G2_REG_INTERRUPT_DEC_BUS_INT)
dev_warn_ratelimited(vpu->dev, "bus error detected.");
if (status & G2_REG_INTERRUPT_DEC_ERROR_INT)
dev_warn_ratelimited(vpu->dev, "decode error detected.");
if (status & G2_REG_INTERRUPT_DEC_TIMEOUT)
dev_warn_ratelimited(vpu->dev, "frame decode timed out.");
/**
* If the decoding haven't stopped, let it continue. The hardware timeout
* will trigger if it is trully stuck.
*/
if (status & G2_REG_INTERRUPT_DEC_E)
return IRQ_HANDLED;
hantro_irq_done(vpu, VB2_BUF_STATE_ERROR);
return IRQ_HANDLED;
}
size_t hantro_g2_chroma_offset(struct hantro_ctx *ctx)
{
return ctx->ref_fmt.plane_fmt[0].bytesperline * ctx->ref_fmt.height;
}
size_t hantro_g2_motion_vectors_offset(struct hantro_ctx *ctx)
{
size_t cr_offset = hantro_g2_chroma_offset(ctx);
return ALIGN((cr_offset * 3) / 2, G2_ALIGN);
}
static size_t hantro_g2_mv_size(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
unsigned int max_log2_ctb_size;
max_log2_ctb_size = sps->log2_min_luma_coding_block_size_minus3 + 3 +
sps->log2_diff_max_min_luma_coding_block_size;
pic_width_in_ctbs = (sps->pic_width_in_luma_samples +
(1 << max_log2_ctb_size) - 1) >> max_log2_ctb_size;
pic_height_in_ctbs = (sps->pic_height_in_luma_samples + (1 << max_log2_ctb_size) - 1)
>> max_log2_ctb_size;
return pic_width_in_ctbs * pic_height_in_ctbs * (1 << (2 * (max_log2_ctb_size - 4))) * 16;
}
size_t hantro_g2_luma_compress_offset(struct hantro_ctx *ctx)
{
return hantro_g2_motion_vectors_offset(ctx) +
hantro_g2_mv_size(ctx);
}
size_t hantro_g2_chroma_compress_offset(struct hantro_ctx *ctx)
{
return hantro_g2_luma_compress_offset(ctx) +
hantro_hevc_luma_compressed_size(ctx->dst_fmt.width, ctx->dst_fmt.height);
}
@@ -0,0 +1,637 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU HEVC codec driver
*
* Copyright (C) 2020 Safran Passenger Innovations LLC
*/
#include "hantro_hw.h"
#include "hantro_g2_regs.h"
static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
u16 *p = (u16 *)((u8 *)ctx->hevc_dec.tile_sizes.cpu);
unsigned int num_tile_rows = pps->num_tile_rows_minus1 + 1;
unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
unsigned int max_log2_ctb_size, ctb_size;
bool tiles_enabled, uniform_spacing;
u32 no_chroma = 0;
tiles_enabled = !!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED);
uniform_spacing = !!(pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING);
hantro_reg_write(vpu, &g2_tile_e, tiles_enabled);
max_log2_ctb_size = sps->log2_min_luma_coding_block_size_minus3 + 3 +
sps->log2_diff_max_min_luma_coding_block_size;
pic_width_in_ctbs = (sps->pic_width_in_luma_samples +
(1 << max_log2_ctb_size) - 1) >> max_log2_ctb_size;
pic_height_in_ctbs = (sps->pic_height_in_luma_samples + (1 << max_log2_ctb_size) - 1)
>> max_log2_ctb_size;
ctb_size = 1 << max_log2_ctb_size;
vpu_debug(1, "Preparing tile sizes buffer for %dx%d CTBs (CTB size %d)\n",
pic_width_in_ctbs, pic_height_in_ctbs, ctb_size);
if (tiles_enabled) {
unsigned int i, j, h;
vpu_debug(1, "Tiles enabled! %dx%d\n", num_tile_cols, num_tile_rows);
hantro_reg_write(vpu, &g2_num_tile_rows, num_tile_rows);
hantro_reg_write(vpu, &g2_num_tile_cols, num_tile_cols);
/* write width + height for each tile in pic */
if (!uniform_spacing) {
u32 tmp_w = 0, tmp_h = 0;
for (i = 0; i < num_tile_rows; i++) {
if (i == num_tile_rows - 1)
h = pic_height_in_ctbs - tmp_h;
else
h = pps->row_height_minus1[i] + 1;
tmp_h += h;
if (i == 0 && h == 1 && ctb_size == 16)
no_chroma = 1;
for (j = 0, tmp_w = 0; j < num_tile_cols - 1; j++) {
tmp_w += pps->column_width_minus1[j] + 1;
*p++ = pps->column_width_minus1[j] + 1;
*p++ = h;
if (i == 0 && h == 1 && ctb_size == 16)
no_chroma = 1;
}
/* last column */
*p++ = pic_width_in_ctbs - tmp_w;
*p++ = h;
}
} else { /* uniform spacing */
u32 tmp, prev_h, prev_w;
for (i = 0, prev_h = 0; i < num_tile_rows; i++) {
tmp = (i + 1) * pic_height_in_ctbs / num_tile_rows;
h = tmp - prev_h;
prev_h = tmp;
if (i == 0 && h == 1 && ctb_size == 16)
no_chroma = 1;
for (j = 0, prev_w = 0; j < num_tile_cols; j++) {
tmp = (j + 1) * pic_width_in_ctbs / num_tile_cols;
*p++ = tmp - prev_w;
*p++ = h;
if (j == 0 &&
(pps->column_width_minus1[0] + 1) == 1 &&
ctb_size == 16)
no_chroma = 1;
prev_w = tmp;
}
}
}
} else {
hantro_reg_write(vpu, &g2_num_tile_rows, 1);
hantro_reg_write(vpu, &g2_num_tile_cols, 1);
/* There's one tile, with dimensions equal to pic size. */
p[0] = pic_width_in_ctbs;
p[1] = pic_height_in_ctbs;
}
if (no_chroma)
vpu_debug(1, "%s: no chroma!\n", __func__);
}
static int compute_header_skip_length(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
int skip = 0;
if (pps->flags & V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT)
/* size of pic_output_flag */
skip++;
if (sps->flags & V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE)
/* size of pic_order_cnt_lsb */
skip += 2;
if (!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC)) {
/* size of pic_order_cnt_lsb */
skip += sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
/* size of short_term_ref_pic_set_sps_flag */
skip++;
if (decode_params->short_term_ref_pic_set_size)
/* size of st_ref_pic_set( num_short_term_ref_pic_sets ) */
skip += decode_params->short_term_ref_pic_set_size;
else if (sps->num_short_term_ref_pic_sets > 1)
skip += fls(sps->num_short_term_ref_pic_sets - 1);
skip += decode_params->long_term_ref_pic_set_size;
}
return skip;
}
static void set_params(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
struct hantro_dev *vpu = ctx->dev;
u32 min_log2_cb_size, max_log2_ctb_size, min_cb_size, max_ctb_size;
u32 pic_width_in_min_cbs, pic_height_in_min_cbs;
u32 pic_width_aligned, pic_height_aligned;
u32 partial_ctb_x, partial_ctb_y;
hantro_reg_write(vpu, &g2_bit_depth_y_minus8, sps->bit_depth_luma_minus8);
hantro_reg_write(vpu, &g2_bit_depth_c_minus8, sps->bit_depth_chroma_minus8);
hantro_reg_write(vpu, &g2_hdr_skip_length, compute_header_skip_length(ctx));
min_log2_cb_size = sps->log2_min_luma_coding_block_size_minus3 + 3;
max_log2_ctb_size = min_log2_cb_size + sps->log2_diff_max_min_luma_coding_block_size;
hantro_reg_write(vpu, &g2_min_cb_size, min_log2_cb_size);
hantro_reg_write(vpu, &g2_max_cb_size, max_log2_ctb_size);
min_cb_size = 1 << min_log2_cb_size;
max_ctb_size = 1 << max_log2_ctb_size;
pic_width_in_min_cbs = sps->pic_width_in_luma_samples / min_cb_size;
pic_height_in_min_cbs = sps->pic_height_in_luma_samples / min_cb_size;
pic_width_aligned = ALIGN(sps->pic_width_in_luma_samples, max_ctb_size);
pic_height_aligned = ALIGN(sps->pic_height_in_luma_samples, max_ctb_size);
partial_ctb_x = !!(sps->pic_width_in_luma_samples != pic_width_aligned);
partial_ctb_y = !!(sps->pic_height_in_luma_samples != pic_height_aligned);
hantro_reg_write(vpu, &g2_partial_ctb_x, partial_ctb_x);
hantro_reg_write(vpu, &g2_partial_ctb_y, partial_ctb_y);
hantro_reg_write(vpu, &g2_pic_width_in_cbs, pic_width_in_min_cbs);
hantro_reg_write(vpu, &g2_pic_height_in_cbs, pic_height_in_min_cbs);
hantro_reg_write(vpu, &g2_pic_width_4x4,
(pic_width_in_min_cbs * min_cb_size) / 4);
hantro_reg_write(vpu, &g2_pic_height_4x4,
(pic_height_in_min_cbs * min_cb_size) / 4);
hantro_reg_write(vpu, &hevc_max_inter_hierdepth,
sps->max_transform_hierarchy_depth_inter);
hantro_reg_write(vpu, &hevc_max_intra_hierdepth,
sps->max_transform_hierarchy_depth_intra);
hantro_reg_write(vpu, &hevc_min_trb_size,
sps->log2_min_luma_transform_block_size_minus2 + 2);
hantro_reg_write(vpu, &hevc_max_trb_size,
sps->log2_min_luma_transform_block_size_minus2 + 2 +
sps->log2_diff_max_min_luma_transform_block_size);
hantro_reg_write(vpu, &g2_tempor_mvp_e,
!!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED) &&
!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC));
hantro_reg_write(vpu, &g2_strong_smooth_e,
!!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED));
hantro_reg_write(vpu, &g2_asym_pred_e,
!!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLED));
hantro_reg_write(vpu, &g2_sao_e,
!!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET));
hantro_reg_write(vpu, &g2_sign_data_hide,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED));
if (pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED) {
hantro_reg_write(vpu, &g2_cu_qpd_e, 1);
hantro_reg_write(vpu, &g2_max_cu_qpd_depth, pps->diff_cu_qp_delta_depth);
} else {
hantro_reg_write(vpu, &g2_cu_qpd_e, 0);
hantro_reg_write(vpu, &g2_max_cu_qpd_depth, 0);
}
hantro_reg_write(vpu, &g2_cb_qp_offset, pps->pps_cb_qp_offset);
hantro_reg_write(vpu, &g2_cr_qp_offset, pps->pps_cr_qp_offset);
hantro_reg_write(vpu, &g2_filt_offset_beta, pps->pps_beta_offset_div2);
hantro_reg_write(vpu, &g2_filt_offset_tc, pps->pps_tc_offset_div2);
hantro_reg_write(vpu, &g2_slice_hdr_ext_e,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT));
hantro_reg_write(vpu, &g2_slice_hdr_ext_bits, pps->num_extra_slice_header_bits);
hantro_reg_write(vpu, &g2_slice_chqp_present,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT));
hantro_reg_write(vpu, &g2_weight_bipr_idc,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED));
hantro_reg_write(vpu, &g2_transq_bypass,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED));
hantro_reg_write(vpu, &g2_list_mod_e,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT));
hantro_reg_write(vpu, &g2_entropy_sync_e,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED));
hantro_reg_write(vpu, &g2_cabac_init_present,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT));
hantro_reg_write(vpu, &g2_idr_pic_e,
!!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC));
hantro_reg_write(vpu, &hevc_parallel_merge,
pps->log2_parallel_merge_level_minus2 + 2);
hantro_reg_write(vpu, &g2_pcm_filt_d,
!!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED));
hantro_reg_write(vpu, &g2_pcm_e,
!!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED));
if (sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED) {
hantro_reg_write(vpu, &g2_max_pcm_size,
sps->log2_diff_max_min_pcm_luma_coding_block_size +
sps->log2_min_pcm_luma_coding_block_size_minus3 + 3);
hantro_reg_write(vpu, &g2_min_pcm_size,
sps->log2_min_pcm_luma_coding_block_size_minus3 + 3);
hantro_reg_write(vpu, &g2_bit_depth_pcm_y,
sps->pcm_sample_bit_depth_luma_minus1 + 1);
hantro_reg_write(vpu, &g2_bit_depth_pcm_c,
sps->pcm_sample_bit_depth_chroma_minus1 + 1);
} else {
hantro_reg_write(vpu, &g2_max_pcm_size, 0);
hantro_reg_write(vpu, &g2_min_pcm_size, 0);
hantro_reg_write(vpu, &g2_bit_depth_pcm_y, 0);
hantro_reg_write(vpu, &g2_bit_depth_pcm_c, 0);
}
hantro_reg_write(vpu, &g2_start_code_e, 1);
hantro_reg_write(vpu, &g2_init_qp, pps->init_qp_minus26 + 26);
hantro_reg_write(vpu, &g2_weight_pred_e,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED));
hantro_reg_write(vpu, &g2_cabac_init_present,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT));
hantro_reg_write(vpu, &g2_const_intra_e,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED));
hantro_reg_write(vpu, &g2_transform_skip,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED));
hantro_reg_write(vpu, &g2_out_filtering_dis,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER));
hantro_reg_write(vpu, &g2_filt_ctrl_pres,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT));
hantro_reg_write(vpu, &g2_dependent_slice,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED));
hantro_reg_write(vpu, &g2_filter_override,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED));
hantro_reg_write(vpu, &g2_refidx0_active,
pps->num_ref_idx_l0_default_active_minus1 + 1);
hantro_reg_write(vpu, &g2_refidx1_active,
pps->num_ref_idx_l1_default_active_minus1 + 1);
hantro_reg_write(vpu, &g2_apf_threshold, 8);
}
static u32 get_dpb_index(const struct v4l2_ctrl_hevc_decode_params *decode_params,
const u32 index)
{
if (index > decode_params->num_active_dpb_entries)
return 0;
return index;
}
static void set_ref_pic_list(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
struct hantro_dev *vpu = ctx->dev;
const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
u32 list0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
u32 list1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
static const struct hantro_reg ref_pic_regs0[] = {
hevc_rlist_f0,
hevc_rlist_f1,
hevc_rlist_f2,
hevc_rlist_f3,
hevc_rlist_f4,
hevc_rlist_f5,
hevc_rlist_f6,
hevc_rlist_f7,
hevc_rlist_f8,
hevc_rlist_f9,
hevc_rlist_f10,
hevc_rlist_f11,
hevc_rlist_f12,
hevc_rlist_f13,
hevc_rlist_f14,
hevc_rlist_f15,
};
static const struct hantro_reg ref_pic_regs1[] = {
hevc_rlist_b0,
hevc_rlist_b1,
hevc_rlist_b2,
hevc_rlist_b3,
hevc_rlist_b4,
hevc_rlist_b5,
hevc_rlist_b6,
hevc_rlist_b7,
hevc_rlist_b8,
hevc_rlist_b9,
hevc_rlist_b10,
hevc_rlist_b11,
hevc_rlist_b12,
hevc_rlist_b13,
hevc_rlist_b14,
hevc_rlist_b15,
};
unsigned int i, j;
/* List 0 contains: short term before, short term after and long term */
j = 0;
for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list0); i++)
list0[j++] = decode_params->poc_st_curr_before[i];
for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list0); i++)
list0[j++] = decode_params->poc_st_curr_after[i];
for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list0); i++)
list0[j++] = decode_params->poc_lt_curr[i];
/* Fill the list, copying over and over */
i = 0;
while (j < ARRAY_SIZE(list0))
list0[j++] = list0[i++];
j = 0;
for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list1); i++)
list1[j++] = decode_params->poc_st_curr_after[i];
for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list1); i++)
list1[j++] = decode_params->poc_st_curr_before[i];
for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list1); i++)
list1[j++] = decode_params->poc_lt_curr[i];
i = 0;
while (j < ARRAY_SIZE(list1))
list1[j++] = list1[i++];
for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
hantro_reg_write(vpu, &ref_pic_regs0[i],
get_dpb_index(decode_params, list0[i]));
hantro_reg_write(vpu, &ref_pic_regs1[i],
get_dpb_index(decode_params, list1[i]));
}
}
static int set_ref(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
dma_addr_t luma_addr, chroma_addr, mv_addr = 0;
dma_addr_t compress_luma_addr, compress_chroma_addr = 0;
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *vb2_dst;
struct hantro_decoded_buffer *dst;
size_t cr_offset = hantro_g2_chroma_offset(ctx);
size_t mv_offset = hantro_g2_motion_vectors_offset(ctx);
size_t compress_luma_offset = hantro_g2_luma_compress_offset(ctx);
size_t compress_chroma_offset = hantro_g2_chroma_compress_offset(ctx);
u32 max_ref_frames;
u16 dpb_longterm_e;
static const struct hantro_reg cur_poc[] = {
hevc_cur_poc_00,
hevc_cur_poc_01,
hevc_cur_poc_02,
hevc_cur_poc_03,
hevc_cur_poc_04,
hevc_cur_poc_05,
hevc_cur_poc_06,
hevc_cur_poc_07,
hevc_cur_poc_08,
hevc_cur_poc_09,
hevc_cur_poc_10,
hevc_cur_poc_11,
hevc_cur_poc_12,
hevc_cur_poc_13,
hevc_cur_poc_14,
hevc_cur_poc_15,
};
unsigned int i;
max_ref_frames = decode_params->num_poc_lt_curr +
decode_params->num_poc_st_curr_before +
decode_params->num_poc_st_curr_after;
/*
* Set max_ref_frames to non-zero to avoid HW hang when decoding
* badly marked I-frames.
*/
max_ref_frames = max_ref_frames ? max_ref_frames : 1;
hantro_reg_write(vpu, &g2_num_ref_frames, max_ref_frames);
hantro_reg_write(vpu, &g2_filter_over_slices,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED));
hantro_reg_write(vpu, &g2_filter_over_tiles,
!!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED));
/*
* Write POC count diff from current pic.
*/
for (i = 0; i < decode_params->num_active_dpb_entries && i < ARRAY_SIZE(cur_poc); i++) {
char poc_diff = decode_params->pic_order_cnt_val - dpb[i].pic_order_cnt_val;
hantro_reg_write(vpu, &cur_poc[i], poc_diff);
}
if (i < ARRAY_SIZE(cur_poc)) {
/*
* After the references, fill one entry pointing to itself,
* i.e. difference is zero.
*/
hantro_reg_write(vpu, &cur_poc[i], 0);
i++;
}
/* Fill the rest with the current picture */
for (; i < ARRAY_SIZE(cur_poc); i++)
hantro_reg_write(vpu, &cur_poc[i], decode_params->pic_order_cnt_val);
set_ref_pic_list(ctx);
/* We will only keep the reference pictures that are still used */
hantro_hevc_ref_init(ctx);
/* Set up addresses of DPB buffers */
dpb_longterm_e = 0;
for (i = 0; i < decode_params->num_active_dpb_entries &&
i < (V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1); i++) {
luma_addr = hantro_hevc_get_ref_buf(ctx, dpb[i].pic_order_cnt_val);
if (!luma_addr)
return -ENOMEM;
chroma_addr = luma_addr + cr_offset;
mv_addr = luma_addr + mv_offset;
compress_luma_addr = luma_addr + compress_luma_offset;
compress_chroma_addr = luma_addr + compress_chroma_offset;
if (dpb[i].flags & V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE)
dpb_longterm_e |= BIT(V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1 - i);
hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr);
hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr);
hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr);
hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), compress_luma_addr);
hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i), compress_chroma_addr);
}
vb2_dst = hantro_get_dst_buf(ctx);
dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf);
luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf);
if (!luma_addr)
return -ENOMEM;
if (hantro_hevc_add_ref_buf(ctx, decode_params->pic_order_cnt_val, luma_addr))
return -EINVAL;
chroma_addr = luma_addr + cr_offset;
mv_addr = luma_addr + mv_offset;
compress_luma_addr = luma_addr + compress_luma_offset;
compress_chroma_addr = luma_addr + compress_chroma_offset;
hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr);
hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr);
hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr);
hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), compress_luma_addr);
hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i++), compress_chroma_addr);
hantro_write_addr(vpu, G2_OUT_LUMA_ADDR, luma_addr);
hantro_write_addr(vpu, G2_OUT_CHROMA_ADDR, chroma_addr);
hantro_write_addr(vpu, G2_OUT_MV_ADDR, mv_addr);
hantro_write_addr(vpu, G2_OUT_COMP_LUMA_ADDR, compress_luma_addr);
hantro_write_addr(vpu, G2_OUT_COMP_CHROMA_ADDR, compress_chroma_addr);
for (; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), 0);
hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), 0);
hantro_write_addr(vpu, G2_REF_MV_ADDR(i), 0);
hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), 0);
hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i), 0);
}
hantro_reg_write(vpu, &g2_refer_lterm_e, dpb_longterm_e);
return 0;
}
static void set_buffers(struct hantro_ctx *ctx)
{
struct vb2_v4l2_buffer *src_buf;
struct hantro_dev *vpu = ctx->dev;
dma_addr_t src_dma;
u32 src_len, src_buf_len;
src_buf = hantro_get_src_buf(ctx);
/* Source (stream) buffer. */
src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
src_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
src_buf_len = vb2_plane_size(&src_buf->vb2_buf, 0);
hantro_write_addr(vpu, G2_STREAM_ADDR, src_dma);
hantro_reg_write(vpu, &g2_stream_len, src_len);
hantro_reg_write(vpu, &g2_strm_buffer_len, src_buf_len);
hantro_reg_write(vpu, &g2_strm_start_offset, 0);
hantro_reg_write(vpu, &g2_start_bit, 0);
hantro_reg_write(vpu, &g2_write_mvs_e, 1);
hantro_write_addr(vpu, G2_TILE_SIZES_ADDR, ctx->hevc_dec.tile_sizes.dma);
hantro_write_addr(vpu, G2_TILE_FILTER_ADDR, ctx->hevc_dec.tile_filter.dma);
hantro_write_addr(vpu, G2_TILE_SAO_ADDR, ctx->hevc_dec.tile_sao.dma);
hantro_write_addr(vpu, G2_TILE_BSD_ADDR, ctx->hevc_dec.tile_bsd.dma);
}
static void prepare_scaling_list_buffer(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_scaling_matrix *sc = ctrls->scaling;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
u8 *p = ((u8 *)ctx->hevc_dec.scaling_lists.cpu);
unsigned int scaling_list_enabled;
unsigned int i, j, k;
scaling_list_enabled = !!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED);
hantro_reg_write(vpu, &g2_scaling_list_e, scaling_list_enabled);
if (!scaling_list_enabled)
return;
for (i = 0; i < ARRAY_SIZE(sc->scaling_list_dc_coef_16x16); i++)
*p++ = sc->scaling_list_dc_coef_16x16[i];
for (i = 0; i < ARRAY_SIZE(sc->scaling_list_dc_coef_32x32); i++)
*p++ = sc->scaling_list_dc_coef_32x32[i];
/* 128-bit boundary */
p += 8;
/* write scaling lists column by column */
for (i = 0; i < 6; i++)
for (j = 0; j < 4; j++)
for (k = 0; k < 4; k++)
*p++ = sc->scaling_list_4x4[i][4 * k + j];
for (i = 0; i < 6; i++)
for (j = 0; j < 8; j++)
for (k = 0; k < 8; k++)
*p++ = sc->scaling_list_8x8[i][8 * k + j];
for (i = 0; i < 6; i++)
for (j = 0; j < 8; j++)
for (k = 0; k < 8; k++)
*p++ = sc->scaling_list_16x16[i][8 * k + j];
for (i = 0; i < 2; i++)
for (j = 0; j < 8; j++)
for (k = 0; k < 8; k++)
*p++ = sc->scaling_list_32x32[i][8 * k + j];
hantro_write_addr(vpu, G2_HEVC_SCALING_LIST_ADDR, ctx->hevc_dec.scaling_lists.dma);
}
int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
int ret;
/* Prepare HEVC decoder context. */
ret = hantro_hevc_dec_prepare_run(ctx);
if (ret)
return ret;
/* Configure hardware registers. */
set_params(ctx);
/* set reference pictures */
ret = set_ref(ctx);
if (ret)
return ret;
set_buffers(ctx);
prepare_tile_info_buffer(ctx);
prepare_scaling_list_buffer(ctx);
hantro_end_prepare_run(ctx);
hantro_reg_write(vpu, &g2_mode, HEVC_DEC_MODE);
hantro_reg_write(vpu, &g2_clk_gate_e, 1);
/* Don't disable output */
hantro_reg_write(vpu, &g2_out_dis, 0);
hantro_reg_write(vpu, &g2_ref_compress_bypass, !ctx->hevc_dec.use_compression);
/* Bus width and max burst */
hantro_reg_write(vpu, &g2_buswidth, BUS_WIDTH_128);
hantro_reg_write(vpu, &g2_max_burst, 16);
/* Swap */
hantro_reg_write(vpu, &g2_strm_swap, 0xf);
hantro_reg_write(vpu, &g2_dirmv_swap, 0xf);
hantro_reg_write(vpu, &g2_compress_swap, 0xf);
/* Start decoding! */
vdpu_write(vpu, G2_REG_INTERRUPT_DEC_E, G2_REG_INTERRUPT);
return 0;
}
@@ -0,0 +1,342 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, Collabora
*
* Author: Benjamin Gaignard <benjamin.gaignard@collabora.com>
*/
#ifndef HANTRO_G2_REGS_H_
#define HANTRO_G2_REGS_H_
#include "hantro.h"
#define G2_SWREG(nr) ((nr) * 4)
#define G2_DEC_REG(b, s, m) \
((const struct hantro_reg) { \
.base = G2_SWREG(b), \
.shift = s, \
.mask = m, \
})
#define G2_REG_VERSION G2_SWREG(0)
#define G2_REG_INTERRUPT G2_SWREG(1)
#define G2_REG_INTERRUPT_DEC_LAST_SLICE_INT BIT(19)
#define G2_REG_INTERRUPT_DEC_TIMEOUT BIT(18)
#define G2_REG_INTERRUPT_DEC_ERROR_INT BIT(16)
#define G2_REG_INTERRUPT_DEC_BUF_INT BIT(14)
#define G2_REG_INTERRUPT_DEC_BUS_INT BIT(13)
#define G2_REG_INTERRUPT_DEC_RDY_INT BIT(12)
#define G2_REG_INTERRUPT_DEC_ABORT_INT BIT(11)
#define G2_REG_INTERRUPT_DEC_IRQ BIT(8)
#define G2_REG_INTERRUPT_DEC_ABORT_E BIT(5)
#define G2_REG_INTERRUPT_DEC_IRQ_DIS BIT(4)
#define G2_REG_INTERRUPT_DEC_E BIT(0)
#define HEVC_DEC_MODE 0xc
#define VP9_DEC_MODE 0xd
#define BUS_WIDTH_32 0
#define BUS_WIDTH_64 1
#define BUS_WIDTH_128 2
#define BUS_WIDTH_256 3
#define g2_dec_int_stat G2_DEC_REG(1, 11, 0xf)
#define g2_dec_irq G2_DEC_REG(1, 8, 0x1)
#define g2_strm_swap G2_DEC_REG(2, 28, 0xf)
#define g2_strm_swap_old G2_DEC_REG(2, 27, 0x1f)
#define g2_pic_swap G2_DEC_REG(2, 22, 0x1f)
#define g2_dirmv_swap G2_DEC_REG(2, 20, 0xf)
#define g2_dirmv_swap_old G2_DEC_REG(2, 17, 0x1f)
#define g2_tab0_swap_old G2_DEC_REG(2, 12, 0x1f)
#define g2_tab1_swap_old G2_DEC_REG(2, 7, 0x1f)
#define g2_tab2_swap_old G2_DEC_REG(2, 2, 0x1f)
#define g2_mode G2_DEC_REG(3, 27, 0x1f)
#define g2_compress_swap G2_DEC_REG(3, 20, 0xf)
#define g2_ref_compress_bypass G2_DEC_REG(3, 17, 0x1)
#define g2_out_rs_e G2_DEC_REG(3, 16, 0x1)
#define g2_out_dis G2_DEC_REG(3, 15, 0x1)
#define g2_out_filtering_dis G2_DEC_REG(3, 14, 0x1)
#define g2_write_mvs_e G2_DEC_REG(3, 12, 0x1)
#define g2_tab3_swap_old G2_DEC_REG(3, 7, 0x1f)
#define g2_rscan_swap G2_DEC_REG(3, 2, 0x1f)
#define g2_pic_width_in_cbs G2_DEC_REG(4, 19, 0x1fff)
#define g2_pic_height_in_cbs G2_DEC_REG(4, 6, 0x1fff)
#define g2_num_ref_frames G2_DEC_REG(4, 0, 0x1f)
#define g2_start_bit G2_DEC_REG(5, 25, 0x7f)
#define g2_scaling_list_e G2_DEC_REG(5, 24, 0x1)
#define g2_cb_qp_offset G2_DEC_REG(5, 19, 0x1f)
#define g2_cr_qp_offset G2_DEC_REG(5, 14, 0x1f)
#define g2_sign_data_hide G2_DEC_REG(5, 12, 0x1)
#define g2_tempor_mvp_e G2_DEC_REG(5, 11, 0x1)
#define g2_max_cu_qpd_depth G2_DEC_REG(5, 5, 0x3f)
#define g2_cu_qpd_e G2_DEC_REG(5, 4, 0x1)
#define g2_pix_shift G2_DEC_REG(5, 0, 0xf)
#define g2_stream_len G2_DEC_REG(6, 0, 0xffffffff)
#define g2_cabac_init_present G2_DEC_REG(7, 31, 0x1)
#define g2_weight_pred_e G2_DEC_REG(7, 28, 0x1)
#define g2_weight_bipr_idc G2_DEC_REG(7, 26, 0x3)
#define g2_filter_over_slices G2_DEC_REG(7, 25, 0x1)
#define g2_filter_over_tiles G2_DEC_REG(7, 24, 0x1)
#define g2_asym_pred_e G2_DEC_REG(7, 23, 0x1)
#define g2_sao_e G2_DEC_REG(7, 22, 0x1)
#define g2_pcm_filt_d G2_DEC_REG(7, 21, 0x1)
#define g2_slice_chqp_present G2_DEC_REG(7, 20, 0x1)
#define g2_dependent_slice G2_DEC_REG(7, 19, 0x1)
#define g2_filter_override G2_DEC_REG(7, 18, 0x1)
#define g2_strong_smooth_e G2_DEC_REG(7, 17, 0x1)
#define g2_filt_offset_beta G2_DEC_REG(7, 12, 0x1f)
#define g2_filt_offset_tc G2_DEC_REG(7, 7, 0x1f)
#define g2_slice_hdr_ext_e G2_DEC_REG(7, 6, 0x1)
#define g2_slice_hdr_ext_bits G2_DEC_REG(7, 3, 0x7)
#define g2_const_intra_e G2_DEC_REG(8, 31, 0x1)
#define g2_filt_ctrl_pres G2_DEC_REG(8, 30, 0x1)
#define g2_bit_depth_y G2_DEC_REG(8, 21, 0xf)
#define g2_bit_depth_c G2_DEC_REG(8, 17, 0xf)
#define g2_idr_pic_e G2_DEC_REG(8, 16, 0x1)
#define g2_bit_depth_pcm_y G2_DEC_REG(8, 12, 0xf)
#define g2_bit_depth_pcm_c G2_DEC_REG(8, 8, 0xf)
#define g2_bit_depth_y_minus8 G2_DEC_REG(8, 6, 0x3)
#define g2_bit_depth_c_minus8 G2_DEC_REG(8, 4, 0x3)
#define g2_rs_out_bit_depth G2_DEC_REG(8, 4, 0xf)
#define g2_output_8_bits G2_DEC_REG(8, 3, 0x1)
#define g2_output_format G2_DEC_REG(8, 0, 0x7)
#define g2_pp_pix_shift G2_DEC_REG(8, 0, 0xf)
#define g2_refidx1_active G2_DEC_REG(9, 19, 0x1f)
#define g2_refidx0_active G2_DEC_REG(9, 14, 0x1f)
#define g2_hdr_skip_length G2_DEC_REG(9, 0, 0x3fff)
#define g2_start_code_e G2_DEC_REG(10, 31, 0x1)
#define g2_init_qp_old G2_DEC_REG(10, 25, 0x3f)
#define g2_init_qp G2_DEC_REG(10, 24, 0x7f)
#define g2_num_tile_cols_old G2_DEC_REG(10, 20, 0x1f)
#define g2_num_tile_cols G2_DEC_REG(10, 19, 0x1f)
#define g2_num_tile_rows_old G2_DEC_REG(10, 15, 0x1f)
#define g2_num_tile_rows G2_DEC_REG(10, 14, 0x1f)
#define g2_tile_e G2_DEC_REG(10, 1, 0x1)
#define g2_entropy_sync_e G2_DEC_REG(10, 0, 0x1)
#define vp9_transform_mode G2_DEC_REG(11, 27, 0x7)
#define vp9_filt_sharpness G2_DEC_REG(11, 21, 0x7)
#define vp9_mcomp_filt_type G2_DEC_REG(11, 8, 0x7)
#define vp9_high_prec_mv_e G2_DEC_REG(11, 7, 0x1)
#define vp9_comp_pred_mode G2_DEC_REG(11, 4, 0x3)
#define vp9_gref_sign_bias G2_DEC_REG(11, 2, 0x1)
#define vp9_aref_sign_bias G2_DEC_REG(11, 0, 0x1)
#define g2_refer_lterm_e G2_DEC_REG(12, 16, 0xffff)
#define g2_min_cb_size G2_DEC_REG(12, 13, 0x7)
#define g2_max_cb_size G2_DEC_REG(12, 10, 0x7)
#define g2_min_pcm_size G2_DEC_REG(12, 7, 0x7)
#define g2_max_pcm_size G2_DEC_REG(12, 4, 0x7)
#define g2_pcm_e G2_DEC_REG(12, 3, 0x1)
#define g2_transform_skip G2_DEC_REG(12, 2, 0x1)
#define g2_transq_bypass G2_DEC_REG(12, 1, 0x1)
#define g2_list_mod_e G2_DEC_REG(12, 0, 0x1)
#define hevc_min_trb_size G2_DEC_REG(13, 13, 0x7)
#define hevc_max_trb_size G2_DEC_REG(13, 10, 0x7)
#define hevc_max_intra_hierdepth G2_DEC_REG(13, 7, 0x7)
#define hevc_max_inter_hierdepth G2_DEC_REG(13, 4, 0x7)
#define hevc_parallel_merge G2_DEC_REG(13, 0, 0xf)
#define hevc_rlist_f0 G2_DEC_REG(14, 0, 0x1f)
#define hevc_rlist_f1 G2_DEC_REG(14, 10, 0x1f)
#define hevc_rlist_f2 G2_DEC_REG(14, 20, 0x1f)
#define hevc_rlist_b0 G2_DEC_REG(14, 5, 0x1f)
#define hevc_rlist_b1 G2_DEC_REG(14, 15, 0x1f)
#define hevc_rlist_b2 G2_DEC_REG(14, 25, 0x1f)
#define hevc_rlist_f3 G2_DEC_REG(15, 0, 0x1f)
#define hevc_rlist_f4 G2_DEC_REG(15, 10, 0x1f)
#define hevc_rlist_f5 G2_DEC_REG(15, 20, 0x1f)
#define hevc_rlist_b3 G2_DEC_REG(15, 5, 0x1f)
#define hevc_rlist_b4 G2_DEC_REG(15, 15, 0x1f)
#define hevc_rlist_b5 G2_DEC_REG(15, 25, 0x1f)
#define hevc_rlist_f6 G2_DEC_REG(16, 0, 0x1f)
#define hevc_rlist_f7 G2_DEC_REG(16, 10, 0x1f)
#define hevc_rlist_f8 G2_DEC_REG(16, 20, 0x1f)
#define hevc_rlist_b6 G2_DEC_REG(16, 5, 0x1f)
#define hevc_rlist_b7 G2_DEC_REG(16, 15, 0x1f)
#define hevc_rlist_b8 G2_DEC_REG(16, 25, 0x1f)
#define hevc_rlist_f9 G2_DEC_REG(17, 0, 0x1f)
#define hevc_rlist_f10 G2_DEC_REG(17, 10, 0x1f)
#define hevc_rlist_f11 G2_DEC_REG(17, 20, 0x1f)
#define hevc_rlist_b9 G2_DEC_REG(17, 5, 0x1f)
#define hevc_rlist_b10 G2_DEC_REG(17, 15, 0x1f)
#define hevc_rlist_b11 G2_DEC_REG(17, 25, 0x1f)
#define hevc_rlist_f12 G2_DEC_REG(18, 0, 0x1f)
#define hevc_rlist_f13 G2_DEC_REG(18, 10, 0x1f)
#define hevc_rlist_f14 G2_DEC_REG(18, 20, 0x1f)
#define hevc_rlist_b12 G2_DEC_REG(18, 5, 0x1f)
#define hevc_rlist_b13 G2_DEC_REG(18, 15, 0x1f)
#define hevc_rlist_b14 G2_DEC_REG(18, 25, 0x1f)
#define hevc_rlist_f15 G2_DEC_REG(19, 0, 0x1f)
#define hevc_rlist_b15 G2_DEC_REG(19, 5, 0x1f)
#define g2_partial_ctb_x G2_DEC_REG(20, 31, 0x1)
#define g2_partial_ctb_y G2_DEC_REG(20, 30, 0x1)
#define g2_pic_width_4x4 G2_DEC_REG(20, 16, 0xfff)
#define g2_pic_height_4x4 G2_DEC_REG(20, 0, 0xfff)
#define vp9_qp_delta_y_dc G2_DEC_REG(13, 23, 0x3f)
#define vp9_qp_delta_ch_dc G2_DEC_REG(13, 17, 0x3f)
#define vp9_qp_delta_ch_ac G2_DEC_REG(13, 11, 0x3f)
#define vp9_last_sign_bias G2_DEC_REG(13, 10, 0x1)
#define vp9_lossless_e G2_DEC_REG(13, 9, 0x1)
#define vp9_comp_pred_var_ref1 G2_DEC_REG(13, 7, 0x3)
#define vp9_comp_pred_var_ref0 G2_DEC_REG(13, 5, 0x3)
#define vp9_comp_pred_fixed_ref G2_DEC_REG(13, 3, 0x3)
#define vp9_segment_temp_upd_e G2_DEC_REG(13, 2, 0x1)
#define vp9_segment_upd_e G2_DEC_REG(13, 1, 0x1)
#define vp9_segment_e G2_DEC_REG(13, 0, 0x1)
#define vp9_filt_level G2_DEC_REG(14, 18, 0x3f)
#define vp9_refpic_seg0 G2_DEC_REG(14, 15, 0x7)
#define vp9_skip_seg0 G2_DEC_REG(14, 14, 0x1)
#define vp9_filt_level_seg0 G2_DEC_REG(14, 8, 0x3f)
#define vp9_quant_seg0 G2_DEC_REG(14, 0, 0xff)
#define vp9_refpic_seg1 G2_DEC_REG(15, 15, 0x7)
#define vp9_skip_seg1 G2_DEC_REG(15, 14, 0x1)
#define vp9_filt_level_seg1 G2_DEC_REG(15, 8, 0x3f)
#define vp9_quant_seg1 G2_DEC_REG(15, 0, 0xff)
#define vp9_refpic_seg2 G2_DEC_REG(16, 15, 0x7)
#define vp9_skip_seg2 G2_DEC_REG(16, 14, 0x1)
#define vp9_filt_level_seg2 G2_DEC_REG(16, 8, 0x3f)
#define vp9_quant_seg2 G2_DEC_REG(16, 0, 0xff)
#define vp9_refpic_seg3 G2_DEC_REG(17, 15, 0x7)
#define vp9_skip_seg3 G2_DEC_REG(17, 14, 0x1)
#define vp9_filt_level_seg3 G2_DEC_REG(17, 8, 0x3f)
#define vp9_quant_seg3 G2_DEC_REG(17, 0, 0xff)
#define vp9_refpic_seg4 G2_DEC_REG(18, 15, 0x7)
#define vp9_skip_seg4 G2_DEC_REG(18, 14, 0x1)
#define vp9_filt_level_seg4 G2_DEC_REG(18, 8, 0x3f)
#define vp9_quant_seg4 G2_DEC_REG(18, 0, 0xff)
#define vp9_refpic_seg5 G2_DEC_REG(19, 15, 0x7)
#define vp9_skip_seg5 G2_DEC_REG(19, 14, 0x1)
#define vp9_filt_level_seg5 G2_DEC_REG(19, 8, 0x3f)
#define vp9_quant_seg5 G2_DEC_REG(19, 0, 0xff)
#define g2_timemout_override_e G2_DEC_REG(45, 31, 0x1)
#define g2_timemout_cycles G2_DEC_REG(45, 0, 0x7fffffff)
#define hevc_cur_poc_00 G2_DEC_REG(46, 24, 0xff)
#define hevc_cur_poc_01 G2_DEC_REG(46, 16, 0xff)
#define hevc_cur_poc_02 G2_DEC_REG(46, 8, 0xff)
#define hevc_cur_poc_03 G2_DEC_REG(46, 0, 0xff)
#define hevc_cur_poc_04 G2_DEC_REG(47, 24, 0xff)
#define hevc_cur_poc_05 G2_DEC_REG(47, 16, 0xff)
#define hevc_cur_poc_06 G2_DEC_REG(47, 8, 0xff)
#define hevc_cur_poc_07 G2_DEC_REG(47, 0, 0xff)
#define hevc_cur_poc_08 G2_DEC_REG(48, 24, 0xff)
#define hevc_cur_poc_09 G2_DEC_REG(48, 16, 0xff)
#define hevc_cur_poc_10 G2_DEC_REG(48, 8, 0xff)
#define hevc_cur_poc_11 G2_DEC_REG(48, 0, 0xff)
#define hevc_cur_poc_12 G2_DEC_REG(49, 24, 0xff)
#define hevc_cur_poc_13 G2_DEC_REG(49, 16, 0xff)
#define hevc_cur_poc_14 G2_DEC_REG(49, 8, 0xff)
#define hevc_cur_poc_15 G2_DEC_REG(49, 0, 0xff)
#define vp9_refpic_seg6 G2_DEC_REG(31, 15, 0x7)
#define vp9_skip_seg6 G2_DEC_REG(31, 14, 0x1)
#define vp9_filt_level_seg6 G2_DEC_REG(31, 8, 0x3f)
#define vp9_quant_seg6 G2_DEC_REG(31, 0, 0xff)
#define vp9_refpic_seg7 G2_DEC_REG(32, 15, 0x7)
#define vp9_skip_seg7 G2_DEC_REG(32, 14, 0x1)
#define vp9_filt_level_seg7 G2_DEC_REG(32, 8, 0x3f)
#define vp9_quant_seg7 G2_DEC_REG(32, 0, 0xff)
#define vp9_lref_width G2_DEC_REG(33, 16, 0xffff)
#define vp9_lref_height G2_DEC_REG(33, 0, 0xffff)
#define vp9_gref_width G2_DEC_REG(34, 16, 0xffff)
#define vp9_gref_height G2_DEC_REG(34, 0, 0xffff)
#define vp9_aref_width G2_DEC_REG(35, 16, 0xffff)
#define vp9_aref_height G2_DEC_REG(35, 0, 0xffff)
#define vp9_lref_hor_scale G2_DEC_REG(36, 16, 0xffff)
#define vp9_lref_ver_scale G2_DEC_REG(36, 0, 0xffff)
#define vp9_gref_hor_scale G2_DEC_REG(37, 16, 0xffff)
#define vp9_gref_ver_scale G2_DEC_REG(37, 0, 0xffff)
#define vp9_aref_hor_scale G2_DEC_REG(38, 16, 0xffff)
#define vp9_aref_ver_scale G2_DEC_REG(38, 0, 0xffff)
#define vp9_filt_ref_adj_0 G2_DEC_REG(46, 24, 0x7f)
#define vp9_filt_ref_adj_1 G2_DEC_REG(46, 16, 0x7f)
#define vp9_filt_ref_adj_2 G2_DEC_REG(46, 8, 0x7f)
#define vp9_filt_ref_adj_3 G2_DEC_REG(46, 0, 0x7f)
#define vp9_filt_mb_adj_0 G2_DEC_REG(47, 24, 0x7f)
#define vp9_filt_mb_adj_1 G2_DEC_REG(47, 16, 0x7f)
#define vp9_filt_mb_adj_2 G2_DEC_REG(47, 8, 0x7f)
#define vp9_filt_mb_adj_3 G2_DEC_REG(47, 0, 0x7f)
#define g2_apf_threshold G2_DEC_REG(55, 0, 0xffff)
#define g2_clk_gate_e G2_DEC_REG(58, 16, 0x1)
#define g2_double_buffer_e G2_DEC_REG(58, 15, 0x1)
#define g2_buswidth G2_DEC_REG(58, 8, 0x7)
#define g2_max_burst G2_DEC_REG(58, 0, 0xff)
#define g2_down_scale_e G2_DEC_REG(184, 7, 0x1)
#define g2_down_scale_y G2_DEC_REG(184, 2, 0x3)
#define g2_down_scale_x G2_DEC_REG(184, 0, 0x3)
#define G2_REG_CONFIG G2_SWREG(58)
#define G2_REG_CONFIG_DEC_CLK_GATE_E BIT(16)
#define G2_REG_CONFIG_DEC_CLK_GATE_IDLE_E BIT(17)
#define G2_OUT_LUMA_ADDR (G2_SWREG(65))
#define G2_REF_LUMA_ADDR(i) (G2_SWREG(67) + ((i) * 0x8))
#define G2_VP9_SEGMENT_WRITE_ADDR (G2_SWREG(79))
#define G2_VP9_SEGMENT_READ_ADDR (G2_SWREG(81))
#define G2_OUT_CHROMA_ADDR (G2_SWREG(99))
#define G2_REF_CHROMA_ADDR(i) (G2_SWREG(101) + ((i) * 0x8))
#define G2_OUT_MV_ADDR (G2_SWREG(133))
#define G2_REF_MV_ADDR(i) (G2_SWREG(135) + ((i) * 0x8))
#define G2_TILE_SIZES_ADDR (G2_SWREG(167))
#define G2_STREAM_ADDR (G2_SWREG(169))
#define G2_HEVC_SCALING_LIST_ADDR (G2_SWREG(171))
#define G2_VP9_CTX_COUNT_ADDR (G2_SWREG(171))
#define G2_VP9_PROBS_ADDR (G2_SWREG(173))
#define G2_RS_OUT_LUMA_ADDR (G2_SWREG(175))
#define G2_RS_OUT_CHROMA_ADDR (G2_SWREG(177))
#define G2_TILE_FILTER_ADDR (G2_SWREG(179))
#define G2_TILE_SAO_ADDR (G2_SWREG(181))
#define G2_TILE_BSD_ADDR (G2_SWREG(183))
#define G2_DS_DST (G2_SWREG(186))
#define G2_DS_DST_CHR (G2_SWREG(188))
#define G2_OUT_COMP_LUMA_ADDR (G2_SWREG(190))
#define G2_REF_COMP_LUMA_ADDR(i) (G2_SWREG(192) + ((i) * 0x8))
#define G2_OUT_COMP_CHROMA_ADDR (G2_SWREG(224))
#define G2_REF_COMP_CHROMA_ADDR(i) (G2_SWREG(226) + ((i) * 0x8))
#define g2_strm_buffer_len G2_DEC_REG(258, 0, 0xffffffff)
#define g2_strm_start_offset G2_DEC_REG(259, 0, 0xffffffff)
#endif
@@ -0,0 +1,996 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VP9 codec driver
*
* Copyright (C) 2021 Collabora Ltd.
*/
#include "media/videobuf2-core.h"
#include "media/videobuf2-dma-contig.h"
#include "media/videobuf2-v4l2.h"
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-vp9.h>
#include "hantro.h"
#include "hantro_vp9.h"
#include "hantro_g2_regs.h"
enum hantro_ref_frames {
INTRA_FRAME = 0,
LAST_FRAME = 1,
GOLDEN_FRAME = 2,
ALTREF_FRAME = 3,
MAX_REF_FRAMES = 4
};
static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame **dec_params)
{
const struct v4l2_ctrl_vp9_compressed_hdr *prob_updates;
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
struct v4l2_ctrl *ctrl;
unsigned int fctx_idx;
/* v4l2-specific stuff */
hantro_start_prepare_run(ctx);
ctrl = v4l2_ctrl_find(&ctx->ctrl_handler, V4L2_CID_STATELESS_VP9_FRAME);
if (WARN_ON(!ctrl))
return -EINVAL;
*dec_params = ctrl->p_cur.p;
ctrl = v4l2_ctrl_find(&ctx->ctrl_handler, V4L2_CID_STATELESS_VP9_COMPRESSED_HDR);
if (WARN_ON(!ctrl))
return -EINVAL;
prob_updates = ctrl->p_cur.p;
vp9_ctx->cur.tx_mode = prob_updates->tx_mode;
/*
* vp9 stuff
*
* by this point the userspace has done all parts of 6.2 uncompressed_header()
* except this fragment:
* if ( FrameIsIntra || error_resilient_mode ) {
* setup_past_independence ( )
* if ( frame_type == KEY_FRAME || error_resilient_mode == 1 ||
* reset_frame_context == 3 ) {
* for ( i = 0; i < 4; i ++ ) {
* save_probs( i )
* }
* } else if ( reset_frame_context == 2 ) {
* save_probs( frame_context_idx )
* }
* frame_context_idx = 0
* }
*/
fctx_idx = v4l2_vp9_reset_frame_ctx(*dec_params, vp9_ctx->frame_context);
vp9_ctx->cur.frame_context_idx = fctx_idx;
/* 6.1 frame(sz): load_probs() and load_probs2() */
vp9_ctx->probability_tables = vp9_ctx->frame_context[fctx_idx];
/*
* The userspace has also performed 6.3 compressed_header(), but handling the
* probs in a special way. All probs which need updating, except MV-related,
* have been read from the bitstream and translated through inv_map_table[],
* but no 6.3.6 inv_recenter_nonneg(v, m) has been performed. The values passed
* by userspace are either translated values (there are no 0 values in
* inv_map_table[]), or zero to indicate no update. All MV-related probs which need
* updating have been read from the bitstream and (mv_prob << 1) | 1 has been
* performed. The values passed by userspace are either new values
* to replace old ones (the above mentioned shift and bitwise or never result in
* a zero) or zero to indicate no update.
* fw_update_probs() performs actual probs updates or leaves probs as-is
* for values for which a zero was passed from userspace.
*/
v4l2_vp9_fw_update_probs(&vp9_ctx->probability_tables, prob_updates, *dec_params);
return 0;
}
static struct hantro_decoded_buffer *
get_ref_buf(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
{
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
struct vb2_buffer *buf;
/*
* If a ref is unused or invalid, address of current destination
* buffer is returned.
*/
buf = vb2_find_buffer(cap_q, timestamp);
if (!buf)
buf = &dst->vb2_buf;
return vb2_to_hantro_decoded_buf(buf);
}
static void update_dec_buf_info(struct hantro_decoded_buffer *buf,
const struct v4l2_ctrl_vp9_frame *dec_params)
{
buf->vp9.width = dec_params->frame_width_minus_1 + 1;
buf->vp9.height = dec_params->frame_height_minus_1 + 1;
buf->vp9.bit_depth = dec_params->bit_depth;
}
static void update_ctx_cur_info(struct hantro_vp9_dec_hw_ctx *vp9_ctx,
struct hantro_decoded_buffer *buf,
const struct v4l2_ctrl_vp9_frame *dec_params)
{
vp9_ctx->cur.valid = true;
vp9_ctx->cur.reference_mode = dec_params->reference_mode;
vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter;
vp9_ctx->cur.flags = dec_params->flags;
vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp;
}
static void config_output(struct hantro_ctx *ctx,
struct hantro_decoded_buffer *dst,
const struct v4l2_ctrl_vp9_frame *dec_params)
{
dma_addr_t luma_addr, chroma_addr, mv_addr;
hantro_reg_write(ctx->dev, &g2_out_dis, 0);
if (!ctx->dev->variant->legacy_regs)
hantro_reg_write(ctx->dev, &g2_output_format, 0);
luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf);
hantro_write_addr(ctx->dev, G2_OUT_LUMA_ADDR, luma_addr);
chroma_addr = luma_addr + hantro_g2_chroma_offset(ctx);
hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
dst->vp9.chroma_offset = hantro_g2_chroma_offset(ctx);
mv_addr = luma_addr + hantro_g2_motion_vectors_offset(ctx);
hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
dst->vp9.mv_offset = hantro_g2_motion_vectors_offset(ctx);
}
struct hantro_vp9_ref_reg {
const struct hantro_reg width;
const struct hantro_reg height;
const struct hantro_reg hor_scale;
const struct hantro_reg ver_scale;
u32 y_base;
u32 c_base;
};
static void config_ref(struct hantro_ctx *ctx,
struct hantro_decoded_buffer *dst,
const struct hantro_vp9_ref_reg *ref_reg,
const struct v4l2_ctrl_vp9_frame *dec_params,
u64 ref_ts)
{
struct hantro_decoded_buffer *buf;
dma_addr_t luma_addr, chroma_addr;
u32 refw, refh;
buf = get_ref_buf(ctx, &dst->base.vb, ref_ts);
refw = buf->vp9.width;
refh = buf->vp9.height;
hantro_reg_write(ctx->dev, &ref_reg->width, refw);
hantro_reg_write(ctx->dev, &ref_reg->height, refh);
hantro_reg_write(ctx->dev, &ref_reg->hor_scale, (refw << 14) / dst->vp9.width);
hantro_reg_write(ctx->dev, &ref_reg->ver_scale, (refh << 14) / dst->vp9.height);
luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
chroma_addr = luma_addr + buf->vp9.chroma_offset;
hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
}
static void config_ref_registers(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp9_frame *dec_params,
struct hantro_decoded_buffer *dst,
struct hantro_decoded_buffer *mv_ref)
{
static const struct hantro_vp9_ref_reg ref_regs[] = {
{
/* Last */
.width = vp9_lref_width,
.height = vp9_lref_height,
.hor_scale = vp9_lref_hor_scale,
.ver_scale = vp9_lref_ver_scale,
.y_base = G2_REF_LUMA_ADDR(0),
.c_base = G2_REF_CHROMA_ADDR(0),
}, {
/* Golden */
.width = vp9_gref_width,
.height = vp9_gref_height,
.hor_scale = vp9_gref_hor_scale,
.ver_scale = vp9_gref_ver_scale,
.y_base = G2_REF_LUMA_ADDR(4),
.c_base = G2_REF_CHROMA_ADDR(4),
}, {
/* Altref */
.width = vp9_aref_width,
.height = vp9_aref_height,
.hor_scale = vp9_aref_hor_scale,
.ver_scale = vp9_aref_ver_scale,
.y_base = G2_REF_LUMA_ADDR(5),
.c_base = G2_REF_CHROMA_ADDR(5),
},
};
dma_addr_t mv_addr;
config_ref(ctx, dst, &ref_regs[0], dec_params, dec_params->last_frame_ts);
config_ref(ctx, dst, &ref_regs[1], dec_params, dec_params->golden_frame_ts);
config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
mv_ref->vp9.mv_offset;
hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
hantro_reg_write(ctx->dev, &vp9_last_sign_bias,
dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_LAST ? 1 : 0);
hantro_reg_write(ctx->dev, &vp9_gref_sign_bias,
dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_GOLDEN ? 1 : 0);
hantro_reg_write(ctx->dev, &vp9_aref_sign_bias,
dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_ALT ? 1 : 0);
}
static void recompute_tile_info(unsigned short *tile_info, unsigned int tiles, unsigned int sbs)
{
int i;
unsigned int accumulated = 0;
unsigned int next_accumulated;
for (i = 1; i <= tiles; ++i) {
next_accumulated = i * sbs / tiles;
*tile_info++ = next_accumulated - accumulated;
accumulated = next_accumulated;
}
}
static void
recompute_tile_rc_info(struct hantro_ctx *ctx,
unsigned int tile_r, unsigned int tile_c,
unsigned int sbs_r, unsigned int sbs_c)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
recompute_tile_info(vp9_ctx->tile_r_info, tile_r, sbs_r);
recompute_tile_info(vp9_ctx->tile_c_info, tile_c, sbs_c);
vp9_ctx->last_tile_r = tile_r;
vp9_ctx->last_tile_c = tile_c;
vp9_ctx->last_sbs_r = sbs_r;
vp9_ctx->last_sbs_c = sbs_c;
}
static inline unsigned int first_tile_row(unsigned int tile_r, unsigned int sbs_r)
{
if (tile_r == sbs_r + 1)
return 1;
if (tile_r == sbs_r + 2)
return 2;
return 0;
}
static void
fill_tile_info(struct hantro_ctx *ctx,
unsigned int tile_r, unsigned int tile_c,
unsigned int sbs_r, unsigned int sbs_c,
unsigned short *tile_mem)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
unsigned int i, j;
bool first = true;
for (i = first_tile_row(tile_r, sbs_r); i < tile_r; ++i) {
unsigned short r_info = vp9_ctx->tile_r_info[i];
if (first) {
if (i > 0)
r_info += vp9_ctx->tile_r_info[0];
if (i == 2)
r_info += vp9_ctx->tile_r_info[1];
first = false;
}
for (j = 0; j < tile_c; ++j) {
*tile_mem++ = vp9_ctx->tile_c_info[j];
*tile_mem++ = r_info;
}
}
}
static void
config_tiles(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp9_frame *dec_params,
struct hantro_decoded_buffer *dst)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
struct hantro_aux_buf *misc = &vp9_ctx->misc;
struct hantro_aux_buf *tile_edge = &vp9_ctx->tile_edge;
dma_addr_t addr;
unsigned short *tile_mem;
unsigned int rows, cols;
addr = misc->dma + vp9_ctx->tile_info_offset;
hantro_write_addr(ctx->dev, G2_TILE_SIZES_ADDR, addr);
tile_mem = misc->cpu + vp9_ctx->tile_info_offset;
if (dec_params->tile_cols_log2 || dec_params->tile_rows_log2) {
unsigned int tile_r = (1 << dec_params->tile_rows_log2);
unsigned int tile_c = (1 << dec_params->tile_cols_log2);
unsigned int sbs_r = hantro_vp9_num_sbs(dst->vp9.height);
unsigned int sbs_c = hantro_vp9_num_sbs(dst->vp9.width);
if (tile_r != vp9_ctx->last_tile_r || tile_c != vp9_ctx->last_tile_c ||
sbs_r != vp9_ctx->last_sbs_r || sbs_c != vp9_ctx->last_sbs_c)
recompute_tile_rc_info(ctx, tile_r, tile_c, sbs_r, sbs_c);
fill_tile_info(ctx, tile_r, tile_c, sbs_r, sbs_c, tile_mem);
cols = tile_c;
rows = tile_r;
hantro_reg_write(ctx->dev, &g2_tile_e, 1);
} else {
tile_mem[0] = hantro_vp9_num_sbs(dst->vp9.width);
tile_mem[1] = hantro_vp9_num_sbs(dst->vp9.height);
cols = 1;
rows = 1;
hantro_reg_write(ctx->dev, &g2_tile_e, 0);
}
if (ctx->dev->variant->legacy_regs) {
hantro_reg_write(ctx->dev, &g2_num_tile_cols_old, cols);
hantro_reg_write(ctx->dev, &g2_num_tile_rows_old, rows);
} else {
hantro_reg_write(ctx->dev, &g2_num_tile_cols, cols);
hantro_reg_write(ctx->dev, &g2_num_tile_rows, rows);
}
/* provide aux buffers even if no tiles are used */
addr = tile_edge->dma;
hantro_write_addr(ctx->dev, G2_TILE_FILTER_ADDR, addr);
addr = tile_edge->dma + vp9_ctx->bsd_ctrl_offset;
hantro_write_addr(ctx->dev, G2_TILE_BSD_ADDR, addr);
}
static void
update_feat_and_flag(struct hantro_vp9_dec_hw_ctx *vp9_ctx,
const struct v4l2_vp9_segmentation *seg,
unsigned int feature,
unsigned int segid)
{
u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature);
vp9_ctx->feature_data[segid][feature] = seg->feature_data[segid][feature];
vp9_ctx->feature_enabled[segid] &= ~mask;
vp9_ctx->feature_enabled[segid] |= (seg->feature_enabled[segid] & mask);
}
static inline s16 clip3(s16 x, s16 y, s16 z)
{
return (z < x) ? x : (z > y) ? y : z;
}
static s16 feat_val_clip3(s16 feat_val, s16 feature_data, bool absolute, u8 clip)
{
if (absolute)
return feature_data;
return clip3(0, 255, feat_val + feature_data);
}
static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
const struct v4l2_vp9_segmentation *seg;
s16 feat_val;
unsigned char feat_id;
unsigned int segid;
bool segment_enabled, absolute, update_data;
static const struct hantro_reg seg_regs[8][V4L2_VP9_SEG_LVL_MAX] = {
{ vp9_quant_seg0, vp9_filt_level_seg0, vp9_refpic_seg0, vp9_skip_seg0 },
{ vp9_quant_seg1, vp9_filt_level_seg1, vp9_refpic_seg1, vp9_skip_seg1 },
{ vp9_quant_seg2, vp9_filt_level_seg2, vp9_refpic_seg2, vp9_skip_seg2 },
{ vp9_quant_seg3, vp9_filt_level_seg3, vp9_refpic_seg3, vp9_skip_seg3 },
{ vp9_quant_seg4, vp9_filt_level_seg4, vp9_refpic_seg4, vp9_skip_seg4 },
{ vp9_quant_seg5, vp9_filt_level_seg5, vp9_refpic_seg5, vp9_skip_seg5 },
{ vp9_quant_seg6, vp9_filt_level_seg6, vp9_refpic_seg6, vp9_skip_seg6 },
{ vp9_quant_seg7, vp9_filt_level_seg7, vp9_refpic_seg7, vp9_skip_seg7 },
};
segment_enabled = !!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED);
hantro_reg_write(ctx->dev, &vp9_segment_e, segment_enabled);
hantro_reg_write(ctx->dev, &vp9_segment_upd_e,
!!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP));
hantro_reg_write(ctx->dev, &vp9_segment_temp_upd_e,
!!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE));
seg = &dec_params->seg;
absolute = !!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE);
update_data = !!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA);
for (segid = 0; segid < 8; ++segid) {
/* Quantizer segment feature */
feat_id = V4L2_VP9_SEG_LVL_ALT_Q;
feat_val = dec_params->quant.base_q_idx;
if (segment_enabled) {
if (update_data)
update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
feat_val = feat_val_clip3(feat_val,
vp9_ctx->feature_data[segid][feat_id],
absolute, 255);
}
hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
/* Loop filter segment feature */
feat_id = V4L2_VP9_SEG_LVL_ALT_L;
feat_val = dec_params->lf.level;
if (segment_enabled) {
if (update_data)
update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
feat_val = feat_val_clip3(feat_val,
vp9_ctx->feature_data[segid][feat_id],
absolute, 63);
}
hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
/* Reference frame segment feature */
feat_id = V4L2_VP9_SEG_LVL_REF_FRAME;
feat_val = 0;
if (segment_enabled) {
if (update_data)
update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) &&
v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
feat_val = vp9_ctx->feature_data[segid][feat_id] + 1;
}
hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
/* Skip segment feature */
feat_id = V4L2_VP9_SEG_LVL_SKIP;
feat_val = 0;
if (segment_enabled) {
if (update_data)
update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
feat_val = v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled,
feat_id, segid) ? 1 : 0;
}
hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
}
}
static void config_loop_filter(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params)
{
bool d = dec_params->lf.flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED;
hantro_reg_write(ctx->dev, &vp9_filt_level, dec_params->lf.level);
hantro_reg_write(ctx->dev, &g2_out_filtering_dis, dec_params->lf.level == 0);
hantro_reg_write(ctx->dev, &vp9_filt_sharpness, dec_params->lf.sharpness);
hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_0, d ? dec_params->lf.ref_deltas[0] : 0);
hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_1, d ? dec_params->lf.ref_deltas[1] : 0);
hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_2, d ? dec_params->lf.ref_deltas[2] : 0);
hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_3, d ? dec_params->lf.ref_deltas[3] : 0);
hantro_reg_write(ctx->dev, &vp9_filt_mb_adj_0, d ? dec_params->lf.mode_deltas[0] : 0);
hantro_reg_write(ctx->dev, &vp9_filt_mb_adj_1, d ? dec_params->lf.mode_deltas[1] : 0);
}
static void config_picture_dimensions(struct hantro_ctx *ctx, struct hantro_decoded_buffer *dst)
{
u32 pic_w_4x4, pic_h_4x4;
hantro_reg_write(ctx->dev, &g2_pic_width_in_cbs, (dst->vp9.width + 7) / 8);
hantro_reg_write(ctx->dev, &g2_pic_height_in_cbs, (dst->vp9.height + 7) / 8);
pic_w_4x4 = roundup(dst->vp9.width, 8) >> 2;
pic_h_4x4 = roundup(dst->vp9.height, 8) >> 2;
hantro_reg_write(ctx->dev, &g2_pic_width_4x4, pic_w_4x4);
hantro_reg_write(ctx->dev, &g2_pic_height_4x4, pic_h_4x4);
}
static void
config_bit_depth(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params)
{
if (ctx->dev->variant->legacy_regs) {
hantro_reg_write(ctx->dev, &g2_bit_depth_y, dec_params->bit_depth);
hantro_reg_write(ctx->dev, &g2_bit_depth_c, dec_params->bit_depth);
hantro_reg_write(ctx->dev, &g2_pix_shift, 0);
} else {
hantro_reg_write(ctx->dev, &g2_bit_depth_y_minus8, dec_params->bit_depth - 8);
hantro_reg_write(ctx->dev, &g2_bit_depth_c_minus8, dec_params->bit_depth - 8);
}
}
static inline bool is_lossless(const struct v4l2_vp9_quantization *quant)
{
return quant->base_q_idx == 0 && quant->delta_q_uv_ac == 0 &&
quant->delta_q_uv_dc == 0 && quant->delta_q_y_dc == 0;
}
static void
config_quant(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params)
{
hantro_reg_write(ctx->dev, &vp9_qp_delta_y_dc, dec_params->quant.delta_q_y_dc);
hantro_reg_write(ctx->dev, &vp9_qp_delta_ch_dc, dec_params->quant.delta_q_uv_dc);
hantro_reg_write(ctx->dev, &vp9_qp_delta_ch_ac, dec_params->quant.delta_q_uv_ac);
hantro_reg_write(ctx->dev, &vp9_lossless_e, is_lossless(&dec_params->quant));
}
static u32
hantro_interp_filter_from_v4l2(unsigned int interpolation_filter)
{
switch (interpolation_filter) {
case V4L2_VP9_INTERP_FILTER_EIGHTTAP:
return 0x1;
case V4L2_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH:
return 0;
case V4L2_VP9_INTERP_FILTER_EIGHTTAP_SHARP:
return 0x2;
case V4L2_VP9_INTERP_FILTER_BILINEAR:
return 0x3;
case V4L2_VP9_INTERP_FILTER_SWITCHABLE:
return 0x4;
}
return 0;
}
static void
config_others(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params,
bool intra_only, bool resolution_change)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
hantro_reg_write(ctx->dev, &g2_idr_pic_e, intra_only);
hantro_reg_write(ctx->dev, &vp9_transform_mode, vp9_ctx->cur.tx_mode);
hantro_reg_write(ctx->dev, &vp9_mcomp_filt_type, intra_only ?
0 : hantro_interp_filter_from_v4l2(dec_params->interpolation_filter));
hantro_reg_write(ctx->dev, &vp9_high_prec_mv_e,
!!(dec_params->flags & V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV));
hantro_reg_write(ctx->dev, &vp9_comp_pred_mode, dec_params->reference_mode);
hantro_reg_write(ctx->dev, &g2_tempor_mvp_e,
!(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) &&
!(vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) &&
!(dec_params->flags & V4L2_VP9_FRAME_FLAG_INTRA_ONLY) &&
!resolution_change &&
vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME
);
hantro_reg_write(ctx->dev, &g2_write_mvs_e,
!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME));
}
static void
config_compound_reference(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp9_frame *dec_params)
{
u32 comp_fixed_ref, comp_var_ref[2];
bool last_ref_frame_sign_bias;
bool golden_ref_frame_sign_bias;
bool alt_ref_frame_sign_bias;
bool comp_ref_allowed = 0;
comp_fixed_ref = 0;
comp_var_ref[0] = 0;
comp_var_ref[1] = 0;
last_ref_frame_sign_bias = dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_LAST;
golden_ref_frame_sign_bias = dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_GOLDEN;
alt_ref_frame_sign_bias = dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_ALT;
/* 6.3.12 Frame reference mode syntax */
comp_ref_allowed |= golden_ref_frame_sign_bias != last_ref_frame_sign_bias;
comp_ref_allowed |= alt_ref_frame_sign_bias != last_ref_frame_sign_bias;
if (comp_ref_allowed) {
if (last_ref_frame_sign_bias ==
golden_ref_frame_sign_bias) {
comp_fixed_ref = ALTREF_FRAME;
comp_var_ref[0] = LAST_FRAME;
comp_var_ref[1] = GOLDEN_FRAME;
} else if (last_ref_frame_sign_bias ==
alt_ref_frame_sign_bias) {
comp_fixed_ref = GOLDEN_FRAME;
comp_var_ref[0] = LAST_FRAME;
comp_var_ref[1] = ALTREF_FRAME;
} else {
comp_fixed_ref = LAST_FRAME;
comp_var_ref[0] = GOLDEN_FRAME;
comp_var_ref[1] = ALTREF_FRAME;
}
}
hantro_reg_write(ctx->dev, &vp9_comp_pred_fixed_ref, comp_fixed_ref);
hantro_reg_write(ctx->dev, &vp9_comp_pred_var_ref0, comp_var_ref[0]);
hantro_reg_write(ctx->dev, &vp9_comp_pred_var_ref1, comp_var_ref[1]);
}
#define INNER_LOOP \
do { \
for (m = 0; m < ARRAY_SIZE(adaptive->coef[0][0][0][0]); ++m) { \
memcpy(adaptive->coef[i][j][k][l][m], \
probs->coef[i][j][k][l][m], \
sizeof(probs->coef[i][j][k][l][m])); \
\
adaptive->coef[i][j][k][l][m][3] = 0; \
} \
} while (0)
static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
struct hantro_aux_buf *misc = &vp9_ctx->misc;
struct hantro_g2_all_probs *all_probs = misc->cpu;
struct hantro_g2_probs *adaptive;
struct hantro_g2_mv_probs *mv;
const struct v4l2_vp9_segmentation *seg = &dec_params->seg;
const struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables;
int i, j, k, l, m;
for (i = 0; i < ARRAY_SIZE(all_probs->kf_y_mode_prob); ++i)
for (j = 0; j < ARRAY_SIZE(all_probs->kf_y_mode_prob[0]); ++j) {
memcpy(all_probs->kf_y_mode_prob[i][j],
v4l2_vp9_kf_y_mode_prob[i][j],
ARRAY_SIZE(all_probs->kf_y_mode_prob[i][j]));
all_probs->kf_y_mode_prob_tail[i][j][0] =
v4l2_vp9_kf_y_mode_prob[i][j][8];
}
memcpy(all_probs->mb_segment_tree_probs, seg->tree_probs,
sizeof(all_probs->mb_segment_tree_probs));
memcpy(all_probs->segment_pred_probs, seg->pred_probs,
sizeof(all_probs->segment_pred_probs));
for (i = 0; i < ARRAY_SIZE(all_probs->kf_uv_mode_prob); ++i) {
memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob[i],
ARRAY_SIZE(all_probs->kf_uv_mode_prob[i]));
all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob[i][8];
}
adaptive = &all_probs->probs;
for (i = 0; i < ARRAY_SIZE(adaptive->inter_mode); ++i) {
memcpy(adaptive->inter_mode[i], probs->inter_mode[i],
ARRAY_SIZE(probs->inter_mode[i]));
adaptive->inter_mode[i][3] = 0;
}
memcpy(adaptive->is_inter, probs->is_inter, sizeof(adaptive->is_inter));
for (i = 0; i < ARRAY_SIZE(adaptive->uv_mode); ++i) {
memcpy(adaptive->uv_mode[i], probs->uv_mode[i],
sizeof(adaptive->uv_mode[i]));
adaptive->uv_mode_tail[i][0] = probs->uv_mode[i][8];
}
memcpy(adaptive->tx8, probs->tx8, sizeof(adaptive->tx8));
memcpy(adaptive->tx16, probs->tx16, sizeof(adaptive->tx16));
memcpy(adaptive->tx32, probs->tx32, sizeof(adaptive->tx32));
for (i = 0; i < ARRAY_SIZE(adaptive->y_mode); ++i) {
memcpy(adaptive->y_mode[i], probs->y_mode[i],
ARRAY_SIZE(adaptive->y_mode[i]));
adaptive->y_mode_tail[i][0] = probs->y_mode[i][8];
}
for (i = 0; i < ARRAY_SIZE(adaptive->partition[0]); ++i) {
memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs[i],
sizeof(v4l2_vp9_kf_partition_probs[i]));
adaptive->partition[0][i][3] = 0;
}
for (i = 0; i < ARRAY_SIZE(adaptive->partition[1]); ++i) {
memcpy(adaptive->partition[1][i], probs->partition[i],
sizeof(probs->partition[i]));
adaptive->partition[1][i][3] = 0;
}
memcpy(adaptive->interp_filter, probs->interp_filter,
sizeof(adaptive->interp_filter));
memcpy(adaptive->comp_mode, probs->comp_mode, sizeof(adaptive->comp_mode));
memcpy(adaptive->skip, probs->skip, sizeof(adaptive->skip));
mv = &adaptive->mv;
memcpy(mv->joint, probs->mv.joint, sizeof(mv->joint));
memcpy(mv->sign, probs->mv.sign, sizeof(mv->sign));
memcpy(mv->class0_bit, probs->mv.class0_bit, sizeof(mv->class0_bit));
memcpy(mv->fr, probs->mv.fr, sizeof(mv->fr));
memcpy(mv->class0_hp, probs->mv.class0_hp, sizeof(mv->class0_hp));
memcpy(mv->hp, probs->mv.hp, sizeof(mv->hp));
memcpy(mv->classes, probs->mv.classes, sizeof(mv->classes));
memcpy(mv->class0_fr, probs->mv.class0_fr, sizeof(mv->class0_fr));
memcpy(mv->bits, probs->mv.bits, sizeof(mv->bits));
memcpy(adaptive->single_ref, probs->single_ref, sizeof(adaptive->single_ref));
memcpy(adaptive->comp_ref, probs->comp_ref, sizeof(adaptive->comp_ref));
for (i = 0; i < ARRAY_SIZE(adaptive->coef); ++i)
for (j = 0; j < ARRAY_SIZE(adaptive->coef[0]); ++j)
for (k = 0; k < ARRAY_SIZE(adaptive->coef[0][0]); ++k)
for (l = 0; l < ARRAY_SIZE(adaptive->coef[0][0][0]); ++l)
INNER_LOOP;
hantro_write_addr(ctx->dev, G2_VP9_PROBS_ADDR, misc->dma);
}
static void config_counts(struct hantro_ctx *ctx)
{
struct hantro_vp9_dec_hw_ctx *vp9_dec = &ctx->vp9_dec;
struct hantro_aux_buf *misc = &vp9_dec->misc;
dma_addr_t addr = misc->dma + vp9_dec->ctx_counters_offset;
hantro_write_addr(ctx->dev, G2_VP9_CTX_COUNT_ADDR, addr);
}
static void config_seg_map(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp9_frame *dec_params,
bool intra_only, bool update_map)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
struct hantro_aux_buf *segment_map = &vp9_ctx->segment_map;
dma_addr_t addr;
if (intra_only ||
(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT)) {
memset(segment_map->cpu, 0, segment_map->size);
memset(vp9_ctx->feature_data, 0, sizeof(vp9_ctx->feature_data));
memset(vp9_ctx->feature_enabled, 0, sizeof(vp9_ctx->feature_enabled));
}
addr = segment_map->dma + vp9_ctx->active_segment * vp9_ctx->segment_map_size;
hantro_write_addr(ctx->dev, G2_VP9_SEGMENT_READ_ADDR, addr);
addr = segment_map->dma + (1 - vp9_ctx->active_segment) * vp9_ctx->segment_map_size;
hantro_write_addr(ctx->dev, G2_VP9_SEGMENT_WRITE_ADDR, addr);
if (update_map)
vp9_ctx->active_segment = 1 - vp9_ctx->active_segment;
}
static void
config_source(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params,
struct vb2_v4l2_buffer *vb2_src)
{
dma_addr_t stream_base, tmp_addr;
unsigned int headers_size;
u32 src_len, start_bit, src_buf_len;
headers_size = dec_params->uncompressed_header_size
+ dec_params->compressed_header_size;
stream_base = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0);
tmp_addr = stream_base + headers_size;
if (ctx->dev->variant->legacy_regs)
hantro_write_addr(ctx->dev, G2_STREAM_ADDR, (tmp_addr & ~0xf));
else
hantro_write_addr(ctx->dev, G2_STREAM_ADDR, stream_base);
start_bit = (tmp_addr & 0xf) * 8;
hantro_reg_write(ctx->dev, &g2_start_bit, start_bit);
src_len = vb2_get_plane_payload(&vb2_src->vb2_buf, 0);
src_len += start_bit / 8 - headers_size;
hantro_reg_write(ctx->dev, &g2_stream_len, src_len);
if (!ctx->dev->variant->legacy_regs) {
tmp_addr &= ~0xf;
hantro_reg_write(ctx->dev, &g2_strm_start_offset, tmp_addr - stream_base);
src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0);
hantro_reg_write(ctx->dev, &g2_strm_buffer_len, src_buf_len);
}
}
static void
config_registers(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params,
struct vb2_v4l2_buffer *vb2_src, struct vb2_v4l2_buffer *vb2_dst)
{
struct hantro_decoded_buffer *dst, *last, *mv_ref;
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
const struct v4l2_vp9_segmentation *seg;
bool intra_only, resolution_change;
/* vp9 stuff */
dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf);
if (vp9_ctx->last.valid)
last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
else
last = dst;
update_dec_buf_info(dst, dec_params);
update_ctx_cur_info(vp9_ctx, dst, dec_params);
seg = &dec_params->seg;
intra_only = !!(dec_params->flags &
(V4L2_VP9_FRAME_FLAG_KEY_FRAME |
V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
if (!intra_only &&
!(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
vp9_ctx->last.valid)
mv_ref = last;
else
mv_ref = dst;
resolution_change = dst->vp9.width != last->vp9.width ||
dst->vp9.height != last->vp9.height;
/* configure basic registers */
hantro_reg_write(ctx->dev, &g2_mode, VP9_DEC_MODE);
if (!ctx->dev->variant->legacy_regs) {
hantro_reg_write(ctx->dev, &g2_strm_swap, 0xf);
hantro_reg_write(ctx->dev, &g2_dirmv_swap, 0xf);
hantro_reg_write(ctx->dev, &g2_compress_swap, 0xf);
hantro_reg_write(ctx->dev, &g2_ref_compress_bypass, 1);
} else {
hantro_reg_write(ctx->dev, &g2_strm_swap_old, 0x1f);
hantro_reg_write(ctx->dev, &g2_pic_swap, 0x10);
hantro_reg_write(ctx->dev, &g2_dirmv_swap_old, 0x10);
hantro_reg_write(ctx->dev, &g2_tab0_swap_old, 0x10);
hantro_reg_write(ctx->dev, &g2_tab1_swap_old, 0x10);
hantro_reg_write(ctx->dev, &g2_tab2_swap_old, 0x10);
hantro_reg_write(ctx->dev, &g2_tab3_swap_old, 0x10);
hantro_reg_write(ctx->dev, &g2_rscan_swap, 0x10);
}
hantro_reg_write(ctx->dev, &g2_buswidth, BUS_WIDTH_128);
hantro_reg_write(ctx->dev, &g2_max_burst, 16);
hantro_reg_write(ctx->dev, &g2_apf_threshold, 8);
hantro_reg_write(ctx->dev, &g2_clk_gate_e, 1);
hantro_reg_write(ctx->dev, &g2_max_cb_size, 6);
hantro_reg_write(ctx->dev, &g2_min_cb_size, 3);
if (ctx->dev->variant->double_buffer)
hantro_reg_write(ctx->dev, &g2_double_buffer_e, 1);
config_output(ctx, dst, dec_params);
if (!intra_only)
config_ref_registers(ctx, dec_params, dst, mv_ref);
config_tiles(ctx, dec_params, dst);
config_segment(ctx, dec_params);
config_loop_filter(ctx, dec_params);
config_picture_dimensions(ctx, dst);
config_bit_depth(ctx, dec_params);
config_quant(ctx, dec_params);
config_others(ctx, dec_params, intra_only, resolution_change);
config_compound_reference(ctx, dec_params);
config_probs(ctx, dec_params);
config_counts(ctx);
config_seg_map(ctx, dec_params, intra_only,
seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP);
config_source(ctx, dec_params, vb2_src);
}
int hantro_g2_vp9_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp9_frame *decode_params;
struct vb2_v4l2_buffer *src;
struct vb2_v4l2_buffer *dst;
int ret;
ret = start_prepare_run(ctx, &decode_params);
if (ret) {
hantro_end_prepare_run(ctx);
return ret;
}
src = hantro_get_src_buf(ctx);
dst = hantro_get_dst_buf(ctx);
config_registers(ctx, decode_params, src, dst);
hantro_end_prepare_run(ctx);
vdpu_write(ctx->dev, G2_REG_INTERRUPT_DEC_E, G2_REG_INTERRUPT);
return 0;
}
#define copy_tx_and_skip(p1, p2) \
do { \
memcpy((p1)->tx8, (p2)->tx8, sizeof((p1)->tx8)); \
memcpy((p1)->tx16, (p2)->tx16, sizeof((p1)->tx16)); \
memcpy((p1)->tx32, (p2)->tx32, sizeof((p1)->tx32)); \
memcpy((p1)->skip, (p2)->skip, sizeof((p1)->skip)); \
} while (0)
void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
unsigned int fctx_idx;
if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX))
goto out_update_last;
fctx_idx = vp9_ctx->cur.frame_context_idx;
if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) {
/* error_resilient_mode == 0 && frame_parallel_decoding_mode == 0 */
struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables;
bool frame_is_intra = vp9_ctx->cur.flags &
(V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY);
struct tx_and_skip {
u8 tx8[2][1];
u8 tx16[2][2];
u8 tx32[2][3];
u8 skip[3];
} _tx_skip, *tx_skip = &_tx_skip;
struct v4l2_vp9_frame_symbol_counts *counts;
struct symbol_counts *hantro_cnts;
u32 tx16p[2][4];
int i;
/* buffer the forward-updated TX and skip probs */
if (frame_is_intra)
copy_tx_and_skip(tx_skip, probs);
/* 6.1.2 refresh_probs(): load_probs() and load_probs2() */
*probs = vp9_ctx->frame_context[fctx_idx];
/* if FrameIsIntra then undo the effect of load_probs2() */
if (frame_is_intra)
copy_tx_and_skip(probs, tx_skip);
counts = &vp9_ctx->cnts;
hantro_cnts = vp9_ctx->misc.cpu + vp9_ctx->ctx_counters_offset;
for (i = 0; i < ARRAY_SIZE(tx16p); ++i) {
memcpy(tx16p[i],
hantro_cnts->tx16x16_count[i],
sizeof(hantro_cnts->tx16x16_count[0]));
tx16p[i][3] = 0;
}
counts->tx16p = &tx16p;
v4l2_vp9_adapt_coef_probs(probs, counts,
!vp9_ctx->last.valid ||
vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME,
frame_is_intra);
if (!frame_is_intra) {
/* load_probs2() already done */
u32 mv_mode[7][4];
for (i = 0; i < ARRAY_SIZE(mv_mode); ++i) {
mv_mode[i][0] = hantro_cnts->inter_mode_counts[i][1][0];
mv_mode[i][1] = hantro_cnts->inter_mode_counts[i][2][0];
mv_mode[i][2] = hantro_cnts->inter_mode_counts[i][0][0];
mv_mode[i][3] = hantro_cnts->inter_mode_counts[i][2][1];
}
counts->mv_mode = &mv_mode;
v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts,
vp9_ctx->cur.reference_mode,
vp9_ctx->cur.interpolation_filter,
vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags);
}
}
vp9_ctx->frame_context[fctx_idx] = vp9_ctx->probability_tables;
out_update_last:
vp9_ctx->last = vp9_ctx->cur;
}
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*/
#include <linux/unaligned.h>
#include <media/v4l2-mem2mem.h>
#include "hantro_jpeg.h"
#include "hantro.h"
#include "hantro_v4l2.h"
#include "hantro_hw.h"
#include "hantro_h1_regs.h"
#define H1_JPEG_QUANT_TABLE_COUNT 16
static void hantro_h1_set_src_img_ctrl(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
u32 overfill_r, overfill_b;
u32 reg;
/*
* The format width and height are already macroblock aligned
* by .vidioc_s_fmt_vid_cap_mplane() callback. Destination
* format width and height can be further modified by
* .vidioc_s_selection(), and the width is 4-aligned.
*/
overfill_r = ctx->src_fmt.width - ctx->dst_fmt.width;
overfill_b = ctx->src_fmt.height - ctx->dst_fmt.height;
reg = H1_REG_IN_IMG_CTRL_ROW_LEN(ctx->src_fmt.width)
| H1_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r / 4)
| H1_REG_IN_IMG_CTRL_OVRFLB(overfill_b)
| H1_REG_IN_IMG_CTRL_FMT(ctx->vpu_src_fmt->enc_fmt);
vepu_write_relaxed(vpu, reg, H1_REG_IN_IMG_CTRL);
}
static void hantro_h1_jpeg_enc_set_buffers(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
struct vb2_buffer *src_buf,
struct vb2_buffer *dst_buf)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
dma_addr_t src[3];
u32 size_left;
size_left = vb2_plane_size(dst_buf, 0) - ctx->vpu_dst_fmt->header_size;
if (WARN_ON(vb2_plane_size(dst_buf, 0) < ctx->vpu_dst_fmt->header_size))
size_left = 0;
WARN_ON(pix_fmt->num_planes > 3);
vepu_write_relaxed(vpu, vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
ctx->vpu_dst_fmt->header_size,
H1_REG_ADDR_OUTPUT_STREAM);
vepu_write_relaxed(vpu, size_left, H1_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
/* single plane formats we supported are all interlaced */
vepu_write_relaxed(vpu, src[0], H1_REG_ADDR_IN_PLANE_0);
} else if (pix_fmt->num_planes == 2) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
src[1] = vb2_dma_contig_plane_dma_addr(src_buf, 1);
vepu_write_relaxed(vpu, src[0], H1_REG_ADDR_IN_PLANE_0);
vepu_write_relaxed(vpu, src[1], H1_REG_ADDR_IN_PLANE_1);
} else {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
src[1] = vb2_dma_contig_plane_dma_addr(src_buf, 1);
src[2] = vb2_dma_contig_plane_dma_addr(src_buf, 2);
vepu_write_relaxed(vpu, src[0], H1_REG_ADDR_IN_PLANE_0);
vepu_write_relaxed(vpu, src[1], H1_REG_ADDR_IN_PLANE_1);
vepu_write_relaxed(vpu, src[2], H1_REG_ADDR_IN_PLANE_2);
}
}
static void
hantro_h1_jpeg_enc_set_qtable(struct hantro_dev *vpu,
unsigned char *luma_qtable,
unsigned char *chroma_qtable)
{
u32 reg, i;
__be32 *luma_qtable_p;
__be32 *chroma_qtable_p;
luma_qtable_p = (__be32 *)luma_qtable;
chroma_qtable_p = (__be32 *)chroma_qtable;
/*
* Quantization table registers must be written in contiguous blocks.
* DO NOT collapse the below two "for" loops into one.
*/
for (i = 0; i < H1_JPEG_QUANT_TABLE_COUNT; i++) {
reg = get_unaligned_be32(&luma_qtable_p[i]);
vepu_write_relaxed(vpu, reg, H1_REG_JPEG_LUMA_QUAT(i));
}
for (i = 0; i < H1_JPEG_QUANT_TABLE_COUNT; i++) {
reg = get_unaligned_be32(&chroma_qtable_p[i]);
vepu_write_relaxed(vpu, reg, H1_REG_JPEG_CHROMA_QUAT(i));
}
}
int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
struct hantro_jpeg_ctx jpeg_ctx;
u32 reg;
src_buf = hantro_get_src_buf(ctx);
dst_buf = hantro_get_dst_buf(ctx);
hantro_start_prepare_run(ctx);
memset(&jpeg_ctx, 0, sizeof(jpeg_ctx));
jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
jpeg_ctx.width = ctx->dst_fmt.width;
jpeg_ctx.height = ctx->dst_fmt.height;
jpeg_ctx.quality = ctx->jpeg_quality;
hantro_jpeg_header_assemble(&jpeg_ctx);
/* Switch to JPEG encoder mode before writing registers */
vepu_write_relaxed(vpu, H1_REG_ENC_CTRL_ENC_MODE_JPEG,
H1_REG_ENC_CTRL);
hantro_h1_set_src_img_ctrl(vpu, ctx);
hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf,
&dst_buf->vb2_buf);
hantro_h1_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable,
jpeg_ctx.hw_chroma_qtable);
reg = H1_REG_AXI_CTRL_OUTPUT_SWAP16
| H1_REG_AXI_CTRL_INPUT_SWAP16
| H1_REG_AXI_CTRL_BURST_LEN(16)
| H1_REG_AXI_CTRL_OUTPUT_SWAP32
| H1_REG_AXI_CTRL_INPUT_SWAP32
| H1_REG_AXI_CTRL_OUTPUT_SWAP8
| H1_REG_AXI_CTRL_INPUT_SWAP8;
/* Make sure that all registers are written at this point. */
vepu_write(vpu, reg, H1_REG_AXI_CTRL);
reg = H1_REG_ENC_CTRL_WIDTH(MB_WIDTH(ctx->src_fmt.width))
| H1_REG_ENC_CTRL_HEIGHT(MB_HEIGHT(ctx->src_fmt.height))
| H1_REG_ENC_CTRL_ENC_MODE_JPEG
| H1_REG_ENC_PIC_INTRA
| H1_REG_ENC_CTRL_EN_BIT;
hantro_end_prepare_run(ctx);
vepu_write(vpu, reg, H1_REG_ENC_CTRL);
return 0;
}
void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8;
struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx);
vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
ctx->vpu_dst_fmt->header_size + bytesused);
}
@@ -0,0 +1,154 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VPU codec driver
*
* Copyright 2018 Google LLC.
* Tomasz Figa <tfiga@chromium.org>
*/
#ifndef HANTRO_H1_REGS_H_
#define HANTRO_H1_REGS_H_
/* Encoder registers. */
#define H1_REG_INTERRUPT 0x004
#define H1_REG_INTERRUPT_FRAME_RDY BIT(2)
#define H1_REG_INTERRUPT_DIS_BIT BIT(1)
#define H1_REG_INTERRUPT_BIT BIT(0)
#define H1_REG_AXI_CTRL 0x008
#define H1_REG_AXI_CTRL_OUTPUT_SWAP16 BIT(15)
#define H1_REG_AXI_CTRL_INPUT_SWAP16 BIT(14)
#define H1_REG_AXI_CTRL_BURST_LEN(x) ((x) << 8)
#define H1_REG_AXI_CTRL_GATE_BIT BIT(4)
#define H1_REG_AXI_CTRL_OUTPUT_SWAP32 BIT(3)
#define H1_REG_AXI_CTRL_INPUT_SWAP32 BIT(2)
#define H1_REG_AXI_CTRL_OUTPUT_SWAP8 BIT(1)
#define H1_REG_AXI_CTRL_INPUT_SWAP8 BIT(0)
#define H1_REG_ADDR_OUTPUT_STREAM 0x014
#define H1_REG_ADDR_OUTPUT_CTRL 0x018
#define H1_REG_ADDR_REF_LUMA 0x01c
#define H1_REG_ADDR_REF_CHROMA 0x020
#define H1_REG_ADDR_REC_LUMA 0x024
#define H1_REG_ADDR_REC_CHROMA 0x028
#define H1_REG_ADDR_IN_PLANE_0 0x02c
#define H1_REG_ADDR_IN_PLANE_1 0x030
#define H1_REG_ADDR_IN_PLANE_2 0x034
#define H1_REG_ENC_CTRL 0x038
#define H1_REG_ENC_CTRL_TIMEOUT_EN BIT(31)
#define H1_REG_ENC_CTRL_NAL_MODE_BIT BIT(29)
#define H1_REG_ENC_CTRL_WIDTH(w) ((w) << 19)
#define H1_REG_ENC_CTRL_HEIGHT(h) ((h) << 10)
#define H1_REG_ENC_PIC_INTER (0x0 << 3)
#define H1_REG_ENC_PIC_INTRA (0x1 << 3)
#define H1_REG_ENC_PIC_MVCINTER (0x2 << 3)
#define H1_REG_ENC_CTRL_ENC_MODE_H264 (0x3 << 1)
#define H1_REG_ENC_CTRL_ENC_MODE_JPEG (0x2 << 1)
#define H1_REG_ENC_CTRL_ENC_MODE_VP8 (0x1 << 1)
#define H1_REG_ENC_CTRL_EN_BIT BIT(0)
#define H1_REG_IN_IMG_CTRL 0x03c
#define H1_REG_IN_IMG_CTRL_ROW_LEN(x) ((x) << 12)
#define H1_REG_IN_IMG_CTRL_OVRFLR_D4(x) ((x) << 10)
#define H1_REG_IN_IMG_CTRL_OVRFLB(x) ((x) << 6)
#define H1_REG_IN_IMG_CTRL_FMT(x) ((x) << 2)
#define H1_REG_ENC_CTRL0 0x040
#define H1_REG_ENC_CTRL0_INIT_QP(x) ((x) << 26)
#define H1_REG_ENC_CTRL0_SLICE_ALPHA(x) ((x) << 22)
#define H1_REG_ENC_CTRL0_SLICE_BETA(x) ((x) << 18)
#define H1_REG_ENC_CTRL0_CHROMA_QP_OFFSET(x) ((x) << 13)
#define H1_REG_ENC_CTRL0_FILTER_DIS(x) ((x) << 5)
#define H1_REG_ENC_CTRL0_IDR_PICID(x) ((x) << 1)
#define H1_REG_ENC_CTRL0_CONSTR_INTRA_PRED BIT(0)
#define H1_REG_ENC_CTRL1 0x044
#define H1_REG_ENC_CTRL1_PPS_ID(x) ((x) << 24)
#define H1_REG_ENC_CTRL1_INTRA_PRED_MODE(x) ((x) << 16)
#define H1_REG_ENC_CTRL1_FRAME_NUM(x) ((x))
#define H1_REG_ENC_CTRL2 0x048
#define H1_REG_ENC_CTRL2_DEBLOCKING_FILTER_MODE(x) ((x) << 30)
#define H1_REG_ENC_CTRL2_H264_SLICE_SIZE(x) ((x) << 23)
#define H1_REG_ENC_CTRL2_DISABLE_QUARTER_PIXMV BIT(22)
#define H1_REG_ENC_CTRL2_TRANS8X8_MODE_EN BIT(21)
#define H1_REG_ENC_CTRL2_CABAC_INIT_IDC(x) ((x) << 19)
#define H1_REG_ENC_CTRL2_ENTROPY_CODING_MODE BIT(18)
#define H1_REG_ENC_CTRL2_H264_INTER4X4_MODE BIT(17)
#define H1_REG_ENC_CTRL2_H264_STREAM_MODE BIT(16)
#define H1_REG_ENC_CTRL2_INTRA16X16_MODE(x) ((x))
#define H1_REG_ENC_CTRL3 0x04c
#define H1_REG_ENC_CTRL3_MUTIMV_EN BIT(30)
#define H1_REG_ENC_CTRL3_MV_PENALTY_1_4P(x) ((x) << 20)
#define H1_REG_ENC_CTRL3_MV_PENALTY_4P(x) ((x) << 10)
#define H1_REG_ENC_CTRL3_MV_PENALTY_1P(x) ((x))
#define H1_REG_ENC_CTRL4 0x050
#define H1_REG_ENC_CTRL4_MV_PENALTY_16X8_8X16(x) ((x) << 20)
#define H1_REG_ENC_CTRL4_MV_PENALTY_8X8(x) ((x) << 10)
#define H1_REG_ENC_CTRL4_8X4_4X8(x) ((x))
#define H1_REG_ENC_CTRL5 0x054
#define H1_REG_ENC_CTRL5_MACROBLOCK_PENALTY(x) ((x) << 24)
#define H1_REG_ENC_CTRL5_COMPLETE_SLICES(x) ((x) << 16)
#define H1_REG_ENC_CTRL5_INTER_MODE(x) ((x))
#define H1_REG_STR_HDR_REM_MSB 0x058
#define H1_REG_STR_HDR_REM_LSB 0x05c
#define H1_REG_STR_BUF_LIMIT 0x060
#define H1_REG_MAD_CTRL 0x064
#define H1_REG_MAD_CTRL_QP_ADJUST(x) ((x) << 28)
#define H1_REG_MAD_CTRL_MAD_THRESHOLD(x) ((x) << 22)
#define H1_REG_MAD_CTRL_QP_SUM_DIV2(x) ((x))
#define H1_REG_ADDR_VP8_PROB_CNT 0x068
#define H1_REG_QP_VAL 0x06c
#define H1_REG_QP_VAL_LUM(x) ((x) << 26)
#define H1_REG_QP_VAL_MAX(x) ((x) << 20)
#define H1_REG_QP_VAL_MIN(x) ((x) << 14)
#define H1_REG_QP_VAL_CHECKPOINT_DISTAN(x) ((x))
#define H1_REG_VP8_QP_VAL(i) (0x06c + ((i) * 0x4))
#define H1_REG_CHECKPOINT(i) (0x070 + ((i) * 0x4))
#define H1_REG_CHECKPOINT_CHECK0(x) (((x) & 0xffff))
#define H1_REG_CHECKPOINT_CHECK1(x) (((x) & 0xffff) << 16)
#define H1_REG_CHECKPOINT_RESULT(x) ((((x) >> (16 - 16 \
* (i & 1))) & 0xffff) \
* 32)
#define H1_REG_CHKPT_WORD_ERR(i) (0x084 + ((i) * 0x4))
#define H1_REG_CHKPT_WORD_ERR_CHK0(x) (((x) & 0xffff))
#define H1_REG_CHKPT_WORD_ERR_CHK1(x) (((x) & 0xffff) << 16)
#define H1_REG_VP8_BOOL_ENC 0x08c
#define H1_REG_CHKPT_DELTA_QP 0x090
#define H1_REG_CHKPT_DELTA_QP_CHK0(x) (((x) & 0x0f) << 0)
#define H1_REG_CHKPT_DELTA_QP_CHK1(x) (((x) & 0x0f) << 4)
#define H1_REG_CHKPT_DELTA_QP_CHK2(x) (((x) & 0x0f) << 8)
#define H1_REG_CHKPT_DELTA_QP_CHK3(x) (((x) & 0x0f) << 12)
#define H1_REG_CHKPT_DELTA_QP_CHK4(x) (((x) & 0x0f) << 16)
#define H1_REG_CHKPT_DELTA_QP_CHK5(x) (((x) & 0x0f) << 20)
#define H1_REG_CHKPT_DELTA_QP_CHK6(x) (((x) & 0x0f) << 24)
#define H1_REG_VP8_CTRL0 0x090
#define H1_REG_RLC_CTRL 0x094
#define H1_REG_RLC_CTRL_STR_OFFS_SHIFT 23
#define H1_REG_RLC_CTRL_STR_OFFS_MASK (0x3f << 23)
#define H1_REG_RLC_CTRL_RLC_SUM(x) ((x))
#define H1_REG_MB_CTRL 0x098
#define H1_REG_MB_CNT_OUT(x) (((x) & 0xffff))
#define H1_REG_MB_CNT_SET(x) (((x) & 0xffff) << 16)
#define H1_REG_ADDR_NEXT_PIC 0x09c
#define H1_REG_JPEG_LUMA_QUAT(i) (0x100 + ((i) * 0x4))
#define H1_REG_JPEG_CHROMA_QUAT(i) (0x140 + ((i) * 0x4))
#define H1_REG_STABILIZATION_OUTPUT 0x0A0
#define H1_REG_ADDR_CABAC_TBL 0x0cc
#define H1_REG_ADDR_MV_OUT 0x0d0
#define H1_REG_RGB_YUV_COEFF(i) (0x0d4 + ((i) * 0x4))
#define H1_REG_RGB_MASK_MSB 0x0dc
#define H1_REG_INTRA_AREA_CTRL 0x0e0
#define H1_REG_CIR_INTRA_CTRL 0x0e4
#define H1_REG_INTRA_SLICE_BITMAP(i) (0x0e8 + ((i) * 0x4))
#define H1_REG_ADDR_VP8_DCT_PART(i) (0x0e8 + ((i) * 0x4))
#define H1_REG_FIRST_ROI_AREA 0x0f0
#define H1_REG_SECOND_ROI_AREA 0x0f4
#define H1_REG_MVC_CTRL 0x0f8
#define H1_REG_MVC_CTRL_MV16X16_FAVOR(x) ((x) << 28)
#define H1_REG_VP8_INTRA_PENALTY(i) (0x100 + ((i) * 0x4))
#define H1_REG_ADDR_VP8_SEG_MAP 0x11c
#define H1_REG_VP8_SEG_QP(i) (0x120 + ((i) * 0x4))
#define H1_REG_DMV_4P_1P_PENALTY(i) (0x180 + ((i) * 0x4))
#define H1_REG_DMV_4P_1P_PENALTY_BIT(x, i) ((x) << (i) * 8)
#define H1_REG_DMV_QPEL_PENALTY(i) (0x200 + ((i) * 0x4))
#define H1_REG_DMV_QPEL_PENALTY_BIT(x, i) ((x) << (i) * 8)
#define H1_REG_VP8_CTRL1 0x280
#define H1_REG_VP8_BIT_COST_GOLDEN 0x284
#define H1_REG_VP8_LOOP_FLT_DELTA(i) (0x288 + ((i) * 0x4))
#endif /* HANTRO_H1_REGS_H_ */
@@ -0,0 +1,521 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Rockchip RK3288 VPU codec driver
*
* Copyright (c) 2014 Rockchip Electronics Co., Ltd.
* Hertz Wong <hertz.wong@rock-chips.com>
* Herman Chen <herman.chen@rock-chips.com>
*
* Copyright (C) 2014 Google, Inc.
* Tomasz Figa <tfiga@chromium.org>
*/
#include <linux/types.h>
#include <media/v4l2-h264.h>
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
/* Size with u32 units. */
#define CABAC_INIT_BUFFER_SIZE (460 * 2)
#define POC_BUFFER_SIZE 34
#define SCALING_LIST_SIZE (6 * 16 + 2 * 64)
/*
* For valid and long term reference marking, index are reversed, so bit 31
* indicates the status of the picture 0.
*/
#define REF_BIT(i) BIT(32 - 1 - (i))
/* Data structure describing auxiliary buffer format. */
struct hantro_h264_dec_priv_tbl {
u32 cabac_table[CABAC_INIT_BUFFER_SIZE];
u32 poc[POC_BUFFER_SIZE];
u8 scaling_list[SCALING_LIST_SIZE];
};
/*
* Constant CABAC table.
* From drivers/media/platform/rk3288-vpu/rk3288_vpu_hw_h264d.c
* in https://chromium.googlesource.com/chromiumos/third_party/kernel,
* chromeos-3.14 branch.
*/
static const u32 h264_cabac_table[] = {
0x14f10236, 0x034a14f1, 0x0236034a, 0xe47fe968, 0xfa35ff36, 0x07330000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0029003f, 0x003f003f, 0xf7530456, 0x0061f948, 0x0d29033e, 0x000b0137,
0x0045ef7f, 0xf3660052, 0xf94aeb6b, 0xe57fe17f, 0xe87fee5f, 0xe57feb72,
0xe27fef7b, 0xf473f07a, 0xf573f43f, 0xfe44f154, 0xf368fd46, 0xf85df65a,
0xe27fff4a, 0xfa61f95b, 0xec7ffc38, 0xfb52f94c, 0xea7df95d, 0xf557fd4d,
0xfb47fc3f, 0xfc44f454, 0xf93ef941, 0x083d0538, 0xfe420140, 0x003dfe4e,
0x01320734, 0x0a23002c, 0x0b26012d, 0x002e052c, 0x1f110133, 0x07321c13,
0x10210e3e, 0xf36cf164, 0xf365f35b, 0xf45ef658, 0xf054f656, 0xf953f357,
0xed5e0146, 0x0048fb4a, 0x123bf866, 0xf164005f, 0xfc4b0248, 0xf54bfd47,
0x0f2ef345, 0x003e0041, 0x1525f148, 0x09391036, 0x003e0c48, 0x18000f09,
0x08190d12, 0x0f090d13, 0x0a250c12, 0x061d1421, 0x0f1e042d, 0x013a003e,
0x073d0c26, 0x0b2d0f27, 0x0b2a0d2c, 0x102d0c29, 0x0a311e22, 0x122a0a37,
0x1133112e, 0x00591aed, 0x16ef1aef, 0x1ee71cec, 0x21e925e5, 0x21e928e4,
0x26ef21f5, 0x28f129fa, 0x26012911, 0x1efa1b03, 0x1a1625f0, 0x23fc26f8,
0x26fd2503, 0x26052a00, 0x23102716, 0x0e301b25, 0x153c0c44, 0x0261fd47,
0xfa2afb32, 0xfd36fe3e, 0x003a013f, 0xfe48ff4a, 0xf75bfb43, 0xfb1bfd27,
0xfe2c002e, 0xf040f844, 0xf64efa4d, 0xf656f45c, 0xf137f63c, 0xfa3efc41,
0xf449f84c, 0xf950f758, 0xef6ef561, 0xec54f54f, 0xfa49fc4a, 0xf356f360,
0xf561ed75, 0xf84efb21, 0xfc30fe35, 0xfd3ef347, 0xf64ff456, 0xf35af261,
0x0000fa5d, 0xfa54f84f, 0x0042ff47, 0x003efe3c, 0xfe3bfb4b, 0xfd3efc3a,
0xf742ff4f, 0x00470344, 0x0a2cf93e, 0x0f240e28, 0x101b0c1d, 0x012c1424,
0x1220052a, 0x01300a3e, 0x112e0940, 0xf468f561, 0xf060f958, 0xf855f955,
0xf755f358, 0x0442fd4d, 0xfd4cfa4c, 0x0a3aff4c, 0xff53f963, 0xf25f025f,
0x004cfb4a, 0x0046f54b, 0x01440041, 0xf249033e, 0x043eff44, 0xf34b0b37,
0x05400c46, 0x0f060613, 0x07100c0e, 0x120d0d0b, 0x0d0f0f10, 0x0c170d17,
0x0f140e1a, 0x0e2c1128, 0x112f1811, 0x15151916, 0x1f1b161d, 0x13230e32,
0x0a39073f, 0xfe4dfc52, 0xfd5e0945, 0xf46d24dd, 0x24de20e6, 0x25e22ce0,
0x22ee22f1, 0x28f121f9, 0x23fb2100, 0x2602210d, 0x17230d3a, 0x1dfd1a00,
0x161e1ff9, 0x23f122fd, 0x220324ff, 0x2205200b, 0x2305220c, 0x270b1e1d,
0x221a1d27, 0x13421f15, 0x1f1f1932, 0xef78ec70, 0xee72f555, 0xf15cf259,
0xe647f151, 0xf2500044, 0xf246e838, 0xe944e832, 0xf54a17f3, 0x1af328f1,
0x31f22c03, 0x2d062c22, 0x21361352, 0xfd4bff17, 0x0122012b, 0x0036fe37,
0x003d0140, 0x0044f75c, 0xf26af361, 0xf15af45a, 0xee58f649, 0xf74ff256,
0xf649f646, 0xf645fb42, 0xf740fb3a, 0x023b15f6, 0x18f51cf8, 0x1cff1d03,
0x1d092314, 0x1d240e43, 0x14f10236, 0x034a14f1, 0x0236034a, 0xe47fe968,
0xfa35ff36, 0x07331721, 0x17021500, 0x01090031, 0xdb760539, 0xf34ef541,
0x013e0c31, 0xfc491132, 0x1240092b, 0x1d001a43, 0x105a0968, 0xd27fec68,
0x0143f34e, 0xf541013e, 0xfa56ef5f, 0xfa3d092d, 0xfd45fa51, 0xf5600637,
0x0743fb56, 0x0258003a, 0xfd4cf65e, 0x05360445, 0xfd510058, 0xf943fb4a,
0xfc4afb50, 0xf948013a, 0x0029003f, 0x003f003f, 0xf7530456, 0x0061f948,
0x0d29033e, 0x002dfc4e, 0xfd60e57e, 0xe462e765, 0xe943e452, 0xec5ef053,
0xea6eeb5b, 0xee66f35d, 0xe37ff95c, 0xfb59f960, 0xf36cfd2e, 0xff41ff39,
0xf75dfd4a, 0xf75cf857, 0xe97e0536, 0x063c063b, 0x0645ff30, 0x0044fc45,
0xf858fe55, 0xfa4eff4b, 0xf94d0236, 0x0532fd44, 0x0132062a, 0xfc51013f,
0xfc460043, 0x0239fe4c, 0x0b230440, 0x013d0b23, 0x12190c18, 0x0d1d0d24,
0xf65df949, 0xfe490d2e, 0x0931f964, 0x09350235, 0x0535fe3d, 0x00380038,
0xf33ffb3c, 0xff3e0439, 0xfa450439, 0x0e270433, 0x0d440340, 0x013d093f,
0x07321027, 0x052c0434, 0x0b30fb3c, 0xff3b003b, 0x1621052c, 0x0e2bff4e,
0x003c0945, 0x0b1c0228, 0x032c0031, 0x002e022c, 0x0233002f, 0x0427023e,
0x062e0036, 0x0336023a, 0x043f0633, 0x06390735, 0x06340637, 0x0b2d0e24,
0x0835ff52, 0x0737fd4e, 0x0f2e161f, 0xff541907, 0x1ef91c03, 0x1c042000,
0x22ff1e06, 0x1e062009, 0x1f131a1b, 0x1a1e2514, 0x1c221146, 0x0143053b,
0x0943101e, 0x12201223, 0x161d181f, 0x1726122b, 0x14290b3f, 0x093b0940,
0xff5efe59, 0xf76cfa4c, 0xfe2c002d, 0x0034fd40, 0xfe3bfc46, 0xfc4bf852,
0xef66f74d, 0x0318002a, 0x00300037, 0xfa3bf947, 0xf453f557, 0xe277013a,
0xfd1dff24, 0x0126022b, 0xfa37003a, 0x0040fd4a, 0xf65a0046, 0xfc1d051f,
0x072a013b, 0xfe3afd48, 0xfd51f561, 0x003a0805, 0x0a0e0e12, 0x0d1b0228,
0x003afd46, 0xfa4ff855, 0x0000f36a, 0xf06af657, 0xeb72ee6e, 0xf262ea6e,
0xeb6aee67, 0xeb6be96c, 0xe670f660, 0xf45ffb5b, 0xf75dea5e, 0xfb560943,
0xfc50f655, 0xff46073c, 0x093a053d, 0x0c320f32, 0x12311136, 0x0a29072e,
0xff330731, 0x08340929, 0x062f0237, 0x0d290a2c, 0x06320535, 0x0d31043f,
0x0640fe45, 0xfe3b0646, 0x0a2c091f, 0x0c2b0335, 0x0e220a26, 0xfd340d28,
0x1120072c, 0x07260d32, 0x0a391a2b, 0x0e0b0b0e, 0x090b120b, 0x150917fe,
0x20f120f1, 0x22eb27e9, 0x2adf29e1, 0x2ee426f4, 0x151d2de8, 0x35d330e6,
0x41d52bed, 0x27f61e09, 0x121a141b, 0x0039f252, 0xfb4bed61, 0xdd7d1b00,
0x1c001ffc, 0x1b062208, 0x1e0a1816, 0x21131620, 0x1a1f1529, 0x1a2c172f,
0x10410e47, 0x083c063f, 0x11411518, 0x17141a17, 0x1b201c17, 0x1c181728,
0x18201c1d, 0x172a1339, 0x1635163d, 0x0b560c28, 0x0b330e3b, 0xfc4ff947,
0xfb45f746, 0xf842f644, 0xed49f445, 0xf046f143, 0xec3eed46, 0xf042ea41,
0xec3f09fe, 0x1af721f7, 0x27f929fe, 0x2d033109, 0x2d1b243b, 0xfa42f923,
0xf92af82d, 0xfb30f438, 0xfa3cfb3e, 0xf842f84c, 0xfb55fa51, 0xf64df951,
0xef50ee49, 0xfc4af653, 0xf747f743, 0xff3df842, 0xf242003b, 0x023b15f3,
0x21f227f9, 0x2efe3302, 0x3c063d11, 0x37222a3e, 0x14f10236, 0x034a14f1,
0x0236034a, 0xe47fe968, 0xfa35ff36, 0x07331619, 0x22001000, 0xfe090429,
0xe3760241, 0xfa47f34f, 0x05340932, 0xfd460a36, 0x1a221316, 0x28003902,
0x29241a45, 0xd37ff165, 0xfc4cfa47, 0xf34f0534, 0x0645f35a, 0x0034082b,
0xfe45fb52, 0xf660023b, 0x024bfd57, 0xfd640138, 0xfd4afa55, 0x003bfd51,
0xf956fb5f, 0xff42ff4d, 0x0146fe56, 0xfb48003d, 0x0029003f, 0x003f003f,
0xf7530456, 0x0061f948, 0x0d29033e, 0x0d0f0733, 0x0250d97f, 0xee5bef60,
0xe651dd62, 0xe866e961, 0xe577e863, 0xeb6eee66, 0xdc7f0050, 0xfb59f95e,
0xfc5c0027, 0x0041f154, 0xdd7ffe49, 0xf468f75b, 0xe17f0337, 0x07380737,
0x083dfd35, 0x0044f94a, 0xf758f367, 0xf35bf759, 0xf25cf84c, 0xf457e96e,
0xe869f64e, 0xec70ef63, 0xb27fba7f, 0xce7fd27f, 0xfc42fb4e, 0xfc47f848,
0x023bff37, 0xf946fa4b, 0xf859de77, 0xfd4b2014, 0x1e16d47f, 0x0036fb3d,
0x003aff3c, 0xfd3df843, 0xe754f24a, 0xfb410534, 0x0239003d, 0xf745f546,
0x1237fc47, 0x003a073d, 0x09291219, 0x0920052b, 0x092f002c, 0x0033022e,
0x1326fc42, 0x0f260c2a, 0x09220059, 0x042d0a1c, 0x0a1f21f5, 0x34d5120f,
0x1c0023ea, 0x26e72200, 0x27ee20f4, 0x66a20000, 0x38f121fc, 0x1d0a25fb,
0x33e327f7, 0x34de45c6, 0x43c12cfb, 0x200737e3, 0x20010000, 0x1b2421e7,
0x22e224e4, 0x26e426e5, 0x22ee23f0, 0x22f220f8, 0x25fa2300, 0x1e0a1c12,
0x1a191d29, 0x004b0248, 0x084d0e23, 0x121f1123, 0x151e112d, 0x142a122d,
0x1b1a1036, 0x07421038, 0x0b490a43, 0xf674e970, 0xf147f93d, 0x0035fb42,
0xf54df750, 0xf754f657, 0xde7feb65, 0xfd27fb35, 0xf93df54b, 0xf14def5b,
0xe76be76f, 0xe47af54c, 0xf62cf634, 0xf639f73a, 0xf048f945, 0xfc45fb4a,
0xf7560242, 0xf7220120, 0x0b1f0534, 0xfe37fe43, 0x0049f859, 0x03340704,
0x0a081108, 0x10130325, 0xff3dfb49, 0xff46fc4e, 0x0000eb7e, 0xe97cec6e,
0xe67ee77c, 0xef69e579, 0xe575ef66, 0xe675e574, 0xdf7af65f, 0xf264f85f,
0xef6fe472, 0xfa59fe50, 0xfc52f755, 0xf851ff48, 0x05400143, 0x09380045,
0x01450745, 0xf945fa43, 0xf04dfe40, 0x023dfa43, 0xfd400239, 0xfd41fd42,
0x003e0933, 0xff42fe47, 0xfe4bff46, 0xf7480e3c, 0x1025002f, 0x12230b25,
0x0c290a29, 0x02300c29, 0x0d29003b, 0x03321328, 0x03421232, 0x13fa12fa,
0x0e001af4, 0x1ff021e7, 0x21ea25e4, 0x27e22ae2, 0x2fd62ddc, 0x31de29ef,
0x200945b9, 0x3fc142c0, 0x4db636d9, 0x34dd29f6, 0x240028ff, 0x1e0e1c1a,
0x17250c37, 0x0b4125df, 0x27dc28db, 0x26e22edf, 0x2ae228e8, 0x31e326f4,
0x28f626fd, 0x2efb1f14, 0x1d1e192c, 0x0c300b31, 0x1a2d1616, 0x17161b15,
0x21141a1c, 0x1e181b22, 0x122a1927, 0x12320c46, 0x15360e47, 0x0b531920,
0x15311536, 0xfb55fa51, 0xf64df951, 0xef50ee49, 0xfc4af653, 0xf747f743,
0xff3df842, 0xf242003b, 0x023b11f6, 0x20f32af7, 0x31fb3500, 0x4003440a,
0x421b2f39, 0xfb470018, 0xff24fe2a, 0xfe34f739, 0xfa3ffc41, 0xfc43f952,
0xfd51fd4c, 0xf948fa4e, 0xf448f244, 0xfd46fa4c, 0xfb42fb3e, 0x0039fc3d,
0xf73c0136, 0x023a11f6, 0x20f32af7, 0x31fb3500, 0x4003440a, 0x421b2f39,
0x14f10236, 0x034a14f1, 0x0236034a, 0xe47fe968, 0xfa35ff36, 0x07331d10,
0x19000e00, 0xf633fd3e, 0xe5631a10, 0xfc55e866, 0x05390639, 0xef490e39,
0x1428140a, 0x1d003600, 0x252a0c61, 0xe07fea75, 0xfe4afc55, 0xe8660539,
0xfa5df258, 0xfa2c0437, 0xf559f167, 0xeb741339, 0x143a0454, 0x0660013f,
0xfb55f36a, 0x053f064b, 0xfd5aff65, 0x0337fc4f, 0xfe4bf461, 0xf932013c,
0x0029003f, 0x003f003f, 0xf7530456, 0x0061f948, 0x0d29033e, 0x0722f758,
0xec7fdc7f, 0xef5bf25f, 0xe754e756, 0xf459ef5b, 0xe17ff24c, 0xee67f35a,
0xdb7f0b50, 0x054c0254, 0x054efa37, 0x043df253, 0xdb7ffb4f, 0xf568f55b,
0xe27f0041, 0xfe4f0048, 0xfc5cfa38, 0x0344f847, 0xf362fc56, 0xf458fb52,
0xfd48fc43, 0xf848f059, 0xf745ff3b, 0x05420439, 0xfc47fe47, 0x023aff4a,
0xfc2cff45, 0x003ef933, 0xfc2ffa2a, 0xfd29fa35, 0x084cf74e, 0xf5530934,
0x0043fb5a, 0x0143f148, 0xfb4bf850, 0xeb53eb40, 0xf31fe740, 0xe35e094b,
0x113ff84a, 0xfb23fe1b, 0x0d5b0341, 0xf945084d, 0xf642033e, 0xfd44ec51,
0x001e0107, 0xfd17eb4a, 0x1042e97c, 0x11252cee, 0x32deea7f, 0x0427002a,
0x07220b1d, 0x081f0625, 0x072a0328, 0x08210d2b, 0x0d24042f, 0x0337023a,
0x063c082c, 0x0b2c0e2a, 0x07300438, 0x04340d25, 0x0931133a, 0x0a300c2d,
0x00451421, 0x083f23ee, 0x21e71cfd, 0x180a1b00, 0x22f234d4, 0x27e81311,
0x1f19241d, 0x1821220f, 0x1e141649, 0x1422131f, 0x1b2c1310, 0x0f240f24,
0x151c1915, 0x1e141f0c, 0x1b10182a, 0x005d0e38, 0x0f391a26, 0xe87fe873,
0xea52f73e, 0x0035003b, 0xf255f359, 0xf35ef55c, 0xe37feb64, 0xf239f443,
0xf547f64d, 0xeb55f058, 0xe968f162, 0xdb7ff652, 0xf830f83d, 0xf842f946,
0xf24bf64f, 0xf753f45c, 0xee6cfc4f, 0xea45f04b, 0xfe3a013a, 0xf34ef753,
0xfc51f363, 0xf351fa26, 0xf33efa3a, 0xfe3bf049, 0xf64cf356, 0xf753f657,
0x0000ea7f, 0xe77fe778, 0xe57fed72, 0xe975e776, 0xe675e871, 0xe476e178,
0xdb7cf65e, 0xf166f663, 0xf36ace7f, 0xfb5c1139, 0xfb56f35e, 0xf45bfe4d,
0x0047ff49, 0x0440f951, 0x05400f39, 0x01430044, 0xf6430144, 0x004d0240,
0x0044fb4e, 0x0737053b, 0x02410e36, 0x0f2c053c, 0x0246fe4c, 0xee560c46,
0x0540f446, 0x0b370538, 0x00450241, 0xfa4a0536, 0x0736fa4c, 0xf552fe4d,
0xfe4d192a, 0x11f310f7, 0x11f41beb, 0x25e229d8, 0x2ad730d1, 0x27e02ed8,
0x34cd2ed7, 0x34d92bed, 0x200b3dc9, 0x38d23ece, 0x51bd2dec, 0x23fe1c0f,
0x22012701, 0x1e111426, 0x122d0f36, 0x004f24f0, 0x25f225ef, 0x2001220f,
0x1d0f1819, 0x22161f10, 0x23121f1c, 0x2129241c, 0x1b2f153e, 0x121f131a,
0x24181817, 0x1b10181e, 0x1f1d1629, 0x162a103c, 0x0f340e3c, 0x034ef07b,
0x15351638, 0x193d1521, 0x1332113d, 0xfd4ef84a, 0xf748f648, 0xee4bf447,
0xf53ffb46, 0xef4bf248, 0xf043f835, 0xf23bf734, 0xf54409fe, 0x1ef61ffc,
0x21ff2107, 0x1f0c2517, 0x1f261440, 0xf747f925, 0xf82cf531, 0xf638f43b,
0xf83ff743, 0xfa44f64f, 0xfd4ef84a, 0xf748f648, 0xee4bf447, 0xf53ffb46,
0xef4bf248, 0xf043f835, 0xf23bf734, 0xf54409fe, 0x1ef61ffc, 0x21ff2107,
0x1f0c2517, 0x1f261440
};
static void
assemble_scaling_list(struct hantro_ctx *ctx)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling;
const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
const size_t num_list_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4);
const size_t list_len_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4[0]);
const size_t list_len_8x8 = ARRAY_SIZE(scaling->scaling_list_8x8[0]);
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
u32 *dst = (u32 *)tbl->scaling_list;
const u32 *src;
int i, j;
if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
return;
for (i = 0; i < num_list_4x4; i++) {
src = (u32 *)&scaling->scaling_list_4x4[i];
for (j = 0; j < list_len_4x4 / 4; j++)
*dst++ = swab32(src[j]);
}
/* Only Intra/Inter Y lists */
for (i = 0; i < 2; i++) {
src = (u32 *)&scaling->scaling_list_8x8[i];
for (j = 0; j < list_len_8x8 / 4; j++)
*dst++ = swab32(src[j]);
}
}
static void prepare_table(struct hantro_ctx *ctx)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
u32 dpb_longterm = 0;
u32 dpb_valid = 0;
int i;
for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) {
tbl->poc[i * 2] = dpb[i].top_field_order_cnt;
tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt;
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
continue;
/*
* Set up bit maps of valid and long term DPBs.
* NOTE: The bits are reversed, i.e. MSb is DPB 0. For frame
* decoding, bit 31 to 15 are used, while for field decoding,
* all bits are used, with bit 31 being a top field, 30 a bottom
* field and so on.
*/
if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) {
if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF)
dpb_valid |= REF_BIT(i * 2);
if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
dpb_valid |= REF_BIT(i * 2 + 1);
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) {
dpb_longterm |= REF_BIT(i * 2);
dpb_longterm |= REF_BIT(i * 2 + 1);
}
} else {
dpb_valid |= REF_BIT(i);
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
dpb_longterm |= REF_BIT(i);
}
}
ctx->h264_dec.dpb_valid = dpb_valid;
ctx->h264_dec.dpb_longterm = dpb_longterm;
if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) ||
!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) {
tbl->poc[32] = ctx->h264_dec.cur_poc;
tbl->poc[33] = 0;
} else {
tbl->poc[32] = dec_param->top_field_order_cnt;
tbl->poc[33] = dec_param->bottom_field_order_cnt;
}
assemble_scaling_list(ctx);
}
static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a,
const struct v4l2_h264_dpb_entry *b)
{
return a->reference_ts == b->reference_ts;
}
static void update_dpb(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_h264_decode_params *dec_param;
DECLARE_BITMAP(new, ARRAY_SIZE(dec_param->dpb)) = { 0, };
DECLARE_BITMAP(used, ARRAY_SIZE(dec_param->dpb)) = { 0, };
unsigned int i, j;
dec_param = ctx->h264_dec.ctrls.decode;
/* Disable all entries by default. */
for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++)
ctx->h264_dec.dpb[i].flags = 0;
/* Try to match new DPB entries with existing ones by their POCs. */
for (i = 0; i < ARRAY_SIZE(dec_param->dpb); i++) {
const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i];
if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
continue;
/*
* To cut off some comparisons, iterate only on target DPB
* entries which are not used yet.
*/
for_each_clear_bit(j, used, ARRAY_SIZE(ctx->h264_dec.dpb)) {
struct v4l2_h264_dpb_entry *cdpb;
cdpb = &ctx->h264_dec.dpb[j];
if (!dpb_entry_match(cdpb, ndpb))
continue;
*cdpb = *ndpb;
__set_bit(j, used);
break;
}
if (j == ARRAY_SIZE(ctx->h264_dec.dpb))
__set_bit(i, new);
}
/* For entries that could not be matched, use remaining free slots. */
for_each_set_bit(i, new, ARRAY_SIZE(dec_param->dpb)) {
const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i];
struct v4l2_h264_dpb_entry *cdpb;
/*
* Both arrays are of the same sizes, so there is no way
* we can end up with no space in target array, unless
* something is buggy.
*/
j = find_first_zero_bit(used, ARRAY_SIZE(ctx->h264_dec.dpb));
if (WARN_ON(j >= ARRAY_SIZE(ctx->h264_dec.dpb)))
return;
cdpb = &ctx->h264_dec.dpb[j];
*cdpb = *ndpb;
__set_bit(j, used);
}
}
dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
unsigned int dpb_idx)
{
struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
dma_addr_t dma_addr = 0;
s32 cur_poc = ctx->h264_dec.cur_poc;
u32 flags;
if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts);
if (!dma_addr) {
struct vb2_v4l2_buffer *dst_buf;
struct vb2_buffer *buf;
/*
* If a DPB entry is unused or invalid, address of current
* destination buffer is returned.
*/
dst_buf = hantro_get_dst_buf(ctx);
buf = &dst_buf->vb2_buf;
dma_addr = hantro_get_dec_buf_addr(ctx, buf);
}
flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0x2 : 0;
flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) <
abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ?
0x1 : 0;
return dma_addr | flags;
}
u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
{
const struct v4l2_h264_dpb_entry *dpb = &ctx->h264_dec.dpb[dpb_idx];
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
return 0;
return dpb->frame_num;
}
/*
* Removes all references with the same parity as the current picture from the
* reference list. The remaining list will have references with the opposite
* parity. This is effectively a deduplication of references since each buffer
* stores two fields. For this reason, each buffer is found twice in the
* reference list.
*
* This technique has been chosen through trial and error. This simple approach
* resulted in the highest conformance score. Note that this method may suffer
* worse quality in the case an opposite reference frame has been lost. If this
* becomes a problem in the future, it should be possible to add a preprocessing
* to identify un-paired fields and avoid removing them.
*/
static void deduplicate_reflist(struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference *reflist)
{
int write_idx = 0;
int i;
if (b->cur_pic_fields == V4L2_H264_FRAME_REF) {
write_idx = b->num_valid;
goto done;
}
for (i = 0; i < b->num_valid; i++) {
if (!(b->cur_pic_fields == reflist[i].fields)) {
reflist[write_idx++] = reflist[i];
continue;
}
}
done:
/* Should not happen unless we have a bug in the reflist builder. */
if (WARN_ON(write_idx > 16))
write_idx = 16;
/* Clear the remaining, some streams fails otherwise */
for (; write_idx < 16; write_idx++)
reflist[write_idx].index = 15;
}
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
{
struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec;
struct hantro_h264_dec_ctrls *ctrls = &h264_ctx->ctrls;
struct v4l2_h264_reflist_builder reflist_builder;
hantro_start_prepare_run(ctx);
ctrls->scaling =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_SCALING_MATRIX);
if (WARN_ON(!ctrls->scaling))
return -EINVAL;
ctrls->decode =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_DECODE_PARAMS);
if (WARN_ON(!ctrls->decode))
return -EINVAL;
ctrls->sps =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_SPS);
if (WARN_ON(!ctrls->sps))
return -EINVAL;
ctrls->pps =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_PPS);
if (WARN_ON(!ctrls->pps))
return -EINVAL;
/* Update the DPB with new refs. */
update_dpb(ctx);
/* Build the P/B{0,1} ref lists. */
v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode,
ctrls->sps, ctx->h264_dec.dpb);
h264_ctx->cur_poc = reflist_builder.cur_pic_order_count;
/* Prepare data in memory. */
prepare_table(ctx);
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
h264_ctx->reflists.b1);
/*
* Reduce ref lists to at most 16 entries, Hantro hardware will deduce
* the actual picture lists in field through the dpb_valid,
* dpb_longterm bitmap along with the current frame parity.
*/
if (reflist_builder.cur_pic_fields != V4L2_H264_FRAME_REF) {
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.p);
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b0);
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b1);
}
return 0;
}
void hantro_h264_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_h264_dec_hw_ctx *h264_dec = &ctx->h264_dec;
struct hantro_aux_buf *priv = &h264_dec->priv;
dma_free_coherent(vpu->dev, priv->size, priv->cpu, priv->dma);
}
int hantro_h264_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_h264_dec_hw_ctx *h264_dec = &ctx->h264_dec;
struct hantro_aux_buf *priv = &h264_dec->priv;
struct hantro_h264_dec_priv_tbl *tbl;
priv->cpu = dma_alloc_coherent(vpu->dev, sizeof(*tbl), &priv->dma,
GFP_KERNEL);
if (!priv->cpu)
return -ENOMEM;
priv->size = sizeof(*tbl);
tbl = priv->cpu;
memcpy(tbl->cabac_table, h264_cabac_table, sizeof(tbl->cabac_table));
return 0;
}
@@ -0,0 +1,287 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU HEVC codec driver
*
* Copyright (C) 2020 Safran Passenger Innovations LLC
*/
#include <linux/types.h>
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
#define VERT_FILTER_RAM_SIZE 8 /* bytes per pixel row */
/*
* BSD control data of current picture at tile border
* 128 bits per 4x4 tile = 128/(8*4) bytes per row
*/
#define BSD_CTRL_RAM_SIZE 4 /* bytes per pixel row */
/* tile border coefficients of filter */
#define VERT_SAO_RAM_SIZE 48 /* bytes per pixel */
#define SCALING_LIST_SIZE (16 * 64)
#define MAX_TILE_COLS 20
#define MAX_TILE_ROWS 22
static bool hevc_use_compression = IS_ENABLED(CONFIG_VIDEO_HANTRO_HEVC_RFC);
module_param_named(hevc_use_compression, hevc_use_compression, bool, 0644);
MODULE_PARM_DESC(hevc_use_compression,
"Use reference frame compression for HEVC");
void hantro_hevc_ref_init(struct hantro_ctx *ctx)
{
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
hevc_dec->ref_bufs_used = 0;
}
dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx,
s32 poc)
{
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
int i;
/* Find the reference buffer in already known ones */
for (i = 0; i < NUM_REF_PICTURES; i++) {
if (hevc_dec->ref_bufs_poc[i] == poc) {
hevc_dec->ref_bufs_used |= 1 << i;
return hevc_dec->ref_bufs[i].dma;
}
}
return 0;
}
int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr)
{
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
int i;
/* Add a new reference buffer */
for (i = 0; i < NUM_REF_PICTURES; i++) {
if (!(hevc_dec->ref_bufs_used & 1 << i)) {
hevc_dec->ref_bufs_used |= 1 << i;
hevc_dec->ref_bufs_poc[i] = poc;
hevc_dec->ref_bufs[i].dma = addr;
return 0;
}
}
return -EINVAL;
}
static int tile_buffer_reallocate(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
unsigned int height64 = (sps->pic_height_in_luma_samples + 63) & ~63;
unsigned int size;
if (num_tile_cols <= 1 ||
num_tile_cols <= hevc_dec->num_tile_cols_allocated)
return 0;
/* Need to reallocate due to tiles passed via PPS */
if (hevc_dec->tile_filter.cpu) {
dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
hevc_dec->tile_filter.cpu,
hevc_dec->tile_filter.dma);
hevc_dec->tile_filter.cpu = NULL;
}
if (hevc_dec->tile_sao.cpu) {
dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
hevc_dec->tile_sao.cpu,
hevc_dec->tile_sao.dma);
hevc_dec->tile_sao.cpu = NULL;
}
if (hevc_dec->tile_bsd.cpu) {
dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size,
hevc_dec->tile_bsd.cpu,
hevc_dec->tile_bsd.dma);
hevc_dec->tile_bsd.cpu = NULL;
}
size = (VERT_FILTER_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8;
hevc_dec->tile_filter.cpu = dma_alloc_coherent(vpu->dev, size,
&hevc_dec->tile_filter.dma,
GFP_KERNEL);
if (!hevc_dec->tile_filter.cpu)
return -ENOMEM;
hevc_dec->tile_filter.size = size;
size = (VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8;
hevc_dec->tile_sao.cpu = dma_alloc_coherent(vpu->dev, size,
&hevc_dec->tile_sao.dma,
GFP_KERNEL);
if (!hevc_dec->tile_sao.cpu)
goto err_free_tile_buffers;
hevc_dec->tile_sao.size = size;
size = BSD_CTRL_RAM_SIZE * height64 * (num_tile_cols - 1);
hevc_dec->tile_bsd.cpu = dma_alloc_coherent(vpu->dev, size,
&hevc_dec->tile_bsd.dma,
GFP_KERNEL);
if (!hevc_dec->tile_bsd.cpu)
goto err_free_sao_buffers;
hevc_dec->tile_bsd.size = size;
hevc_dec->num_tile_cols_allocated = num_tile_cols;
return 0;
err_free_sao_buffers:
if (hevc_dec->tile_sao.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
hevc_dec->tile_sao.cpu,
hevc_dec->tile_sao.dma);
hevc_dec->tile_sao.cpu = NULL;
err_free_tile_buffers:
if (hevc_dec->tile_filter.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
hevc_dec->tile_filter.cpu,
hevc_dec->tile_filter.dma);
hevc_dec->tile_filter.cpu = NULL;
return -ENOMEM;
}
static int hantro_hevc_validate_sps(struct hantro_ctx *ctx, const struct v4l2_ctrl_hevc_sps *sps)
{
/*
* for tile pixel format check if the width and height match
* hardware constraints
*/
if (ctx->vpu_dst_fmt->fourcc == V4L2_PIX_FMT_NV12_4L4) {
if (ctx->dst_fmt.width !=
ALIGN(sps->pic_width_in_luma_samples, ctx->vpu_dst_fmt->frmsize.step_width))
return -EINVAL;
if (ctx->dst_fmt.height !=
ALIGN(sps->pic_height_in_luma_samples, ctx->vpu_dst_fmt->frmsize.step_height))
return -EINVAL;
}
return 0;
}
int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx)
{
struct hantro_hevc_dec_hw_ctx *hevc_ctx = &ctx->hevc_dec;
struct hantro_hevc_dec_ctrls *ctrls = &hevc_ctx->ctrls;
int ret;
hantro_start_prepare_run(ctx);
ctrls->decode_params =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS);
if (WARN_ON(!ctrls->decode_params))
return -EINVAL;
ctrls->scaling =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
if (WARN_ON(!ctrls->scaling))
return -EINVAL;
ctrls->sps =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_SPS);
if (WARN_ON(!ctrls->sps))
return -EINVAL;
ret = hantro_hevc_validate_sps(ctx, ctrls->sps);
if (ret)
return ret;
ctrls->pps =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_PPS);
if (WARN_ON(!ctrls->pps))
return -EINVAL;
ret = tile_buffer_reallocate(ctx);
if (ret)
return ret;
return 0;
}
void hantro_hevc_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
if (hevc_dec->tile_sizes.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_sizes.size,
hevc_dec->tile_sizes.cpu,
hevc_dec->tile_sizes.dma);
hevc_dec->tile_sizes.cpu = NULL;
if (hevc_dec->scaling_lists.cpu)
dma_free_coherent(vpu->dev, hevc_dec->scaling_lists.size,
hevc_dec->scaling_lists.cpu,
hevc_dec->scaling_lists.dma);
hevc_dec->scaling_lists.cpu = NULL;
if (hevc_dec->tile_filter.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
hevc_dec->tile_filter.cpu,
hevc_dec->tile_filter.dma);
hevc_dec->tile_filter.cpu = NULL;
if (hevc_dec->tile_sao.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
hevc_dec->tile_sao.cpu,
hevc_dec->tile_sao.dma);
hevc_dec->tile_sao.cpu = NULL;
if (hevc_dec->tile_bsd.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size,
hevc_dec->tile_bsd.cpu,
hevc_dec->tile_bsd.dma);
hevc_dec->tile_bsd.cpu = NULL;
}
int hantro_hevc_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
unsigned int size;
memset(hevc_dec, 0, sizeof(*hevc_dec));
/*
* Maximum number of tiles times width and height (2 bytes each),
* rounding up to next 16 bytes boundary + one extra 16 byte
* chunk (HW guys wanted to have this).
*/
size = round_up(MAX_TILE_COLS * MAX_TILE_ROWS * 4 * sizeof(u16) + 16, 16);
hevc_dec->tile_sizes.cpu = dma_alloc_coherent(vpu->dev, size,
&hevc_dec->tile_sizes.dma,
GFP_KERNEL);
if (!hevc_dec->tile_sizes.cpu)
return -ENOMEM;
hevc_dec->tile_sizes.size = size;
hevc_dec->scaling_lists.cpu = dma_alloc_coherent(vpu->dev, SCALING_LIST_SIZE,
&hevc_dec->scaling_lists.dma,
GFP_KERNEL);
if (!hevc_dec->scaling_lists.cpu)
return -ENOMEM;
hevc_dec->scaling_lists.size = SCALING_LIST_SIZE;
hantro_hevc_ref_init(ctx);
hevc_dec->use_compression =
hevc_use_compression & hantro_needs_postproc(ctx, ctx->vpu_dst_fmt);
return 0;
}
@@ -0,0 +1,588 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VPU codec driver
*
* Copyright 2018 Google LLC.
* Tomasz Figa <tfiga@chromium.org>
*/
#ifndef HANTRO_HW_H_
#define HANTRO_HW_H_
#include <linux/interrupt.h>
#include <linux/v4l2-controls.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-vp9.h>
#include <media/videobuf2-core.h>
#include "rockchip_av1_entropymode.h"
#include "rockchip_av1_filmgrain.h"
#define DEC_8190_ALIGN_MASK 0x07U
#define MB_DIM 16
#define TILE_MB_DIM 4
#define MB_WIDTH(w) DIV_ROUND_UP(w, MB_DIM)
#define MB_HEIGHT(h) DIV_ROUND_UP(h, MB_DIM)
#define FMT_MIN_WIDTH 48
#define FMT_MIN_HEIGHT 48
#define FMT_HD_WIDTH 1280
#define FMT_HD_HEIGHT 720
#define FMT_FHD_WIDTH 1920
#define FMT_FHD_HEIGHT 1088
#define FMT_UHD_WIDTH 3840
#define FMT_UHD_HEIGHT 2160
#define FMT_4K_WIDTH 4096
#define FMT_4K_HEIGHT 2304
#define NUM_REF_PICTURES (V4L2_HEVC_DPB_ENTRIES_NUM_MAX + 1)
#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1)
#define MAX_POSTPROC_BUFFERS 64
#define CBS_SIZE 16 /* compression table size in bytes */
#define CBS_LUMA 8 /* luminance CBS is composed of 1 8x8 coded block */
#define CBS_CHROMA_W (8 * 2) /* chrominance CBS is composed of two 8x4 coded
* blocks, with Cb CB first then Cr CB following
*/
#define CBS_CHROMA_H 4
struct hantro_dev;
struct hantro_ctx;
struct hantro_buf;
struct hantro_variant;
/**
* struct hantro_aux_buf - auxiliary DMA buffer for hardware data
*
* @cpu: CPU pointer to the buffer.
* @dma: DMA address of the buffer.
* @size: Size of the buffer.
* @attrs: Attributes of the DMA mapping.
*/
struct hantro_aux_buf {
void *cpu;
dma_addr_t dma;
size_t size;
unsigned long attrs;
};
/* Max. number of entries in the DPB (HW limitation). */
#define HANTRO_H264_DPB_SIZE 16
/**
* struct hantro_h264_dec_ctrls
*
* @decode: Decode params
* @scaling: Scaling info
* @sps: SPS info
* @pps: PPS info
*/
struct hantro_h264_dec_ctrls {
const struct v4l2_ctrl_h264_decode_params *decode;
const struct v4l2_ctrl_h264_scaling_matrix *scaling;
const struct v4l2_ctrl_h264_sps *sps;
const struct v4l2_ctrl_h264_pps *pps;
};
/**
* struct hantro_h264_dec_reflists
*
* @p: P reflist
* @b0: B0 reflist
* @b1: B1 reflist
*/
struct hantro_h264_dec_reflists {
struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
};
/**
* struct hantro_h264_dec_hw_ctx
*
* @priv: Private auxiliary buffer for hardware.
* @dpb: DPB
* @reflists: P/B0/B1 reflists
* @ctrls: V4L2 controls attached to a run
* @dpb_longterm: DPB long-term
* @dpb_valid: DPB valid
* @cur_poc: Current picture order count
*/
struct hantro_h264_dec_hw_ctx {
struct hantro_aux_buf priv;
struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE];
struct hantro_h264_dec_reflists reflists;
struct hantro_h264_dec_ctrls ctrls;
u32 dpb_longterm;
u32 dpb_valid;
s32 cur_poc;
};
/**
* struct hantro_hevc_dec_ctrls
* @decode_params: Decode params
* @scaling: Scaling matrix
* @sps: SPS info
* @pps: PPS info
* @hevc_hdr_skip_length: the number of data (in bits) to skip in the
* slice segment header syntax after 'slice type'
* token
*/
struct hantro_hevc_dec_ctrls {
const struct v4l2_ctrl_hevc_decode_params *decode_params;
const struct v4l2_ctrl_hevc_scaling_matrix *scaling;
const struct v4l2_ctrl_hevc_sps *sps;
const struct v4l2_ctrl_hevc_pps *pps;
u32 hevc_hdr_skip_length;
};
/**
* struct hantro_hevc_dec_hw_ctx
* @tile_sizes: Tile sizes buffer
* @tile_filter: Tile vertical filter buffer
* @tile_sao: Tile SAO buffer
* @tile_bsd: Tile BSD control buffer
* @ref_bufs: Internal reference buffers
* @scaling_lists: Scaling lists buffer
* @ref_bufs_poc: Internal reference buffers picture order count
* @ref_bufs_used: Bitfield of used reference buffers
* @ctrls: V4L2 controls attached to a run
* @num_tile_cols_allocated: number of allocated tiles
* @use_compression: use reference buffer compression
*/
struct hantro_hevc_dec_hw_ctx {
struct hantro_aux_buf tile_sizes;
struct hantro_aux_buf tile_filter;
struct hantro_aux_buf tile_sao;
struct hantro_aux_buf tile_bsd;
struct hantro_aux_buf ref_bufs[NUM_REF_PICTURES];
struct hantro_aux_buf scaling_lists;
s32 ref_bufs_poc[NUM_REF_PICTURES];
u32 ref_bufs_used;
struct hantro_hevc_dec_ctrls ctrls;
unsigned int num_tile_cols_allocated;
bool use_compression;
};
/**
* struct hantro_mpeg2_dec_hw_ctx
*
* @qtable: Quantization table
*/
struct hantro_mpeg2_dec_hw_ctx {
struct hantro_aux_buf qtable;
};
/**
* struct hantro_vp8_dec_hw_ctx
*
* @segment_map: Segment map buffer.
* @prob_tbl: Probability table buffer.
*/
struct hantro_vp8_dec_hw_ctx {
struct hantro_aux_buf segment_map;
struct hantro_aux_buf prob_tbl;
};
/**
* struct hantro_vp9_frame_info
*
* @valid: frame info valid flag
* @frame_context_idx: index of frame context
* @reference_mode: inter prediction type
* @tx_mode: transform mode
* @interpolation_filter: filter selection for inter prediction
* @flags: frame flags
* @timestamp: frame timestamp
*/
struct hantro_vp9_frame_info {
u32 valid : 1;
u32 frame_context_idx : 2;
u32 reference_mode : 2;
u32 tx_mode : 3;
u32 interpolation_filter : 3;
u32 flags;
u64 timestamp;
};
#define MAX_SB_COLS 64
#define MAX_SB_ROWS 34
/**
* struct hantro_vp9_dec_hw_ctx
*
* @tile_edge: auxiliary DMA buffer for tile edge processing
* @segment_map: auxiliary DMA buffer for segment map
* @misc: auxiliary DMA buffer for tile info, probabilities and hw counters
* @cnts: vp9 library struct for abstracting hw counters access
* @probability_tables: VP9 probability tables implied by the spec
* @frame_context: VP9 frame contexts
* @cur: current frame information
* @last: last frame information
* @bsd_ctrl_offset: bsd offset into tile_edge
* @segment_map_size: size of segment map
* @ctx_counters_offset: hw counters offset into misc
* @tile_info_offset: tile info offset into misc
* @tile_r_info: per-tile information array
* @tile_c_info: per-tile information array
* @last_tile_r: last number of tile rows
* @last_tile_c: last number of tile cols
* @last_sbs_r: last number of superblock rows
* @last_sbs_c: last number of superblock cols
* @active_segment: number of active segment (alternating between 0 and 1)
* @feature_enabled: segmentation feature enabled flags
* @feature_data: segmentation feature data
*/
struct hantro_vp9_dec_hw_ctx {
struct hantro_aux_buf tile_edge;
struct hantro_aux_buf segment_map;
struct hantro_aux_buf misc;
struct v4l2_vp9_frame_symbol_counts cnts;
struct v4l2_vp9_frame_context probability_tables;
struct v4l2_vp9_frame_context frame_context[4];
struct hantro_vp9_frame_info cur;
struct hantro_vp9_frame_info last;
unsigned int bsd_ctrl_offset;
unsigned int segment_map_size;
unsigned int ctx_counters_offset;
unsigned int tile_info_offset;
unsigned short tile_r_info[MAX_SB_ROWS];
unsigned short tile_c_info[MAX_SB_COLS];
unsigned int last_tile_r;
unsigned int last_tile_c;
unsigned int last_sbs_r;
unsigned int last_sbs_c;
unsigned int active_segment;
u8 feature_enabled[8];
s16 feature_data[8][4];
};
/**
* struct hantro_av1_dec_ctrls
* @sequence: AV1 Sequence
* @tile_group_entry: AV1 Tile Group entry
* @frame: AV1 Frame Header OBU
* @film_grain: AV1 Film Grain
*/
struct hantro_av1_dec_ctrls {
const struct v4l2_ctrl_av1_sequence *sequence;
const struct v4l2_ctrl_av1_tile_group_entry *tile_group_entry;
const struct v4l2_ctrl_av1_frame *frame;
const struct v4l2_ctrl_av1_film_grain *film_grain;
};
struct hantro_av1_frame_ref {
int width;
int height;
int mi_cols;
int mi_rows;
u64 timestamp;
enum v4l2_av1_frame_type frame_type;
bool used;
u32 order_hint;
u32 order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME];
struct vb2_v4l2_buffer *vb2_ref;
};
/**
* struct hantro_av1_dec_hw_ctx
* @db_data_col: db tile col data buffer
* @db_ctrl_col: db tile col ctrl buffer
* @cdef_col: cdef tile col buffer
* @sr_col: sr tile col buffer
* @lr_col: lr tile col buffer
* @global_model: global model buffer
* @tile_info: tile info buffer
* @segment: segmentation info buffer
* @film_grain: film grain buffer
* @prob_tbl: probability table
* @prob_tbl_out: probability table output
* @tile_buf: tile buffer
* @ctrls: V4L2 controls attached to a run
* @frame_refs: reference frames info slots
* @ref_frame_sign_bias: array of sign bias
* @num_tile_cols_allocated: number of allocated tiles
* @cdfs: current probabilities structure
* @cdfs_ndvc: current mv probabilities structure
* @default_cdfs: default probabilities structure
* @default_cdfs_ndvc: default mv probabilties structure
* @cdfs_last: stored probabilities structures
* @cdfs_last_ndvc: stored mv probabilities structures
* @current_frame_index: index of the current in frame_refs array
*/
struct hantro_av1_dec_hw_ctx {
struct hantro_aux_buf db_data_col;
struct hantro_aux_buf db_ctrl_col;
struct hantro_aux_buf cdef_col;
struct hantro_aux_buf sr_col;
struct hantro_aux_buf lr_col;
struct hantro_aux_buf global_model;
struct hantro_aux_buf tile_info;
struct hantro_aux_buf segment;
struct hantro_aux_buf film_grain;
struct hantro_aux_buf prob_tbl;
struct hantro_aux_buf prob_tbl_out;
struct hantro_aux_buf tile_buf;
struct hantro_av1_dec_ctrls ctrls;
struct hantro_av1_frame_ref frame_refs[AV1_MAX_FRAME_BUF_COUNT];
u32 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME];
unsigned int num_tile_cols_allocated;
struct av1cdfs *cdfs;
struct mvcdfs *cdfs_ndvc;
struct av1cdfs default_cdfs;
struct mvcdfs default_cdfs_ndvc;
struct av1cdfs cdfs_last[NUM_REF_FRAMES];
struct mvcdfs cdfs_last_ndvc[NUM_REF_FRAMES];
int current_frame_index;
};
/**
* struct hantro_postproc_ctx
*
* @dec_q: References buffers, in decoder format.
*/
struct hantro_postproc_ctx {
struct hantro_aux_buf dec_q[MAX_POSTPROC_BUFFERS];
};
/**
* struct hantro_postproc_ops - post-processor operations
*
* @enable: Enable the post-processor block. Optional.
* @disable: Disable the post-processor block. Optional.
* @enum_framesizes: Enumerate possible scaled output formats.
* Returns zero if OK, a negative value in error cases.
* Optional.
*/
struct hantro_postproc_ops {
void (*enable)(struct hantro_ctx *ctx);
void (*disable)(struct hantro_ctx *ctx);
int (*enum_framesizes)(struct hantro_ctx *ctx, struct v4l2_frmsizeenum *fsize);
};
/**
* struct hantro_codec_ops - codec mode specific operations
*
* @init: If needed, can be used for initialization.
* Optional and called from process context.
* @exit: If needed, can be used to undo the .init phase.
* Optional and called from process context.
* @run: Start single {en,de)coding job. Called from atomic context
* to indicate that a pair of buffers is ready and the hardware
* should be programmed and started. Returns zero if OK, a
* negative value in error cases.
* @done: Read back processing results and additional data from hardware.
* @reset: Reset the hardware in case of a timeout.
*/
struct hantro_codec_ops {
int (*init)(struct hantro_ctx *ctx);
void (*exit)(struct hantro_ctx *ctx);
int (*run)(struct hantro_ctx *ctx);
void (*done)(struct hantro_ctx *ctx);
void (*reset)(struct hantro_ctx *ctx);
};
/**
* enum hantro_enc_fmt - source format ID for hardware registers.
*
* @ROCKCHIP_VPU_ENC_FMT_YUV420P: Y/CbCr 4:2:0 planar format
* @ROCKCHIP_VPU_ENC_FMT_YUV420SP: Y/CbCr 4:2:0 semi-planar format
* @ROCKCHIP_VPU_ENC_FMT_YUYV422: YUV 4:2:2 packed format (YUYV)
* @ROCKCHIP_VPU_ENC_FMT_UYVY422: YUV 4:2:2 packed format (UYVY)
*/
enum hantro_enc_fmt {
ROCKCHIP_VPU_ENC_FMT_YUV420P = 0,
ROCKCHIP_VPU_ENC_FMT_YUV420SP = 1,
ROCKCHIP_VPU_ENC_FMT_YUYV422 = 2,
ROCKCHIP_VPU_ENC_FMT_UYVY422 = 3,
};
extern const struct hantro_variant imx8mm_vpu_g1_variant;
extern const struct hantro_variant imx8mq_vpu_g1_variant;
extern const struct hantro_variant imx8mq_vpu_g2_variant;
extern const struct hantro_variant imx8mq_vpu_variant;
extern const struct hantro_variant px30_vpu_variant;
extern const struct hantro_variant rk3036_vpu_variant;
extern const struct hantro_variant rk3066_vpu_variant;
extern const struct hantro_variant rk3288_vpu_variant;
extern const struct hantro_variant rk3328_vpu_variant;
extern const struct hantro_variant rk3399_vpu_variant;
extern const struct hantro_variant rk3568_vepu_variant;
extern const struct hantro_variant rk3568_vpu_variant;
extern const struct hantro_variant rk3588_vpu981_variant;
extern const struct hantro_variant sama5d4_vdec_variant;
extern const struct hantro_variant sunxi_vpu_variant;
extern const struct hantro_variant stm32mp25_vdec_variant;
extern const struct hantro_variant stm32mp25_venc_variant;
extern const struct hantro_postproc_ops hantro_g1_postproc_ops;
extern const struct hantro_postproc_ops hantro_g2_postproc_ops;
extern const struct hantro_postproc_ops rockchip_vpu981_postproc_ops;
extern const u32 hantro_vp8_dec_mc_filter[8][6];
void hantro_watchdog(struct work_struct *work);
void hantro_irq_done(struct hantro_dev *vpu,
enum vb2_buffer_state result);
void hantro_start_prepare_run(struct hantro_ctx *ctx);
void hantro_end_prepare_run(struct hantro_ctx *ctx);
irqreturn_t hantro_g1_irq(int irq, void *dev_id);
void hantro_g1_reset(struct hantro_ctx *ctx);
int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx);
int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx);
void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx);
void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx);
dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
unsigned int dpb_idx);
u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx,
unsigned int dpb_idx);
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx);
int rockchip_vpu2_h264_dec_run(struct hantro_ctx *ctx);
int hantro_g1_h264_dec_run(struct hantro_ctx *ctx);
int hantro_h264_dec_init(struct hantro_ctx *ctx);
void hantro_h264_dec_exit(struct hantro_ctx *ctx);
int hantro_hevc_dec_init(struct hantro_ctx *ctx);
void hantro_hevc_dec_exit(struct hantro_ctx *ctx);
int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx);
int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx);
void hantro_hevc_ref_init(struct hantro_ctx *ctx);
dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, s32 poc);
int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr);
int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx);
void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx);
int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx);
void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx);
static inline unsigned short hantro_vp9_num_sbs(unsigned short dimension)
{
return (dimension + 63) / 64;
}
static inline size_t
hantro_vp9_mv_size(unsigned int width, unsigned int height)
{
int num_ctbs;
/*
* There can be up to (CTBs x 64) number of blocks,
* and the motion vector for each block needs 16 bytes.
*/
num_ctbs = hantro_vp9_num_sbs(width) * hantro_vp9_num_sbs(height);
return (num_ctbs * 64) * 16;
}
static inline size_t
hantro_h264_mv_size(unsigned int width, unsigned int height)
{
/*
* A decoded 8-bit 4:2:0 NV12 frame may need memory for up to
* 448 bytes per macroblock with additional 32 bytes on
* multi-core variants.
*
* The H264 decoder needs extra space on the output buffers
* to store motion vectors. This is needed for reference
* frames and only if the format is non-post-processed NV12.
*
* Memory layout is as follow:
*
* +---------------------------+
* | Y-plane 256 bytes x MBs |
* +---------------------------+
* | UV-plane 128 bytes x MBs |
* +---------------------------+
* | MV buffer 64 bytes x MBs |
* +---------------------------+
* | MC sync 32 bytes |
* +---------------------------+
*/
return 64 * MB_WIDTH(width) * MB_WIDTH(height) + 32;
}
static inline size_t
hantro_hevc_mv_size(unsigned int width, unsigned int height)
{
/*
* A CTB can be 64x64, 32x32 or 16x16.
* Allocated memory for the "worse" case: 16x16
*/
return width * height / 16;
}
static inline size_t
hantro_hevc_luma_compressed_size(unsigned int width, unsigned int height)
{
u32 pic_width_in_cbsy =
round_up((width + CBS_LUMA - 1) / CBS_LUMA, CBS_SIZE);
u32 pic_height_in_cbsy = (height + CBS_LUMA - 1) / CBS_LUMA;
return round_up(pic_width_in_cbsy * pic_height_in_cbsy, CBS_SIZE);
}
static inline size_t
hantro_hevc_chroma_compressed_size(unsigned int width, unsigned int height)
{
u32 pic_width_in_cbsc =
round_up((width + CBS_CHROMA_W - 1) / CBS_CHROMA_W, CBS_SIZE);
u32 pic_height_in_cbsc = (height / 2 + CBS_CHROMA_H - 1) / CBS_CHROMA_H;
return round_up(pic_width_in_cbsc * pic_height_in_cbsc, CBS_SIZE);
}
static inline size_t
hantro_hevc_compressed_size(unsigned int width, unsigned int height)
{
return hantro_hevc_luma_compressed_size(width, height) +
hantro_hevc_chroma_compressed_size(width, height);
}
static inline unsigned short hantro_av1_num_sbs(unsigned short dimension)
{
return DIV_ROUND_UP(dimension, 64);
}
static inline size_t
hantro_av1_mv_size(unsigned int width, unsigned int height)
{
size_t num_sbs = hantro_av1_num_sbs(width) * hantro_av1_num_sbs(height);
return ALIGN(num_sbs * 384, 16) * 2 + 512;
}
size_t hantro_g2_chroma_offset(struct hantro_ctx *ctx);
size_t hantro_g2_motion_vectors_offset(struct hantro_ctx *ctx);
size_t hantro_g2_luma_compress_offset(struct hantro_ctx *ctx);
size_t hantro_g2_chroma_compress_offset(struct hantro_ctx *ctx);
int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx);
int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx);
void hantro_mpeg2_dec_copy_qtable(u8 *qtable,
const struct v4l2_ctrl_mpeg2_quantisation *ctrl);
int hantro_mpeg2_dec_init(struct hantro_ctx *ctx);
void hantro_mpeg2_dec_exit(struct hantro_ctx *ctx);
int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx);
int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx);
int hantro_vp8_dec_init(struct hantro_ctx *ctx);
void hantro_vp8_dec_exit(struct hantro_ctx *ctx);
void hantro_vp8_prob_update(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr);
int hantro_g2_vp9_dec_run(struct hantro_ctx *ctx);
void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx);
int hantro_vp9_dec_init(struct hantro_ctx *ctx);
void hantro_vp9_dec_exit(struct hantro_ctx *ctx);
void hantro_g2_check_idle(struct hantro_dev *vpu);
void hantro_g2_reset(struct hantro_ctx *ctx);
irqreturn_t hantro_g2_irq(int irq, void *dev_id);
#endif /* HANTRO_HW_H_ */
@@ -0,0 +1,245 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) Collabora, Ltd.
*
* Based on GSPCA and CODA drivers:
* Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
* Copyright (C) 2014 Philipp Zabel, Pengutronix
*/
#include <linux/align.h>
#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <media/v4l2-jpeg.h>
#include "hantro_jpeg.h"
#include "hantro.h"
#define LUMA_QUANT_OFF 25
#define CHROMA_QUANT_OFF 90
#define HEIGHT_OFF 159
#define WIDTH_OFF 161
#define HUFF_LUMA_DC_OFF 178
#define HUFF_LUMA_AC_OFF 211
#define HUFF_CHROMA_DC_OFF 394
#define HUFF_CHROMA_AC_OFF 427
static const u32 hw_reorder[] = {
0, 8, 16, 24, 1, 9, 17, 25,
32, 40, 48, 56, 33, 41, 49, 57,
2, 10, 18, 26, 3, 11, 19, 27,
34, 42, 50, 58, 35, 43, 51, 59,
4, 12, 20, 28, 5, 13, 21, 29,
36, 44, 52, 60, 37, 45, 53, 61,
6, 14, 22, 30, 7, 15, 23, 31,
38, 46, 54, 62, 39, 47, 55, 63
};
/* For simplicity, we keep a pre-formatted JPEG header,
* and we'll use fixed offsets to change the width, height
* quantization tables, etc.
*/
static const unsigned char hantro_jpeg_header[] = {
/* SOI */
0xff, 0xd8,
/* JFIF-APP0 */
0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
0x00, 0x00,
/* DQT */
0xff, 0xdb, 0x00, 0x84,
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,
0x01,
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,
/* SOF */
0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01,
0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01,
0x03, 0x11, 0x01,
/* DHT */
0xff, 0xc4, 0x00, 0x1f, 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,
/* DHT */
0xff, 0xc4, 0x00, 0xb5, 0x10,
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, 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,
/* DHT */
0xff, 0xc4, 0x00, 0x1f, 0x01,
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,
/* DHT */
0xff, 0xc4, 0x00, 0xb5, 0x11,
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, 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,
/* COM */
0xff, 0xfe, 0x00, 0x03, 0x00,
/* SOS */
0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
};
/*
* JPEG_HEADER_SIZE is used in other parts of the driver in lieu of
* "sizeof(hantro_jpeg_header)". The two must be equal.
*/
static_assert(sizeof(hantro_jpeg_header) == JPEG_HEADER_SIZE);
/*
* hantro_jpeg_header is padded with a COM segment, so that the payload
* of the SOS segment (the entropy-encoded image scan), which should
* trail the whole header, is 8-byte aligned for the hardware to write
* to directly.
*/
static_assert(IS_ALIGNED(sizeof(hantro_jpeg_header), 8),
"Hantro JPEG header size needs to be 8-byte aligned.");
static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
{
unsigned int temp;
temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100);
if (temp <= 0)
temp = 1;
if (temp > 255)
temp = 255;
return (unsigned char)temp;
}
static void
jpeg_scale_quant_table(unsigned char *file_q_tab,
unsigned char *reordered_q_tab,
const unsigned char *tab, int scale)
{
int i;
BUILD_BUG_ON(ARRAY_SIZE(v4l2_jpeg_zigzag_scan_index) != JPEG_QUANT_SIZE);
BUILD_BUG_ON(ARRAY_SIZE(hw_reorder) != JPEG_QUANT_SIZE);
for (i = 0; i < JPEG_QUANT_SIZE; i++) {
file_q_tab[i] = jpeg_scale_qp(tab[v4l2_jpeg_zigzag_scan_index[i]], scale);
reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale);
}
}
static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx)
{
int scale;
/*
* Non-linear scaling factor:
* [5,50] -> [1000..100], [51,100] -> [98..0]
*/
if (ctx->quality < 50)
scale = 5000 / ctx->quality;
else
scale = 200 - 2 * ctx->quality;
BUILD_BUG_ON(ARRAY_SIZE(v4l2_jpeg_ref_table_luma_qt) != JPEG_QUANT_SIZE);
BUILD_BUG_ON(ARRAY_SIZE(v4l2_jpeg_ref_table_chroma_qt) != JPEG_QUANT_SIZE);
BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_luma_qtable) != JPEG_QUANT_SIZE);
BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_chroma_qtable) != JPEG_QUANT_SIZE);
jpeg_scale_quant_table(ctx->buffer + LUMA_QUANT_OFF,
ctx->hw_luma_qtable,
(const unsigned char *)v4l2_jpeg_ref_table_luma_qt, scale);
jpeg_scale_quant_table(ctx->buffer + CHROMA_QUANT_OFF,
ctx->hw_chroma_qtable,
(const unsigned char *)v4l2_jpeg_ref_table_chroma_qt, scale);
}
void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
{
char *buf = ctx->buffer;
memcpy(buf, hantro_jpeg_header,
sizeof(hantro_jpeg_header));
buf[HEIGHT_OFF + 0] = ctx->height >> 8;
buf[HEIGHT_OFF + 1] = ctx->height;
buf[WIDTH_OFF + 0] = ctx->width >> 8;
buf[WIDTH_OFF + 1] = ctx->width;
memcpy(buf + HUFF_LUMA_DC_OFF, v4l2_jpeg_ref_table_luma_dc_ht, V4L2_JPEG_REF_HT_DC_LEN);
memcpy(buf + HUFF_LUMA_AC_OFF, v4l2_jpeg_ref_table_luma_ac_ht, V4L2_JPEG_REF_HT_AC_LEN);
memcpy(buf + HUFF_CHROMA_DC_OFF, v4l2_jpeg_ref_table_chroma_dc_ht, V4L2_JPEG_REF_HT_DC_LEN);
memcpy(buf + HUFF_CHROMA_AC_OFF, v4l2_jpeg_ref_table_chroma_ac_ht, V4L2_JPEG_REF_HT_AC_LEN);
jpeg_set_quality(ctx);
}
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#define JPEG_HEADER_SIZE 624
#define JPEG_QUANT_SIZE 64
struct hantro_jpeg_ctx {
int width;
int height;
int quality;
unsigned char *buffer;
unsigned char hw_luma_qtable[JPEG_QUANT_SIZE];
unsigned char hw_chroma_qtable[JPEG_QUANT_SIZE];
};
void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx);
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*/
#include "hantro.h"
static const u8 zigzag[64] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
void hantro_mpeg2_dec_copy_qtable(u8 *qtable,
const struct v4l2_ctrl_mpeg2_quantisation *ctrl)
{
int i, n;
if (!qtable || !ctrl)
return;
for (i = 0; i < ARRAY_SIZE(zigzag); i++) {
n = zigzag[i];
qtable[n + 0] = ctrl->intra_quantiser_matrix[i];
qtable[n + 64] = ctrl->non_intra_quantiser_matrix[i];
qtable[n + 128] = ctrl->chroma_intra_quantiser_matrix[i];
qtable[n + 192] = ctrl->chroma_non_intra_quantiser_matrix[i];
}
}
int hantro_mpeg2_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
ctx->mpeg2_dec.qtable.size = ARRAY_SIZE(zigzag) * 4;
ctx->mpeg2_dec.qtable.cpu =
dma_alloc_coherent(vpu->dev,
ctx->mpeg2_dec.qtable.size,
&ctx->mpeg2_dec.qtable.dma,
GFP_KERNEL);
if (!ctx->mpeg2_dec.qtable.cpu)
return -ENOMEM;
return 0;
}
void hantro_mpeg2_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
dma_free_coherent(vpu->dev,
ctx->mpeg2_dec.qtable.size,
ctx->mpeg2_dec.qtable.cpu,
ctx->mpeg2_dec.qtable.dma);
}
@@ -0,0 +1,344 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro G1 post-processor support
*
* Copyright (C) 2019 Collabora, Ltd.
*/
#include <linux/dma-mapping.h>
#include <linux/types.h>
#include "hantro.h"
#include "hantro_hw.h"
#include "hantro_g1_regs.h"
#include "hantro_g2_regs.h"
#include "hantro_v4l2.h"
#define HANTRO_PP_REG_WRITE(vpu, reg_name, val) \
{ \
hantro_reg_write(vpu, \
&hantro_g1_postproc_regs.reg_name, \
val); \
}
#define HANTRO_PP_REG_WRITE_RELAXED(vpu, reg_name, val) \
{ \
hantro_reg_write_relaxed(vpu, \
&hantro_g1_postproc_regs.reg_name, \
val); \
}
#define VPU_PP_IN_YUYV 0x0
#define VPU_PP_IN_NV12 0x1
#define VPU_PP_IN_YUV420 0x2
#define VPU_PP_IN_YUV240_TILED 0x5
#define VPU_PP_OUT_RGB 0x0
#define VPU_PP_OUT_YUYV 0x3
static const struct hantro_postproc_regs hantro_g1_postproc_regs = {
.pipeline_en = {G1_REG_PP_INTERRUPT, 1, 0x1},
.max_burst = {G1_REG_PP_DEV_CONFIG, 0, 0x1f},
.clk_gate = {G1_REG_PP_DEV_CONFIG, 1, 0x1},
.out_swap32 = {G1_REG_PP_DEV_CONFIG, 5, 0x1},
.out_endian = {G1_REG_PP_DEV_CONFIG, 6, 0x1},
.out_luma_base = {G1_REG_PP_OUT_LUMA_BASE, 0, 0xffffffff},
.input_width = {G1_REG_PP_INPUT_SIZE, 0, 0x1ff},
.input_height = {G1_REG_PP_INPUT_SIZE, 9, 0x1ff},
.output_width = {G1_REG_PP_CONTROL, 4, 0x7ff},
.output_height = {G1_REG_PP_CONTROL, 15, 0x7ff},
.input_fmt = {G1_REG_PP_CONTROL, 29, 0x7},
.output_fmt = {G1_REG_PP_CONTROL, 26, 0x7},
.orig_width = {G1_REG_PP_MASK1_ORIG_WIDTH, 23, 0x1ff},
.display_width = {G1_REG_PP_DISPLAY_WIDTH_IN_EXT, 0, 0xfff},
.input_width_ext = {G1_REG_PP_DISPLAY_WIDTH_IN_EXT, 26, 0x7},
.input_height_ext = {G1_REG_PP_DISPLAY_WIDTH_IN_EXT, 29, 0x7},
};
bool hantro_needs_postproc(const struct hantro_ctx *ctx,
const struct hantro_fmt *fmt)
{
if (ctx->is_encoder)
return false;
if (ctx->need_postproc)
return true;
return fmt->postprocessed;
}
static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *dst_buf;
u32 src_pp_fmt, dst_pp_fmt;
dma_addr_t dst_dma;
/* Turn on pipeline mode. Must be done first. */
HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x1);
src_pp_fmt = VPU_PP_IN_NV12;
switch (ctx->vpu_dst_fmt->fourcc) {
case V4L2_PIX_FMT_YUYV:
dst_pp_fmt = VPU_PP_OUT_YUYV;
break;
default:
WARN(1, "output format %d not supported by the post-processor, this wasn't expected.",
ctx->vpu_dst_fmt->fourcc);
dst_pp_fmt = 0;
break;
}
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
dst_dma = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
HANTRO_PP_REG_WRITE(vpu, clk_gate, 0x1);
HANTRO_PP_REG_WRITE(vpu, out_endian, 0x1);
HANTRO_PP_REG_WRITE(vpu, out_swap32, 0x1);
HANTRO_PP_REG_WRITE(vpu, max_burst, 16);
HANTRO_PP_REG_WRITE(vpu, out_luma_base, dst_dma);
HANTRO_PP_REG_WRITE(vpu, input_width, MB_WIDTH(ctx->dst_fmt.width));
HANTRO_PP_REG_WRITE(vpu, input_height, MB_HEIGHT(ctx->dst_fmt.height));
HANTRO_PP_REG_WRITE(vpu, input_fmt, src_pp_fmt);
HANTRO_PP_REG_WRITE(vpu, output_fmt, dst_pp_fmt);
HANTRO_PP_REG_WRITE(vpu, output_width, ctx->dst_fmt.width);
HANTRO_PP_REG_WRITE(vpu, output_height, ctx->dst_fmt.height);
HANTRO_PP_REG_WRITE(vpu, orig_width, MB_WIDTH(ctx->dst_fmt.width));
HANTRO_PP_REG_WRITE(vpu, display_width, ctx->dst_fmt.width);
HANTRO_PP_REG_WRITE(vpu, input_width_ext, MB_WIDTH(ctx->dst_fmt.width) >> 9);
HANTRO_PP_REG_WRITE(vpu, input_height_ext, MB_HEIGHT(ctx->dst_fmt.height >> 8));
}
static int down_scale_factor(struct hantro_ctx *ctx)
{
if (ctx->src_fmt.width <= ctx->dst_fmt.width)
return 0;
return DIV_ROUND_CLOSEST(ctx->src_fmt.width, ctx->dst_fmt.width);
}
static void hantro_postproc_g2_enable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *dst_buf;
int down_scale = down_scale_factor(ctx);
int out_depth;
size_t chroma_offset;
dma_addr_t dst_dma;
dst_buf = hantro_get_dst_buf(ctx);
dst_dma = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
chroma_offset = ctx->dst_fmt.plane_fmt[0].bytesperline *
ctx->dst_fmt.height;
if (down_scale) {
hantro_reg_write(vpu, &g2_down_scale_e, 1);
hantro_reg_write(vpu, &g2_down_scale_y, down_scale >> 2);
hantro_reg_write(vpu, &g2_down_scale_x, down_scale >> 2);
hantro_write_addr(vpu, G2_DS_DST, dst_dma);
hantro_write_addr(vpu, G2_DS_DST_CHR, dst_dma + (chroma_offset >> down_scale));
} else {
hantro_write_addr(vpu, G2_RS_OUT_LUMA_ADDR, dst_dma);
hantro_write_addr(vpu, G2_RS_OUT_CHROMA_ADDR, dst_dma + chroma_offset);
}
out_depth = hantro_get_format_depth(ctx->dst_fmt.pixelformat);
if (ctx->dev->variant->legacy_regs) {
u8 pp_shift = 0;
if (out_depth > 8)
pp_shift = 16 - out_depth;
hantro_reg_write(ctx->dev, &g2_rs_out_bit_depth, out_depth);
hantro_reg_write(ctx->dev, &g2_pp_pix_shift, pp_shift);
} else {
hantro_reg_write(vpu, &g2_output_8_bits, out_depth > 8 ? 0 : 1);
hantro_reg_write(vpu, &g2_output_format, out_depth > 8 ? 1 : 0);
}
hantro_reg_write(vpu, &g2_out_rs_e, 1);
}
static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
struct v4l2_frmsizeenum *fsize)
{
/**
* G2 scaler can scale down by 0, 2, 4 or 8
* use fsize->index has power of 2 diviser
**/
if (fsize->index > 3)
return -EINVAL;
if (!ctx->src_fmt.width || !ctx->src_fmt.height)
return -EINVAL;
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
fsize->discrete.width = ctx->src_fmt.width >> fsize->index;
fsize->discrete.height = ctx->src_fmt.height >> fsize->index;
return 0;
}
void hantro_postproc_free(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
unsigned int i;
for (i = 0; i < queue->max_num_buffers; ++i) {
struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
if (priv->cpu) {
dma_free_attrs(vpu->dev, priv->size, priv->cpu,
priv->dma, priv->attrs);
priv->cpu = NULL;
}
}
}
static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
{
unsigned int buf_size;
buf_size = ctx->ref_fmt.plane_fmt[0].sizeimage;
if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE)
buf_size += hantro_h264_mv_size(ctx->ref_fmt.width,
ctx->ref_fmt.height);
else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_VP9_FRAME)
buf_size += hantro_vp9_mv_size(ctx->ref_fmt.width,
ctx->ref_fmt.height);
else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) {
buf_size += hantro_hevc_mv_size(ctx->ref_fmt.width,
ctx->ref_fmt.height);
if (ctx->hevc_dec.use_compression)
buf_size += hantro_hevc_compressed_size(ctx->ref_fmt.width,
ctx->ref_fmt.height);
}
else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME)
buf_size += hantro_av1_mv_size(ctx->ref_fmt.width,
ctx->ref_fmt.height);
return buf_size;
}
static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
unsigned int buf_size = hantro_postproc_buffer_size(ctx);
if (!buf_size)
return -EINVAL;
/*
* The buffers on this queue are meant as intermediate
* buffers for the decoder, so no mapping is needed.
*/
priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
GFP_KERNEL, priv->attrs);
if (!priv->cpu)
return -ENOMEM;
priv->size = buf_size;
return 0;
}
int hantro_postproc_init(struct hantro_ctx *ctx)
{
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
unsigned int num_buffers = vb2_get_num_buffers(cap_queue);
unsigned int i;
int ret;
for (i = 0; i < num_buffers; i++) {
ret = hantro_postproc_alloc(ctx, i);
if (ret) {
hantro_postproc_free(ctx);
return ret;
}
}
return 0;
}
dma_addr_t
hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
{
struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
unsigned int buf_size = hantro_postproc_buffer_size(ctx);
struct hantro_dev *vpu = ctx->dev;
int ret;
if (priv->size < buf_size && priv->cpu) {
/* buffer is too small, release it */
dma_free_attrs(vpu->dev, priv->size, priv->cpu,
priv->dma, priv->attrs);
priv->cpu = NULL;
}
if (!priv->cpu) {
/* buffer not already allocated, try getting a new one */
ret = hantro_postproc_alloc(ctx, index);
if (ret)
return 0;
}
if (!priv->cpu)
return 0;
return priv->dma;
}
static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x0);
}
static void hantro_postproc_g2_disable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
hantro_reg_write(vpu, &g2_out_rs_e, 0);
}
void hantro_postproc_disable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
if (vpu->variant->postproc_ops && vpu->variant->postproc_ops->disable)
vpu->variant->postproc_ops->disable(ctx);
}
void hantro_postproc_enable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
if (vpu->variant->postproc_ops && vpu->variant->postproc_ops->enable)
vpu->variant->postproc_ops->enable(ctx);
}
int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
struct v4l2_frmsizeenum *fsize)
{
struct hantro_dev *vpu = ctx->dev;
if (vpu->variant->postproc_ops && vpu->variant->postproc_ops->enum_framesizes)
return vpu->variant->postproc_ops->enum_framesizes(ctx, fsize);
return -EINVAL;
}
const struct hantro_postproc_ops hantro_g1_postproc_ops = {
.enable = hantro_postproc_g1_enable,
.disable = hantro_postproc_g1_disable,
};
const struct hantro_postproc_ops hantro_g2_postproc_ops = {
.enable = hantro_postproc_g2_enable,
.disable = hantro_postproc_g2_disable,
.enum_framesizes = hantro_postproc_g2_enum_framesizes,
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
* Alpha Lin <Alpha.Lin@rock-chips.com>
* Jeffy Chen <jeffy.chen@rock-chips.com>
*
* Copyright 2018 Google LLC.
* Tomasz Figa <tfiga@chromium.org>
*
* Based on s5p-mfc driver by Samsung Electronics Co., Ltd.
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
*/
#ifndef HANTRO_V4L2_H_
#define HANTRO_V4L2_H_
#include "hantro.h"
#define HANTRO_FORCE_POSTPROC true
#define HANTRO_AUTO_POSTPROC false
extern const struct v4l2_ioctl_ops hantro_ioctl_ops;
extern const struct vb2_ops hantro_queue_ops;
int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc);
void hantro_reset_fmts(struct hantro_ctx *ctx);
int hantro_get_format_depth(u32 fourcc);
const struct hantro_fmt *
hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream,
int bit_depth, bool need_postproc);
#endif /* HANTRO_V4L2_H_ */
@@ -0,0 +1,201 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*/
#include "hantro.h"
/*
* probs table with packed
*/
struct vp8_prob_tbl_packed {
u8 prob_mb_skip_false;
u8 prob_intra;
u8 prob_ref_last;
u8 prob_ref_golden;
u8 prob_segment[3];
u8 padding0;
u8 prob_luma_16x16_pred_mode[4];
u8 prob_chroma_pred_mode[3];
u8 padding1;
/* mv prob */
u8 prob_mv_context[2][V4L2_VP8_MV_PROB_CNT];
u8 padding2[2];
/* coeff probs */
u8 prob_coeffs[4][8][3][V4L2_VP8_COEFF_PROB_CNT];
u8 padding3[96];
};
/*
* filter taps taken to 7-bit precision,
* reference RFC6386#Page-16, filters[8][6]
*/
const u32 hantro_vp8_dec_mc_filter[8][6] = {
{ 0, 0, 128, 0, 0, 0 },
{ 0, -6, 123, 12, -1, 0 },
{ 2, -11, 108, 36, -8, 1 },
{ 0, -9, 93, 50, -6, 0 },
{ 3, -16, 77, 77, -16, 3 },
{ 0, -6, 50, 93, -9, 0 },
{ 1, -8, 36, 108, -11, 2 },
{ 0, -1, 12, 123, -6, 0 }
};
void hantro_vp8_prob_update(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
const struct v4l2_vp8_entropy *entropy = &hdr->entropy;
u32 i, j, k;
u8 *dst;
/* first probs */
dst = ctx->vp8_dec.prob_tbl.cpu;
dst[0] = hdr->prob_skip_false;
dst[1] = hdr->prob_intra;
dst[2] = hdr->prob_last;
dst[3] = hdr->prob_gf;
dst[4] = hdr->segment.segment_probs[0];
dst[5] = hdr->segment.segment_probs[1];
dst[6] = hdr->segment.segment_probs[2];
dst[7] = 0;
dst += 8;
dst[0] = entropy->y_mode_probs[0];
dst[1] = entropy->y_mode_probs[1];
dst[2] = entropy->y_mode_probs[2];
dst[3] = entropy->y_mode_probs[3];
dst[4] = entropy->uv_mode_probs[0];
dst[5] = entropy->uv_mode_probs[1];
dst[6] = entropy->uv_mode_probs[2];
dst[7] = 0; /*unused */
/* mv probs */
dst += 8;
dst[0] = entropy->mv_probs[0][0]; /* is short */
dst[1] = entropy->mv_probs[1][0];
dst[2] = entropy->mv_probs[0][1]; /* sign */
dst[3] = entropy->mv_probs[1][1];
dst[4] = entropy->mv_probs[0][8 + 9];
dst[5] = entropy->mv_probs[0][9 + 9];
dst[6] = entropy->mv_probs[1][8 + 9];
dst[7] = entropy->mv_probs[1][9 + 9];
dst += 8;
for (i = 0; i < 2; ++i) {
for (j = 0; j < 8; j += 4) {
dst[0] = entropy->mv_probs[i][j + 9 + 0];
dst[1] = entropy->mv_probs[i][j + 9 + 1];
dst[2] = entropy->mv_probs[i][j + 9 + 2];
dst[3] = entropy->mv_probs[i][j + 9 + 3];
dst += 4;
}
}
for (i = 0; i < 2; ++i) {
dst[0] = entropy->mv_probs[i][0 + 2];
dst[1] = entropy->mv_probs[i][1 + 2];
dst[2] = entropy->mv_probs[i][2 + 2];
dst[3] = entropy->mv_probs[i][3 + 2];
dst[4] = entropy->mv_probs[i][4 + 2];
dst[5] = entropy->mv_probs[i][5 + 2];
dst[6] = entropy->mv_probs[i][6 + 2];
dst[7] = 0; /*unused */
dst += 8;
}
/* coeff probs (header part) */
dst = ctx->vp8_dec.prob_tbl.cpu;
dst += (8 * 7);
for (i = 0; i < 4; ++i) {
for (j = 0; j < 8; ++j) {
for (k = 0; k < 3; ++k) {
dst[0] = entropy->coeff_probs[i][j][k][0];
dst[1] = entropy->coeff_probs[i][j][k][1];
dst[2] = entropy->coeff_probs[i][j][k][2];
dst[3] = entropy->coeff_probs[i][j][k][3];
dst += 4;
}
}
}
/* coeff probs (footer part) */
dst = ctx->vp8_dec.prob_tbl.cpu;
dst += (8 * 55);
for (i = 0; i < 4; ++i) {
for (j = 0; j < 8; ++j) {
for (k = 0; k < 3; ++k) {
dst[0] = entropy->coeff_probs[i][j][k][4];
dst[1] = entropy->coeff_probs[i][j][k][5];
dst[2] = entropy->coeff_probs[i][j][k][6];
dst[3] = entropy->coeff_probs[i][j][k][7];
dst[4] = entropy->coeff_probs[i][j][k][8];
dst[5] = entropy->coeff_probs[i][j][k][9];
dst[6] = entropy->coeff_probs[i][j][k][10];
dst[7] = 0; /*unused */
dst += 8;
}
}
}
}
int hantro_vp8_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_aux_buf *aux_buf;
unsigned int mb_width, mb_height;
size_t segment_map_size;
int ret;
/* segment map table size calculation */
mb_width = DIV_ROUND_UP(ctx->dst_fmt.width, 16);
mb_height = DIV_ROUND_UP(ctx->dst_fmt.height, 16);
segment_map_size = round_up(DIV_ROUND_UP(mb_width * mb_height, 4), 64);
/*
* In context init the dma buffer for segment map must be allocated.
* And the data in segment map buffer must be set to all zero.
*/
aux_buf = &ctx->vp8_dec.segment_map;
aux_buf->size = segment_map_size;
aux_buf->cpu = dma_alloc_coherent(vpu->dev, aux_buf->size,
&aux_buf->dma, GFP_KERNEL);
if (!aux_buf->cpu)
return -ENOMEM;
/*
* Allocate probability table buffer,
* total 1208 bytes, 4K page is far enough.
*/
aux_buf = &ctx->vp8_dec.prob_tbl;
aux_buf->size = sizeof(struct vp8_prob_tbl_packed);
aux_buf->cpu = dma_alloc_coherent(vpu->dev, aux_buf->size,
&aux_buf->dma, GFP_KERNEL);
if (!aux_buf->cpu) {
ret = -ENOMEM;
goto err_free_seg_map;
}
return 0;
err_free_seg_map:
dma_free_coherent(vpu->dev, ctx->vp8_dec.segment_map.size,
ctx->vp8_dec.segment_map.cpu,
ctx->vp8_dec.segment_map.dma);
return ret;
}
void hantro_vp8_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_vp8_dec_hw_ctx *vp8_dec = &ctx->vp8_dec;
struct hantro_dev *vpu = ctx->dev;
dma_free_coherent(vpu->dev, vp8_dec->segment_map.size,
vp8_dec->segment_map.cpu, vp8_dec->segment_map.dma);
dma_free_coherent(vpu->dev, vp8_dec->prob_tbl.size,
vp8_dec->prob_tbl.cpu, vp8_dec->prob_tbl.dma);
}
@@ -0,0 +1,240 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VP9 codec driver
*
* Copyright (C) 2021 Collabora Ltd.
*/
#include <linux/types.h>
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
#include "hantro_vp9.h"
#define POW2(x) (1 << (x))
#define MAX_LOG2_TILE_COLUMNS 6
#define MAX_NUM_TILE_COLS POW2(MAX_LOG2_TILE_COLUMNS)
#define MAX_TILE_COLS 20
#define MAX_TILE_ROWS 22
static size_t hantro_vp9_tile_filter_size(unsigned int height)
{
u32 h, height32, size;
h = roundup(height, 8);
height32 = roundup(h, 64);
size = 24 * height32 * (MAX_NUM_TILE_COLS - 1); /* luma: 8, chroma: 8 + 8 */
return size;
}
static size_t hantro_vp9_bsd_control_size(unsigned int height)
{
u32 h, height32;
h = roundup(height, 8);
height32 = roundup(h, 64);
return 16 * (height32 / 4) * (MAX_NUM_TILE_COLS - 1);
}
static size_t hantro_vp9_segment_map_size(unsigned int width, unsigned int height)
{
u32 w, h;
int num_ctbs;
w = roundup(width, 8);
h = roundup(height, 8);
num_ctbs = ((w + 63) / 64) * ((h + 63) / 64);
return num_ctbs * 32;
}
static inline size_t hantro_vp9_prob_tab_size(void)
{
return roundup(sizeof(struct hantro_g2_all_probs), 16);
}
static inline size_t hantro_vp9_count_tab_size(void)
{
return roundup(sizeof(struct symbol_counts), 16);
}
static inline size_t hantro_vp9_tile_info_size(void)
{
return roundup((MAX_TILE_COLS * MAX_TILE_ROWS * 4 * sizeof(u16) + 15 + 16) & ~0xf, 16);
}
static void *get_coeffs_arr(struct symbol_counts *cnts, int i, int j, int k, int l, int m)
{
if (i == 0)
return &cnts->count_coeffs[j][k][l][m];
if (i == 1)
return &cnts->count_coeffs8x8[j][k][l][m];
if (i == 2)
return &cnts->count_coeffs16x16[j][k][l][m];
if (i == 3)
return &cnts->count_coeffs32x32[j][k][l][m];
return NULL;
}
static void *get_eobs1(struct symbol_counts *cnts, int i, int j, int k, int l, int m)
{
if (i == 0)
return &cnts->count_coeffs[j][k][l][m][3];
if (i == 1)
return &cnts->count_coeffs8x8[j][k][l][m][3];
if (i == 2)
return &cnts->count_coeffs16x16[j][k][l][m][3];
if (i == 3)
return &cnts->count_coeffs32x32[j][k][l][m][3];
return NULL;
}
#define INNER_LOOP \
do { \
for (m = 0; m < ARRAY_SIZE(vp9_ctx->cnts.coeff[i][0][0][0]); ++m) { \
vp9_ctx->cnts.coeff[i][j][k][l][m] = \
get_coeffs_arr(cnts, i, j, k, l, m); \
vp9_ctx->cnts.eob[i][j][k][l][m][0] = \
&cnts->count_eobs[i][j][k][l][m]; \
vp9_ctx->cnts.eob[i][j][k][l][m][1] = \
get_eobs1(cnts, i, j, k, l, m); \
} \
} while (0)
static void init_v4l2_vp9_count_tbl(struct hantro_ctx *ctx)
{
struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec;
struct symbol_counts *cnts = vp9_ctx->misc.cpu + vp9_ctx->ctx_counters_offset;
int i, j, k, l, m;
vp9_ctx->cnts.partition = &cnts->partition_counts;
vp9_ctx->cnts.skip = &cnts->mbskip_count;
vp9_ctx->cnts.intra_inter = &cnts->intra_inter_count;
vp9_ctx->cnts.tx32p = &cnts->tx32x32_count;
/*
* g2 hardware uses tx16x16_count[2][3], while the api
* expects tx16p[2][4], so this must be explicitly copied
* into vp9_ctx->cnts.tx16p when passing the data to the
* vp9 library function
*/
vp9_ctx->cnts.tx8p = &cnts->tx8x8_count;
vp9_ctx->cnts.y_mode = &cnts->sb_ymode_counts;
vp9_ctx->cnts.uv_mode = &cnts->uv_mode_counts;
vp9_ctx->cnts.comp = &cnts->comp_inter_count;
vp9_ctx->cnts.comp_ref = &cnts->comp_ref_count;
vp9_ctx->cnts.single_ref = &cnts->single_ref_count;
vp9_ctx->cnts.filter = &cnts->switchable_interp_counts;
vp9_ctx->cnts.mv_joint = &cnts->mv_counts.joints;
vp9_ctx->cnts.sign = &cnts->mv_counts.sign;
vp9_ctx->cnts.classes = &cnts->mv_counts.classes;
vp9_ctx->cnts.class0 = &cnts->mv_counts.class0;
vp9_ctx->cnts.bits = &cnts->mv_counts.bits;
vp9_ctx->cnts.class0_fp = &cnts->mv_counts.class0_fp;
vp9_ctx->cnts.fp = &cnts->mv_counts.fp;
vp9_ctx->cnts.class0_hp = &cnts->mv_counts.class0_hp;
vp9_ctx->cnts.hp = &cnts->mv_counts.hp;
for (i = 0; i < ARRAY_SIZE(vp9_ctx->cnts.coeff); ++i)
for (j = 0; j < ARRAY_SIZE(vp9_ctx->cnts.coeff[i]); ++j)
for (k = 0; k < ARRAY_SIZE(vp9_ctx->cnts.coeff[i][0]); ++k)
for (l = 0; l < ARRAY_SIZE(vp9_ctx->cnts.coeff[i][0][0]); ++l)
INNER_LOOP;
}
int hantro_vp9_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
const struct hantro_variant *variant = vpu->variant;
struct hantro_vp9_dec_hw_ctx *vp9_dec = &ctx->vp9_dec;
struct hantro_aux_buf *tile_edge = &vp9_dec->tile_edge;
struct hantro_aux_buf *segment_map = &vp9_dec->segment_map;
struct hantro_aux_buf *misc = &vp9_dec->misc;
u32 i, max_width, max_height, size;
if (variant->num_dec_fmts < 1)
return -EINVAL;
for (i = 0; i < variant->num_dec_fmts; ++i)
if (variant->dec_fmts[i].fourcc == V4L2_PIX_FMT_VP9_FRAME)
break;
if (i == variant->num_dec_fmts)
return -EINVAL;
max_width = vpu->variant->dec_fmts[i].frmsize.max_width;
max_height = vpu->variant->dec_fmts[i].frmsize.max_height;
size = hantro_vp9_tile_filter_size(max_height);
vp9_dec->bsd_ctrl_offset = size;
size += hantro_vp9_bsd_control_size(max_height);
tile_edge->cpu = dma_alloc_coherent(vpu->dev, size, &tile_edge->dma, GFP_KERNEL);
if (!tile_edge->cpu)
return -ENOMEM;
tile_edge->size = size;
memset(tile_edge->cpu, 0, size);
size = hantro_vp9_segment_map_size(max_width, max_height);
vp9_dec->segment_map_size = size;
size *= 2; /* we need two areas of this size, used alternately */
segment_map->cpu = dma_alloc_coherent(vpu->dev, size, &segment_map->dma, GFP_KERNEL);
if (!segment_map->cpu)
goto err_segment_map;
segment_map->size = size;
memset(segment_map->cpu, 0, size);
size = hantro_vp9_prob_tab_size();
vp9_dec->ctx_counters_offset = size;
size += hantro_vp9_count_tab_size();
vp9_dec->tile_info_offset = size;
size += hantro_vp9_tile_info_size();
misc->cpu = dma_alloc_coherent(vpu->dev, size, &misc->dma, GFP_KERNEL);
if (!misc->cpu)
goto err_misc;
misc->size = size;
memset(misc->cpu, 0, size);
init_v4l2_vp9_count_tbl(ctx);
return 0;
err_misc:
dma_free_coherent(vpu->dev, segment_map->size, segment_map->cpu, segment_map->dma);
err_segment_map:
dma_free_coherent(vpu->dev, tile_edge->size, tile_edge->cpu, tile_edge->dma);
return -ENOMEM;
}
void hantro_vp9_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_vp9_dec_hw_ctx *vp9_dec = &ctx->vp9_dec;
struct hantro_aux_buf *tile_edge = &vp9_dec->tile_edge;
struct hantro_aux_buf *segment_map = &vp9_dec->segment_map;
struct hantro_aux_buf *misc = &vp9_dec->misc;
dma_free_coherent(vpu->dev, misc->size, misc->cpu, misc->dma);
dma_free_coherent(vpu->dev, segment_map->size, segment_map->cpu, segment_map->dma);
dma_free_coherent(vpu->dev, tile_edge->size, tile_edge->cpu, tile_edge->dma);
}
@@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VP9 codec driver
*
* Copyright (C) 2021 Collabora Ltd.
*/
struct hantro_g2_mv_probs {
u8 joint[3];
u8 sign[2];
u8 class0_bit[2][1];
u8 fr[2][3];
u8 class0_hp[2];
u8 hp[2];
u8 classes[2][10];
u8 class0_fr[2][2][3];
u8 bits[2][10];
};
struct hantro_g2_probs {
u8 inter_mode[7][4];
u8 is_inter[4];
u8 uv_mode[10][8];
u8 tx8[2][1];
u8 tx16[2][2];
u8 tx32[2][3];
u8 y_mode_tail[4][1];
u8 y_mode[4][8];
u8 partition[2][16][4]; /* [keyframe][][], [inter][][] */
u8 uv_mode_tail[10][1];
u8 interp_filter[4][2];
u8 comp_mode[5];
u8 skip[3];
u8 pad1[1];
struct hantro_g2_mv_probs mv;
u8 single_ref[5][2];
u8 comp_ref[5];
u8 pad2[17];
u8 coef[4][2][2][6][6][4];
};
struct hantro_g2_all_probs {
u8 kf_y_mode_prob[10][10][8];
u8 kf_y_mode_prob_tail[10][10][1];
u8 ref_pred_probs[3];
u8 mb_segment_tree_probs[7];
u8 segment_pred_probs[3];
u8 ref_scores[4];
u8 prob_comppred[2];
u8 pad1[9];
u8 kf_uv_mode_prob[10][8];
u8 kf_uv_mode_prob_tail[10][1];
u8 pad2[6];
struct hantro_g2_probs probs;
};
struct mv_counts {
u32 joints[4];
u32 sign[2][2];
u32 classes[2][11];
u32 class0[2][2];
u32 bits[2][10][2];
u32 class0_fp[2][2][4];
u32 fp[2][4];
u32 class0_hp[2][2];
u32 hp[2][2];
};
struct symbol_counts {
u32 inter_mode_counts[7][3][2];
u32 sb_ymode_counts[4][10];
u32 uv_mode_counts[10][10];
u32 partition_counts[16][4];
u32 switchable_interp_counts[4][3];
u32 intra_inter_count[4][2];
u32 comp_inter_count[5][2];
u32 single_ref_count[5][2][2];
u32 comp_ref_count[5][2];
u32 tx32x32_count[2][4];
u32 tx16x16_count[2][3];
u32 tx8x8_count[2][2];
u32 mbskip_count[3][2];
struct mv_counts mv_counts;
u32 count_coeffs[2][2][6][6][4];
u32 count_coeffs8x8[2][2][6][6][4];
u32 count_coeffs16x16[2][2][6][6][4];
u32 count_coeffs32x32[2][2][6][6][4];
u32 count_eobs[4][2][2][6][6];
};
@@ -0,0 +1,394 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2019 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include "hantro.h"
#include "hantro_jpeg.h"
#include "hantro_g1_regs.h"
#include "hantro_g2_regs.h"
#define CTRL_SOFT_RESET 0x00
#define RESET_G1 BIT(1)
#define RESET_G2 BIT(0)
#define CTRL_CLOCK_ENABLE 0x04
#define CLOCK_G1 BIT(1)
#define CLOCK_G2 BIT(0)
#define CTRL_G1_DEC_FUSE 0x08
#define CTRL_G1_PP_FUSE 0x0c
#define CTRL_G2_DEC_FUSE 0x10
static void imx8m_soft_reset(struct hantro_dev *vpu, u32 reset_bits)
{
u32 val;
/* Assert */
val = readl(vpu->ctrl_base + CTRL_SOFT_RESET);
val &= ~reset_bits;
writel(val, vpu->ctrl_base + CTRL_SOFT_RESET);
udelay(2);
/* Release */
val = readl(vpu->ctrl_base + CTRL_SOFT_RESET);
val |= reset_bits;
writel(val, vpu->ctrl_base + CTRL_SOFT_RESET);
}
static void imx8m_clk_enable(struct hantro_dev *vpu, u32 clock_bits)
{
u32 val;
val = readl(vpu->ctrl_base + CTRL_CLOCK_ENABLE);
val |= clock_bits;
writel(val, vpu->ctrl_base + CTRL_CLOCK_ENABLE);
}
static int imx8mq_runtime_resume(struct hantro_dev *vpu)
{
int ret;
ret = clk_bulk_prepare_enable(vpu->variant->num_clocks, vpu->clocks);
if (ret) {
dev_err(vpu->dev, "Failed to enable clocks\n");
return ret;
}
imx8m_soft_reset(vpu, RESET_G1 | RESET_G2);
imx8m_clk_enable(vpu, CLOCK_G1 | CLOCK_G2);
/* Set values of the fuse registers */
writel(0xffffffff, vpu->ctrl_base + CTRL_G1_DEC_FUSE);
writel(0xffffffff, vpu->ctrl_base + CTRL_G1_PP_FUSE);
writel(0xffffffff, vpu->ctrl_base + CTRL_G2_DEC_FUSE);
clk_bulk_disable_unprepare(vpu->variant->num_clocks, vpu->clocks);
return 0;
}
/*
* Supported formats.
*/
static const struct hantro_fmt imx8m_vpu_postproc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_YUYV,
.codec_mode = HANTRO_MODE_NONE,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt imx8m_vpu_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.codec_mode = HANTRO_MODE_H264_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_P010,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12_4L4,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 8,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
{
.fourcc = V4L2_PIX_FMT_NV15_4L4,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 8,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
{
.fourcc = V4L2_PIX_FMT_HEVC_SLICE,
.codec_mode = HANTRO_MODE_HEVC_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = TILE_MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = TILE_MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP9_FRAME,
.codec_mode = HANTRO_MODE_VP9_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = TILE_MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = TILE_MB_DIM,
},
},
};
static int imx8mq_vpu_hw_init(struct hantro_dev *vpu)
{
vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1];
return 0;
}
static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
imx8m_soft_reset(vpu, RESET_G1);
}
/*
* Supported codec ops.
*/
static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = {
[HANTRO_MODE_MPEG2_DEC] = {
.run = hantro_g1_mpeg2_dec_run,
.reset = imx8m_vpu_g1_reset,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.reset = imx8m_vpu_g1_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.reset = imx8m_vpu_g1_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
};
static const struct hantro_codec_ops imx8mq_vpu_g1_codec_ops[] = {
[HANTRO_MODE_MPEG2_DEC] = {
.run = hantro_g1_mpeg2_dec_run,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
};
static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = {
[HANTRO_MODE_HEVC_DEC] = {
.run = hantro_g2_hevc_dec_run,
.reset = hantro_g2_reset,
.init = hantro_hevc_dec_init,
.exit = hantro_hevc_dec_exit,
},
[HANTRO_MODE_VP9_DEC] = {
.run = hantro_g2_vp9_dec_run,
.reset = hantro_g2_reset,
.done = hantro_g2_vp9_dec_done,
.init = hantro_vp9_dec_init,
.exit = hantro_vp9_dec_exit,
},
};
/*
* VPU variants.
*/
static const struct hantro_irq imx8mq_irqs[] = {
{ "g1", hantro_g1_irq },
};
static const struct hantro_irq imx8mq_g2_irqs[] = {
{ "g2", hantro_g2_irq },
};
static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" };
static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" };
static const char * const imx8mq_g1_clk_names[] = { "g1" };
static const char * const imx8mq_g2_clk_names[] = { "g2" };
const struct hantro_variant imx8mq_vpu_variant = {
.dec_fmts = imx8m_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
.postproc_fmts = imx8m_vpu_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts),
.postproc_ops = &hantro_g1_postproc_ops,
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = imx8mq_vpu_codec_ops,
.init = imx8mq_vpu_hw_init,
.runtime_resume = imx8mq_runtime_resume,
.irqs = imx8mq_irqs,
.num_irqs = ARRAY_SIZE(imx8mq_irqs),
.clk_names = imx8mq_clk_names,
.num_clocks = ARRAY_SIZE(imx8mq_clk_names),
.reg_names = imx8mq_reg_names,
.num_regs = ARRAY_SIZE(imx8mq_reg_names)
};
static const struct of_device_id imx8mq_vpu_shared_resources[] = {
{ .compatible = "nxp,imx8mq-vpu-g1", },
{ .compatible = "nxp,imx8mq-vpu-g2", },
{ /* sentinel */ }
};
const struct hantro_variant imx8mq_vpu_g1_variant = {
.dec_fmts = imx8m_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
.postproc_fmts = imx8m_vpu_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts),
.postproc_ops = &hantro_g1_postproc_ops,
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = imx8mq_vpu_g1_codec_ops,
.irqs = imx8mq_irqs,
.num_irqs = ARRAY_SIZE(imx8mq_irqs),
.clk_names = imx8mq_g1_clk_names,
.num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
.shared_devices = imx8mq_vpu_shared_resources,
};
const struct hantro_variant imx8mq_vpu_g2_variant = {
.dec_offset = 0x0,
.dec_fmts = imx8m_vpu_g2_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts),
.postproc_fmts = imx8m_vpu_g2_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_g2_postproc_fmts),
.postproc_ops = &hantro_g2_postproc_ops,
.codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER,
.codec_ops = imx8mq_vpu_g2_codec_ops,
.irqs = imx8mq_g2_irqs,
.num_irqs = ARRAY_SIZE(imx8mq_g2_irqs),
.clk_names = imx8mq_g2_clk_names,
.num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names),
.shared_devices = imx8mq_vpu_shared_resources,
};
const struct hantro_variant imx8mm_vpu_g1_variant = {
.dec_fmts = imx8m_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = imx8mq_vpu_g1_codec_ops,
.irqs = imx8mq_irqs,
.num_irqs = ARRAY_SIZE(imx8mq_irqs),
.clk_names = imx8mq_g1_clk_names,
.num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,272 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ROCKCHIP_AV1_ENTROPYMODE_H_
#define _ROCKCHIP_AV1_ENTROPYMODE_H_
#include <linux/types.h>
struct hantro_ctx;
#define AV1_INTER_MODE_CONTEXTS 15
#define AV1_INTRA_MODES 13
#define AV1_REF_CONTEXTS 3
#define AV1_SWITCHABLE_FILTERS 3 /* number of switchable filters */
#define AV1_TX_SIZE_CONTEXTS 3
#define BLOCK_SIZE_GROUPS 4
#define BR_CDF_SIZE 4
#define BWD_REFS 3
#define CFL_ALLOWED_TYPES 2
#define CFL_ALPHA_CONTEXTS 6
#define CFL_ALPHABET_SIZE 16
#define CFL_JOINT_SIGNS 8
#define CDF_SIZE(x) ((x) - 1)
#define COMP_GROUP_IDX_CONTEXTS 7
#define COMP_INDEX_CONTEXTS 6
#define COMP_INTER_CONTEXTS 5
#define COMP_REF_TYPE_CONTEXTS 5
#define COMPOUND_TYPES 3
#define DC_SIGN_CONTEXTS 3
#define DELTA_LF_PROBS 3
#define DELTA_Q_PROBS 3
#define DIRECTIONAL_MODES 8
#define DRL_MODE_CONTEXTS 3
#define EOB_COEF_CONTEXTS 9
#define EXT_TX_SIZES 3
#define EXT_TX_TYPES 16
#define EXTTX_SIZES 4
#define FRAME_LF_COUNT 4
#define FWD_REFS 4
#define GLOBALMV_MODE_CONTEXTS 2
#define ICDF(x) (32768U - (x))
#define INTER_COMPOUND_MODES 8
#define INTERINTRA_MODES 4
#define INTRA_INTER_CONTEXTS 4
#define KF_MODE_CONTEXTS 5
#define LEVEL_CONTEXTS 21
#define MAX_ANGLE_DELTA 3
#define MAX_MB_SEGMENTS 8
#define MAX_SEGMENTS 8
#define MAX_TX_CATS 4
#define MAX_TX_DEPTH 2
#define MBSKIP_CONTEXTS 3
#define MOTION_MODES 3
#define MOTION_MODE_CONTEXTS 10
#define NEWMV_MODE_CONTEXTS 6
#define NUM_BASE_LEVELS 2
#define NUM_REF_FRAMES 8
#define PALETTE_BLOCK_SIZES 7
#define PALETTE_IDX_CONTEXTS 18
#define PALETTE_SIZES 7
#define PALETTE_UV_MODE_CONTEXTS 2
#define PALETTE_Y_MODE_CONTEXTS 3
#define PARTITION_PLOFFSET 4
#define NUM_PARTITION_CONTEXTS (4 * PARTITION_PLOFFSET)
#define PLANE_TYPES 2
#define PREDICTION_PROBS 3
#define REF_CONTEXTS 5
#define REFMV_MODE_CONTEXTS 9
#define SEG_TEMPORAL_PRED_CTXS 3
#define SIG_COEF_CONTEXTS 42
#define SIG_COEF_CONTEXTS_EOB 4
#define SINGLE_REFS 7
#define SKIP_CONTEXTS 3
#define SKIP_MODE_CONTEXTS 3
#define SPATIAL_PREDICTION_PROBS 3
#define SWITCHABLE_FILTER_CONTEXTS ((AV1_SWITCHABLE_FILTERS + 1) * 4)
#define TOKEN_CDF_Q_CTXS 4
#define TX_SIZES 5
#define TX_SIZE_CONTEXTS 2
#define TX_TYPES 4
#define TXB_SKIP_CONTEXTS 13
#define TXFM_PARTITION_CONTEXTS 22
#define UNI_COMP_REF_CONTEXTS 3
#define UNIDIR_COMP_REFS 4
#define UV_INTRA_MODES 14
#define VARTX_PART_CONTEXTS 22
#define ZEROMV_MODE_CONTEXTS 2
enum blocksizetype {
BLOCK_SIZE_AB4X4,
BLOCK_SIZE_SB4X8,
BLOCK_SIZE_SB8X4,
BLOCK_SIZE_SB8X8,
BLOCK_SIZE_SB8X16,
BLOCK_SIZE_SB16X8,
BLOCK_SIZE_MB16X16,
BLOCK_SIZE_SB16X32,
BLOCK_SIZE_SB32X16,
BLOCK_SIZE_SB32X32,
BLOCK_SIZE_SB32X64,
BLOCK_SIZE_SB64X32,
BLOCK_SIZE_SB64X64,
BLOCK_SIZE_SB64X128,
BLOCK_SIZE_SB128X64,
BLOCK_SIZE_SB128X128,
BLOCK_SIZE_SB4X16,
BLOCK_SIZE_SB16X4,
BLOCK_SIZE_SB8X32,
BLOCK_SIZE_SB32X8,
BLOCK_SIZE_SB16X64,
BLOCK_SIZE_SB64X16,
BLOCK_SIZE_TYPES,
BLOCK_SIZES_ALL = BLOCK_SIZE_TYPES
};
enum filterintramodetype {
FILTER_DC_PRED,
FILTER_V_PRED,
FILTER_H_PRED,
FILTER_D153_PRED,
FILTER_PAETH_PRED,
FILTER_INTRA_MODES,
FILTER_INTRA_UNUSED = 7
};
enum frametype {
KEY_FRAME = 0,
INTER_FRAME = 1,
NUM_FRAME_TYPES,
};
enum txsize {
TX_4X4 = 0,
TX_8X8 = 1,
TX_16X16 = 2,
TX_32X32 = 3,
TX_SIZE_MAX_SB,
};
enum { SIMPLE_TRANSLATION, OBMC_CAUSAL, MOTION_MODE_COUNT };
enum mb_prediction_mode {
DC_PRED, /* average of above and left pixels */
V_PRED, /* vertical prediction */
H_PRED, /* horizontal prediction */
D45_PRED, /* Directional 45 deg prediction [anti-clockwise from 0 deg hor] */
D135_PRED, /* Directional 135 deg prediction [anti-clockwise from 0 deg hor] */
D117_PRED, /* Directional 112 deg prediction [anti-clockwise from 0 deg hor] */
D153_PRED, /* Directional 157 deg prediction [anti-clockwise from 0 deg hor] */
D27_PRED, /* Directional 22 deg prediction [anti-clockwise from 0 deg hor] */
D63_PRED, /* Directional 67 deg prediction [anti-clockwise from 0 deg hor] */
SMOOTH_PRED,
TM_PRED_AV1 = SMOOTH_PRED,
SMOOTH_V_PRED, // Vertical interpolation
SMOOTH_H_PRED, // Horizontal interpolation
TM_PRED, /* Truemotion prediction */
PAETH_PRED = TM_PRED,
NEARESTMV,
NEARMV,
ZEROMV,
NEWMV,
NEAREST_NEARESTMV,
NEAR_NEARMV,
NEAREST_NEWMV,
NEW_NEARESTMV,
NEAR_NEWMV,
NEW_NEARMV,
ZERO_ZEROMV,
NEW_NEWMV,
SPLITMV,
MB_MODE_COUNT
};
enum partitiontype {
PARTITION_NONE,
PARTITION_HORZ,
PARTITION_VERT,
PARTITION_SPLIT,
PARTITION_TYPES
};
struct mvcdfs {
u16 joint_cdf[3];
u16 sign_cdf[2];
u16 clsss_cdf[2][10];
u16 clsss0_fp_cdf[2][2][3];
u16 fp_cdf[2][3];
u16 class0_hp_cdf[2];
u16 hp_cdf[2];
u16 class0_cdf[2];
u16 bits_cdf[2][10];
};
struct av1cdfs {
u16 partition_cdf[13][16];
u16 kf_ymode_cdf[KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][AV1_INTRA_MODES - 1];
u16 segment_pred_cdf[PREDICTION_PROBS];
u16 spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS][MAX_MB_SEGMENTS - 1];
u16 mbskip_cdf[MBSKIP_CONTEXTS];
u16 delta_q_cdf[DELTA_Q_PROBS];
u16 delta_lf_multi_cdf[FRAME_LF_COUNT][DELTA_LF_PROBS];
u16 delta_lf_cdf[DELTA_LF_PROBS];
u16 skip_mode_cdf[SKIP_MODE_CONTEXTS];
u16 vartx_part_cdf[VARTX_PART_CONTEXTS][1];
u16 tx_size_cdf[MAX_TX_CATS][AV1_TX_SIZE_CONTEXTS][MAX_TX_DEPTH];
u16 if_ymode_cdf[BLOCK_SIZE_GROUPS][AV1_INTRA_MODES - 1];
u16 uv_mode_cdf[2][AV1_INTRA_MODES][AV1_INTRA_MODES - 1 + 1];
u16 intra_inter_cdf[INTRA_INTER_CONTEXTS];
u16 comp_inter_cdf[COMP_INTER_CONTEXTS];
u16 single_ref_cdf[AV1_REF_CONTEXTS][SINGLE_REFS - 1];
u16 comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][1];
u16 uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1][1];
u16 comp_ref_cdf[AV1_REF_CONTEXTS][FWD_REFS - 1];
u16 comp_bwdref_cdf[AV1_REF_CONTEXTS][BWD_REFS - 1];
u16 newmv_cdf[NEWMV_MODE_CONTEXTS];
u16 zeromv_cdf[ZEROMV_MODE_CONTEXTS];
u16 refmv_cdf[REFMV_MODE_CONTEXTS];
u16 drl_cdf[DRL_MODE_CONTEXTS];
u16 interp_filter_cdf[SWITCHABLE_FILTER_CONTEXTS][AV1_SWITCHABLE_FILTERS - 1];
struct mvcdfs mv_cdf;
u16 obmc_cdf[BLOCK_SIZE_TYPES];
u16 motion_mode_cdf[BLOCK_SIZE_TYPES][2];
u16 inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES - 1];
u16 compound_type_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(COMPOUND_TYPES - 1)];
u16 interintra_cdf[BLOCK_SIZE_GROUPS];
u16 interintra_mode_cdf[BLOCK_SIZE_GROUPS][INTERINTRA_MODES - 1];
u16 wedge_interintra_cdf[BLOCK_SIZE_TYPES];
u16 wedge_idx_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(16)];
u16 palette_y_mode_cdf[PALETTE_BLOCK_SIZES][PALETTE_Y_MODE_CONTEXTS][1];
u16 palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][1];
u16 palette_y_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1];
u16 palette_uv_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1];
u16 cfl_sign_cdf[CFL_JOINT_SIGNS - 1];
u16 cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CFL_ALPHABET_SIZE - 1];
u16 intrabc_cdf[1];
u16 angle_delta_cdf[DIRECTIONAL_MODES][6];
u16 filter_intra_mode_cdf[FILTER_INTRA_MODES - 1];
u16 filter_intra_cdf[BLOCK_SIZES_ALL];
u16 comp_group_idx_cdf[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)];
u16 compound_idx_cdf[COMP_INDEX_CONTEXTS][CDF_SIZE(2)];
u16 dummy0[14];
// Palette index contexts; sizes 1/7, 2/6, 3/5 packed together
u16 palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8];
u16 palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8];
u16 tx_type_intra0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8];
u16 tx_type_intra1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4];
u16 tx_type_inter_cdf[2][EXTTX_SIZES][EXT_TX_TYPES];
u16 txb_skip_cdf[TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)];
u16 eob_extra_cdf[TX_SIZES][PLANE_TYPES][EOB_COEF_CONTEXTS][CDF_SIZE(2)];
u16 dummy1[5];
u16 eob_flag_cdf16[PLANE_TYPES][2][4];
u16 eob_flag_cdf32[PLANE_TYPES][2][8];
u16 eob_flag_cdf64[PLANE_TYPES][2][8];
u16 eob_flag_cdf128[PLANE_TYPES][2][8];
u16 eob_flag_cdf256[PLANE_TYPES][2][8];
u16 eob_flag_cdf512[PLANE_TYPES][2][16];
u16 eob_flag_cdf1024[PLANE_TYPES][2][16];
u16 coeff_base_eob_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(3)];
u16 coeff_base_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS][CDF_SIZE(4) + 1];
u16 dc_sign_cdf[PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)];
u16 dummy2[2];
u16 coeff_br_cdf[TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1];
u16 dummy3[16];
};
void rockchip_av1_store_cdfs(struct hantro_ctx *ctx,
u32 refresh_frame_flags);
void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx);
void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs,
struct mvcdfs *cdfs_ndvc);
void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr);
#endif /* _ROCKCHIP_AV1_ENTROPYMODE_H_ */
@@ -0,0 +1,401 @@
// SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0
#include "rockchip_av1_filmgrain.h"
static const s32 gaussian_sequence[2048] = {
56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820,
224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800,
112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588,
-584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368,
432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4,
192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396,
540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740,
248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292,
248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532,
340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704,
220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96,
-792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244,
60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136,
488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676,
-376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400,
-456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844,
-164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96,
-1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356,
728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280,
4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808,
772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228,
-1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136,
-88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264,
-528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388,
1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500,
204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384,
548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220,
-100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148,
96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572,
-332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516,
240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916,
-1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492,
896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560,
-1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108,
-28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516,
-672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88,
-152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196,
-524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864,
424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920,
436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564,
-68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876,
-1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244,
496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184,
56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364,
-528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72,
540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24,
424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4,
-88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120,
756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108,
-260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296,
60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336,
-28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164,
-1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264,
308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536,
-784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296,
-1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696,
284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204,
264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212,
-212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40,
908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384,
124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8,
1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704,
-224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348,
-280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592,
-196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420,
320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220,
-644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208,
-116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544,
-388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288,
-16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240,
-196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132,
636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16,
-220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044,
-32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732,
392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460,
-816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52,
-140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104,
-284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460,
756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716,
-604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960,
472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476,
844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692,
60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352,
-1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144,
-8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44,
472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356,
652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452,
-436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552,
-692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264,
-668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448,
-832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588,
220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464,
412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216,
320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132,
372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412,
924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48,
332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196,
436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48,
-456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292,
1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32,
-44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012,
-48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120,
-116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56,
528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416,
-600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404,
-316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92,
1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904,
20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728,
96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584,
192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48,
648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180,
816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528,
648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364,
-376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260,
-492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324,
-1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64,
384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120,
-480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168,
-68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888,
64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588,
-184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484,
128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580,
112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392,
828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80,
-556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688,
0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4,
-364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300,
24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444,
508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192,
716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160,
600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188,
-816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404,
-696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400,
344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92,
-136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824,
164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620,
192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720,
288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620,
-684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508,
-1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736,
556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836,
268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180,
884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140,
-724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32,
-228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916,
244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368,
-56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380,
-796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572,
-624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864,
1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908,
-84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84,
344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396,
-1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360,
1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928,
-120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288,
504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196,
76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504,
116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272,
28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344,
-4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208,
-512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156,
-212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240,
-448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432,
252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244,
312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584,
732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24,
124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300,
-212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416,
440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380,
-820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384,
648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88,
680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876,
-664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320,
-672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88,
-496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196,
-176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120,
372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664,
-232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0,
-412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264,
-136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288,
-276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56,
52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148,
716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156,
-300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144,
-676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148,
104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944,
428, -484
};
static inline s32 clamp(s32 value, s32 low, s32 high)
{
return value < low ? low : (value > high ? high : value);
}
static inline s32 round_power_of_two(const s32 val, s32 n)
{
const s32 a = (s32)1 << (n - 1);
return (val + a) >> n;
}
static void rockchip_av1_init_random_generator(u8 luma_num, u16 seed,
u16 *random_register)
{
u16 random_reg = seed;
random_reg ^= ((luma_num * 37 + 178) & 255) << 8;
random_reg ^= ((luma_num * 173 + 105) & 255);
*random_register = random_reg;
}
static inline void rockchip_av1_update_random_register(u16 *random_register)
{
u16 bit;
u16 random_reg = *random_register;
bit = ((random_reg >> 0) ^ (random_reg >> 1) ^ (random_reg >> 3) ^
(random_reg >> 12)) & 1;
*random_register = (random_reg >> 1) | (bit << 15);
}
static inline s32 rockchip_av1_get_random_number(u16 random_register)
{
return (random_register >> 5) & ((1 << 11) - 1);
}
void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82],
s32 bitdepth,
u8 num_y_points,
s32 grain_scale_shift,
s32 ar_coeff_lag,
s32 (*ar_coeffs_y)[24],
s32 ar_coeff_shift,
s32 grain_min,
s32 grain_max,
u16 random_seed)
{
s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift;
u16 grain_random_register = random_seed;
s32 i, j;
for (i = 0; i < 73; i++) {
for (j = 0; j < 82; j++) {
if (num_y_points > 0) {
rockchip_av1_update_random_register
(&grain_random_register);
(*luma_grain_block)[i][j] =
round_power_of_two(gaussian_sequence
[rockchip_av1_get_random_number
(grain_random_register)],
gauss_sec_shift);
} else {
(*luma_grain_block)[i][j] = 0;
}
}
}
for (i = 3; i < 73; i++)
for (j = 3; j < 82 - 3; j++) {
s32 pos = 0;
s32 wsum = 0;
s32 deltarow, deltacol;
for (deltarow = -ar_coeff_lag; deltarow <= 0;
deltarow++) {
for (deltacol = -ar_coeff_lag;
deltacol <= ar_coeff_lag; deltacol++) {
if (deltarow == 0 && deltacol == 0)
break;
wsum = wsum + (*ar_coeffs_y)[pos] *
(*luma_grain_block)[i + deltarow][j + deltacol];
++pos;
}
}
(*luma_grain_block)[i][j] =
clamp((*luma_grain_block)[i][j] +
round_power_of_two(wsum, ar_coeff_shift),
grain_min, grain_max);
}
}
// Calculate chroma grain noise once per frame
void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82],
s32 (*cb_grain_block)[38][44],
s32 (*cr_grain_block)[38][44],
s32 bitdepth,
u8 num_y_points,
u8 num_cb_points,
u8 num_cr_points,
s32 grain_scale_shift,
s32 ar_coeff_lag,
s32 (*ar_coeffs_cb)[25],
s32 (*ar_coeffs_cr)[25],
s32 ar_coeff_shift,
s32 grain_min,
s32 grain_max,
u8 chroma_scaling_from_luma,
u16 random_seed)
{
s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift;
u16 grain_random_register = 0;
s32 i, j;
rockchip_av1_init_random_generator(7, random_seed,
&grain_random_register);
for (i = 0; i < 38; i++) {
for (j = 0; j < 44; j++) {
if (num_cb_points || chroma_scaling_from_luma) {
rockchip_av1_update_random_register
(&grain_random_register);
(*cb_grain_block)[i][j] =
round_power_of_two(gaussian_sequence
[rockchip_av1_get_random_number
(grain_random_register)],
gauss_sec_shift);
} else {
(*cb_grain_block)[i][j] = 0;
}
}
}
rockchip_av1_init_random_generator(11, random_seed,
&grain_random_register);
for (i = 0; i < 38; i++) {
for (j = 0; j < 44; j++) {
if (num_cr_points || chroma_scaling_from_luma) {
rockchip_av1_update_random_register
(&grain_random_register);
(*cr_grain_block)[i][j] =
round_power_of_two(gaussian_sequence
[rockchip_av1_get_random_number
(grain_random_register)],
gauss_sec_shift);
} else {
(*cr_grain_block)[i][j] = 0;
}
}
}
for (i = 3; i < 38; i++) {
for (j = 3; j < 44 - 3; j++) {
s32 wsum_cb = 0;
s32 wsum_cr = 0;
s32 pos = 0;
s32 deltarow, deltacol;
for (deltarow = -ar_coeff_lag; deltarow <= 0;
deltarow++) {
for (deltacol = -ar_coeff_lag;
deltacol <= ar_coeff_lag; deltacol++) {
if (deltarow == 0 && deltacol == 0)
break;
wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] *
(*cb_grain_block)[i + deltarow][j + deltacol];
wsum_cr =
wsum_cr +
(*ar_coeffs_cr)[pos] *
(*cr_grain_block)[i + deltarow][j + deltacol];
++pos;
}
}
if (num_y_points > 0) {
s32 av_luma = 0;
s32 luma_coord_y = (i << 1) - 3;
s32 luma_coord_x = (j << 1) - 3;
av_luma +=
(*luma_grain_block)[luma_coord_y][luma_coord_x];
av_luma +=
(*luma_grain_block)[luma_coord_y][luma_coord_x + 1];
av_luma +=
(*luma_grain_block)[luma_coord_y + 1][luma_coord_x];
av_luma +=
(*luma_grain_block)[(luma_coord_y + 1)][luma_coord_x + 1];
av_luma = round_power_of_two(av_luma, 2);
wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] * av_luma;
wsum_cr = wsum_cr + (*ar_coeffs_cr)[pos] * av_luma;
}
if (num_cb_points || chroma_scaling_from_luma) {
(*cb_grain_block)[i][j] =
clamp((*cb_grain_block)[i][j] +
round_power_of_two(wsum_cb, ar_coeff_shift),
grain_min, grain_max);
}
if (num_cr_points || chroma_scaling_from_luma) {
(*cr_grain_block)[i][j] =
clamp((*cr_grain_block)[i][j] +
round_power_of_two(wsum_cr, ar_coeff_shift),
grain_min, grain_max);
}
}
}
}
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ROCKCHIP_AV1_FILMGRAIN_H_
#define _ROCKCHIP_AV1_FILMGRAIN_H_
#include <linux/types.h>
void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82],
s32 bitdepth,
u8 num_y_points,
s32 grain_scale_shift,
s32 ar_coeff_lag,
s32 (*ar_coeffs_y)[24],
s32 ar_coeff_shift,
s32 grain_min,
s32 grain_max,
u16 random_seed);
void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82],
s32 (*cb_grain_block)[38][44],
s32 (*cr_grain_block)[38][44],
s32 bitdepth,
u8 num_y_points,
u8 num_cb_points,
u8 num_cr_points,
s32 grain_scale_shift,
s32 ar_coeff_lag,
s32 (*ar_coeffs_cb)[25],
s32 (*ar_coeffs_cr)[25],
s32 ar_coeff_shift,
s32 grain_min,
s32 grain_max,
u8 chroma_scaling_from_luma,
u16 random_seed);
#endif
@@ -0,0 +1,491 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (c) 2014 Rockchip Electronics Co., Ltd.
* Hertz Wong <hertz.wong@rock-chips.com>
* Herman Chen <herman.chen@rock-chips.com>
*
* Copyright (C) 2014 Google, Inc.
* Tomasz Figa <tfiga@chromium.org>
*/
#include <linux/types.h>
#include <linux/sort.h>
#include <media/v4l2-mem2mem.h>
#include "hantro_hw.h"
#include "hantro_v4l2.h"
#define VDPU_SWREG(nr) ((nr) * 4)
#define VDPU_REG_DEC_OUT_BASE VDPU_SWREG(63)
#define VDPU_REG_RLC_VLC_BASE VDPU_SWREG(64)
#define VDPU_REG_QTABLE_BASE VDPU_SWREG(61)
#define VDPU_REG_DIR_MV_BASE VDPU_SWREG(62)
#define VDPU_REG_REFER_BASE(i) (VDPU_SWREG(84 + (i)))
#define VDPU_REG_DEC_E(v) ((v) ? BIT(0) : 0)
#define VDPU_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(11) : 0)
#define VDPU_REG_DEC_SCMD_DIS(v) ((v) ? BIT(10) : 0)
#define VDPU_REG_FILTERING_DIS(v) ((v) ? BIT(8) : 0)
#define VDPU_REG_PIC_FIXED_QUANT(v) ((v) ? BIT(7) : 0)
#define VDPU_REG_DEC_LATENCY(v) (((v) << 1) & GENMASK(6, 1))
#define VDPU_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25))
#define VDPU_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0))
#define VDPU_REG_APF_THRESHOLD(v) (((v) << 17) & GENMASK(30, 17))
#define VDPU_REG_STARTMB_X(v) (((v) << 8) & GENMASK(16, 8))
#define VDPU_REG_STARTMB_Y(v) (((v) << 0) & GENMASK(7, 0))
#define VDPU_REG_DEC_MODE(v) (((v) << 0) & GENMASK(3, 0))
#define VDPU_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(5) : 0)
#define VDPU_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(4) : 0)
#define VDPU_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(3) : 0)
#define VDPU_REG_DEC_INSWAP32_E(v) ((v) ? BIT(2) : 0)
#define VDPU_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(1) : 0)
#define VDPU_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(0) : 0)
#define VDPU_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(22) : 0)
#define VDPU_REG_DEC_MAX_BURST(v) (((v) << 16) & GENMASK(20, 16))
#define VDPU_REG_DEC_AXI_WR_ID(v) (((v) << 8) & GENMASK(15, 8))
#define VDPU_REG_DEC_AXI_RD_ID(v) (((v) << 0) & GENMASK(7, 0))
#define VDPU_REG_START_CODE_E(v) ((v) ? BIT(22) : 0)
#define VDPU_REG_CH_8PIX_ILEAV_E(v) ((v) ? BIT(21) : 0)
#define VDPU_REG_RLC_MODE_E(v) ((v) ? BIT(20) : 0)
#define VDPU_REG_PIC_INTERLACE_E(v) ((v) ? BIT(17) : 0)
#define VDPU_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(16) : 0)
#define VDPU_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(13) : 0)
#define VDPU_REG_WRITE_MVS_E(v) ((v) ? BIT(10) : 0)
#define VDPU_REG_SEQ_MBAFF_E(v) ((v) ? BIT(7) : 0)
#define VDPU_REG_PICORD_COUNT_E(v) ((v) ? BIT(6) : 0)
#define VDPU_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(5) : 0)
#define VDPU_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(4) : 0)
#define VDPU_REG_PRED_BC_TAP_0_0(v) (((v) << 22) & GENMASK(31, 22))
#define VDPU_REG_PRED_BC_TAP_0_1(v) (((v) << 12) & GENMASK(21, 12))
#define VDPU_REG_PRED_BC_TAP_0_2(v) (((v) << 2) & GENMASK(11, 2))
#define VDPU_REG_REFBU_E(v) ((v) ? BIT(31) : 0)
#define VDPU_REG_PINIT_RLIST_F9(v) (((v) << 25) & GENMASK(29, 25))
#define VDPU_REG_PINIT_RLIST_F8(v) (((v) << 20) & GENMASK(24, 20))
#define VDPU_REG_PINIT_RLIST_F7(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_PINIT_RLIST_F6(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_PINIT_RLIST_F5(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_PINIT_RLIST_F4(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_PINIT_RLIST_F15(v) (((v) << 25) & GENMASK(29, 25))
#define VDPU_REG_PINIT_RLIST_F14(v) (((v) << 20) & GENMASK(24, 20))
#define VDPU_REG_PINIT_RLIST_F13(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_PINIT_RLIST_F12(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_PINIT_RLIST_F11(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_PINIT_RLIST_F10(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_REFER1_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER0_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER3_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER2_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER5_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER4_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER7_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER6_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER9_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER8_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER11_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER10_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER13_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER12_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFER15_NBR(v) (((v) << 16) & GENMASK(31, 16))
#define VDPU_REG_REFER14_NBR(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_BINIT_RLIST_F5(v) (((v) << 25) & GENMASK(29, 25))
#define VDPU_REG_BINIT_RLIST_F4(v) (((v) << 20) & GENMASK(24, 20))
#define VDPU_REG_BINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_BINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_BINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_BINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_BINIT_RLIST_F11(v) (((v) << 25) & GENMASK(29, 25))
#define VDPU_REG_BINIT_RLIST_F10(v) (((v) << 20) & GENMASK(24, 20))
#define VDPU_REG_BINIT_RLIST_F9(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_BINIT_RLIST_F8(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_BINIT_RLIST_F7(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_BINIT_RLIST_F6(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_BINIT_RLIST_F15(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_BINIT_RLIST_F14(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_BINIT_RLIST_F13(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_BINIT_RLIST_F12(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_BINIT_RLIST_B5(v) (((v) << 25) & GENMASK(29, 25))
#define VDPU_REG_BINIT_RLIST_B4(v) (((v) << 20) & GENMASK(24, 20))
#define VDPU_REG_BINIT_RLIST_B3(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_BINIT_RLIST_B2(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_BINIT_RLIST_B1(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_BINIT_RLIST_B0(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_BINIT_RLIST_B11(v) (((v) << 25) & GENMASK(29, 25))
#define VDPU_REG_BINIT_RLIST_B10(v) (((v) << 20) & GENMASK(24, 20))
#define VDPU_REG_BINIT_RLIST_B9(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_BINIT_RLIST_B8(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_BINIT_RLIST_B7(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_BINIT_RLIST_B6(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_BINIT_RLIST_B15(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_BINIT_RLIST_B14(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_BINIT_RLIST_B13(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_BINIT_RLIST_B12(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_PINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15))
#define VDPU_REG_PINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10))
#define VDPU_REG_PINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5))
#define VDPU_REG_PINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_REFER_LTERM_E(v) (((v) << 0) & GENMASK(31, 0))
#define VDPU_REG_REFER_VALID_E(v) (((v) << 0) & GENMASK(31, 0))
#define VDPU_REG_STRM_START_BIT(v) (((v) << 0) & GENMASK(5, 0))
#define VDPU_REG_CH_QP_OFFSET2(v) (((v) << 22) & GENMASK(26, 22))
#define VDPU_REG_CH_QP_OFFSET(v) (((v) << 17) & GENMASK(21, 17))
#define VDPU_REG_PIC_MB_HEIGHT_P(v) (((v) << 9) & GENMASK(16, 9))
#define VDPU_REG_PIC_MB_WIDTH(v) (((v) << 0) & GENMASK(8, 0))
#define VDPU_REG_WEIGHT_BIPR_IDC(v) (((v) << 16) & GENMASK(17, 16))
#define VDPU_REG_REF_FRAMES(v) (((v) << 0) & GENMASK(4, 0))
#define VDPU_REG_FILT_CTRL_PRES(v) ((v) ? BIT(31) : 0)
#define VDPU_REG_RDPIC_CNT_PRES(v) ((v) ? BIT(30) : 0)
#define VDPU_REG_FRAMENUM_LEN(v) (((v) << 16) & GENMASK(20, 16))
#define VDPU_REG_FRAMENUM(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_REFPIC_MK_LEN(v) (((v) << 16) & GENMASK(26, 16))
#define VDPU_REG_IDR_PIC_ID(v) (((v) << 0) & GENMASK(15, 0))
#define VDPU_REG_PPS_ID(v) (((v) << 24) & GENMASK(31, 24))
#define VDPU_REG_REFIDX1_ACTIVE(v) (((v) << 19) & GENMASK(23, 19))
#define VDPU_REG_REFIDX0_ACTIVE(v) (((v) << 14) & GENMASK(18, 14))
#define VDPU_REG_POC_LENGTH(v) (((v) << 0) & GENMASK(7, 0))
#define VDPU_REG_IDR_PIC_E(v) ((v) ? BIT(8) : 0)
#define VDPU_REG_DIR_8X8_INFER_E(v) ((v) ? BIT(7) : 0)
#define VDPU_REG_BLACKWHITE_E(v) ((v) ? BIT(6) : 0)
#define VDPU_REG_CABAC_E(v) ((v) ? BIT(5) : 0)
#define VDPU_REG_WEIGHT_PRED_E(v) ((v) ? BIT(4) : 0)
#define VDPU_REG_CONST_INTRA_E(v) ((v) ? BIT(3) : 0)
#define VDPU_REG_8X8TRANS_FLAG_E(v) ((v) ? BIT(2) : 0)
#define VDPU_REG_TYPE1_QUANT_E(v) ((v) ? BIT(1) : 0)
#define VDPU_REG_FIELDPIC_FLAG_E(v) ((v) ? BIT(0) : 0)
static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
struct hantro_dev *vpu = ctx->dev;
u32 reg;
reg = VDPU_REG_DEC_ADV_PRE_DIS(0) |
VDPU_REG_DEC_SCMD_DIS(0) |
VDPU_REG_FILTERING_DIS(0) |
VDPU_REG_PIC_FIXED_QUANT(0) |
VDPU_REG_DEC_LATENCY(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(50));
reg = VDPU_REG_INIT_QP(pps->pic_init_qp_minus26 + 26) |
VDPU_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(51));
reg = VDPU_REG_APF_THRESHOLD(8) |
VDPU_REG_STARTMB_X(0) |
VDPU_REG_STARTMB_Y(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(52));
reg = VDPU_REG_DEC_MODE(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(53));
reg = VDPU_REG_DEC_STRENDIAN_E(1) |
VDPU_REG_DEC_STRSWAP32_E(1) |
VDPU_REG_DEC_OUTSWAP32_E(1) |
VDPU_REG_DEC_INSWAP32_E(1) |
VDPU_REG_DEC_OUT_ENDIAN(1) |
VDPU_REG_DEC_IN_ENDIAN(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(54));
reg = VDPU_REG_DEC_DATA_DISC_E(0) |
VDPU_REG_DEC_MAX_BURST(16) |
VDPU_REG_DEC_AXI_WR_ID(0) |
VDPU_REG_DEC_AXI_RD_ID(0xff);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(56));
reg = VDPU_REG_START_CODE_E(1) |
VDPU_REG_CH_8PIX_ILEAV_E(0) |
VDPU_REG_RLC_MODE_E(0) |
VDPU_REG_PIC_INTERLACE_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD ||
dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) |
VDPU_REG_PIC_FIELDMODE_E(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) |
VDPU_REG_PIC_TOPFIELD_E(!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)) |
VDPU_REG_WRITE_MVS_E((sps->profile_idc > 66) && dec_param->nal_ref_idc) |
VDPU_REG_SEQ_MBAFF_E(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) |
VDPU_REG_PICORD_COUNT_E(sps->profile_idc > 66) |
VDPU_REG_DEC_TIMEOUT_E(1) |
VDPU_REG_DEC_CLK_GATE_E(1);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(57));
reg = VDPU_REG_PRED_BC_TAP_0_0(1) |
VDPU_REG_PRED_BC_TAP_0_1((u32)-5) |
VDPU_REG_PRED_BC_TAP_0_2(20);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(59));
reg = VDPU_REG_REFBU_E(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(65));
reg = VDPU_REG_STRM_START_BIT(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(109));
reg = VDPU_REG_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset) |
VDPU_REG_CH_QP_OFFSET(pps->chroma_qp_index_offset) |
VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) |
VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(110));
reg = VDPU_REG_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc) |
VDPU_REG_REF_FRAMES(sps->max_num_ref_frames);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(111));
reg = VDPU_REG_FILT_CTRL_PRES(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) |
VDPU_REG_RDPIC_CNT_PRES(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT) |
VDPU_REG_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) |
VDPU_REG_FRAMENUM(dec_param->frame_num);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(112));
reg = VDPU_REG_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) |
VDPU_REG_IDR_PIC_ID(dec_param->idr_pic_id);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(113));
reg = VDPU_REG_PPS_ID(pps->pic_parameter_set_id) |
VDPU_REG_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) |
VDPU_REG_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) |
VDPU_REG_POC_LENGTH(dec_param->pic_order_cnt_bit_size);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(114));
reg = VDPU_REG_IDR_PIC_E(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) |
VDPU_REG_DIR_8X8_INFER_E(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) |
VDPU_REG_BLACKWHITE_E(sps->profile_idc >= 100 && sps->chroma_format_idc == 0) |
VDPU_REG_CABAC_E(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) |
VDPU_REG_WEIGHT_PRED_E(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) |
VDPU_REG_CONST_INTRA_E(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) |
VDPU_REG_8X8TRANS_FLAG_E(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE) |
VDPU_REG_TYPE1_QUANT_E(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) |
VDPU_REG_FIELDPIC_FLAG_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(115));
}
static void set_ref(struct hantro_ctx *ctx)
{
const struct v4l2_h264_reference *b0_reflist, *b1_reflist, *p_reflist;
struct hantro_dev *vpu = ctx->dev;
u32 reg;
int i;
b0_reflist = ctx->h264_dec.reflists.b0;
b1_reflist = ctx->h264_dec.reflists.b1;
p_reflist = ctx->h264_dec.reflists.p;
reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9].index) |
VDPU_REG_PINIT_RLIST_F8(p_reflist[8].index) |
VDPU_REG_PINIT_RLIST_F7(p_reflist[7].index) |
VDPU_REG_PINIT_RLIST_F6(p_reflist[6].index) |
VDPU_REG_PINIT_RLIST_F5(p_reflist[5].index) |
VDPU_REG_PINIT_RLIST_F4(p_reflist[4].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(74));
reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15].index) |
VDPU_REG_PINIT_RLIST_F14(p_reflist[14].index) |
VDPU_REG_PINIT_RLIST_F13(p_reflist[13].index) |
VDPU_REG_PINIT_RLIST_F12(p_reflist[12].index) |
VDPU_REG_PINIT_RLIST_F11(p_reflist[11].index) |
VDPU_REG_PINIT_RLIST_F10(p_reflist[10].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(75));
reg = VDPU_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) |
VDPU_REG_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, 0));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(76));
reg = VDPU_REG_REFER3_NBR(hantro_h264_get_ref_nbr(ctx, 3)) |
VDPU_REG_REFER2_NBR(hantro_h264_get_ref_nbr(ctx, 2));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(77));
reg = VDPU_REG_REFER5_NBR(hantro_h264_get_ref_nbr(ctx, 5)) |
VDPU_REG_REFER4_NBR(hantro_h264_get_ref_nbr(ctx, 4));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(78));
reg = VDPU_REG_REFER7_NBR(hantro_h264_get_ref_nbr(ctx, 7)) |
VDPU_REG_REFER6_NBR(hantro_h264_get_ref_nbr(ctx, 6));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(79));
reg = VDPU_REG_REFER9_NBR(hantro_h264_get_ref_nbr(ctx, 9)) |
VDPU_REG_REFER8_NBR(hantro_h264_get_ref_nbr(ctx, 8));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(80));
reg = VDPU_REG_REFER11_NBR(hantro_h264_get_ref_nbr(ctx, 11)) |
VDPU_REG_REFER10_NBR(hantro_h264_get_ref_nbr(ctx, 10));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(81));
reg = VDPU_REG_REFER13_NBR(hantro_h264_get_ref_nbr(ctx, 13)) |
VDPU_REG_REFER12_NBR(hantro_h264_get_ref_nbr(ctx, 12));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(82));
reg = VDPU_REG_REFER15_NBR(hantro_h264_get_ref_nbr(ctx, 15)) |
VDPU_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(83));
reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5].index) |
VDPU_REG_BINIT_RLIST_F4(b0_reflist[4].index) |
VDPU_REG_BINIT_RLIST_F3(b0_reflist[3].index) |
VDPU_REG_BINIT_RLIST_F2(b0_reflist[2].index) |
VDPU_REG_BINIT_RLIST_F1(b0_reflist[1].index) |
VDPU_REG_BINIT_RLIST_F0(b0_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(100));
reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11].index) |
VDPU_REG_BINIT_RLIST_F10(b0_reflist[10].index) |
VDPU_REG_BINIT_RLIST_F9(b0_reflist[9].index) |
VDPU_REG_BINIT_RLIST_F8(b0_reflist[8].index) |
VDPU_REG_BINIT_RLIST_F7(b0_reflist[7].index) |
VDPU_REG_BINIT_RLIST_F6(b0_reflist[6].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(101));
reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15].index) |
VDPU_REG_BINIT_RLIST_F14(b0_reflist[14].index) |
VDPU_REG_BINIT_RLIST_F13(b0_reflist[13].index) |
VDPU_REG_BINIT_RLIST_F12(b0_reflist[12].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(102));
reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5].index) |
VDPU_REG_BINIT_RLIST_B4(b1_reflist[4].index) |
VDPU_REG_BINIT_RLIST_B3(b1_reflist[3].index) |
VDPU_REG_BINIT_RLIST_B2(b1_reflist[2].index) |
VDPU_REG_BINIT_RLIST_B1(b1_reflist[1].index) |
VDPU_REG_BINIT_RLIST_B0(b1_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(103));
reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11].index) |
VDPU_REG_BINIT_RLIST_B10(b1_reflist[10].index) |
VDPU_REG_BINIT_RLIST_B9(b1_reflist[9].index) |
VDPU_REG_BINIT_RLIST_B8(b1_reflist[8].index) |
VDPU_REG_BINIT_RLIST_B7(b1_reflist[7].index) |
VDPU_REG_BINIT_RLIST_B6(b1_reflist[6].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(104));
reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15].index) |
VDPU_REG_BINIT_RLIST_B14(b1_reflist[14].index) |
VDPU_REG_BINIT_RLIST_B13(b1_reflist[13].index) |
VDPU_REG_BINIT_RLIST_B12(b1_reflist[12].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(105));
reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3].index) |
VDPU_REG_PINIT_RLIST_F2(p_reflist[2].index) |
VDPU_REG_PINIT_RLIST_F1(p_reflist[1].index) |
VDPU_REG_PINIT_RLIST_F0(p_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(106));
reg = VDPU_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(107));
reg = VDPU_REG_REFER_VALID_E(ctx->h264_dec.dpb_valid);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(108));
/* Set up addresses of DPB buffers. */
for (i = 0; i < HANTRO_H264_DPB_SIZE; i++) {
dma_addr_t dma_addr = hantro_h264_get_ref_buf(ctx, i);
vdpu_write_relaxed(vpu, dma_addr, VDPU_REG_REFER_BASE(i));
}
}
static void set_buffers(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
struct vb2_v4l2_buffer *dst_buf;
struct hantro_dev *vpu = ctx->dev;
dma_addr_t src_dma, dst_dma;
size_t offset = 0;
/* Source (stream) buffer. */
src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
vdpu_write_relaxed(vpu, src_dma, VDPU_REG_RLC_VLC_BASE);
/* Destination (decoded frame) buffer. */
dst_buf = hantro_get_dst_buf(ctx);
dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
/* Adjust dma addr to start at second line for bottom field */
if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
offset = ALIGN(ctx->src_fmt.width, MB_DIM);
vdpu_write_relaxed(vpu, dst_dma + offset, VDPU_REG_DEC_OUT_BASE);
/* Higher profiles require DMV buffer appended to reference frames. */
if (ctrls->sps->profile_idc > 66 && ctrls->decode->nal_ref_idc) {
unsigned int bytes_per_mb = 384;
/* DMV buffer for monochrome start directly after Y-plane */
if (ctrls->sps->profile_idc >= 100 &&
ctrls->sps->chroma_format_idc == 0)
bytes_per_mb = 256;
offset = bytes_per_mb * MB_WIDTH(ctx->src_fmt.width) *
MB_HEIGHT(ctx->src_fmt.height);
/*
* DMV buffer is split in two for field encoded frames,
* adjust offset for bottom field
*/
if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
offset += 32 * MB_WIDTH(ctx->src_fmt.width) *
MB_HEIGHT(ctx->src_fmt.height);
vdpu_write_relaxed(vpu, dst_dma + offset, VDPU_REG_DIR_MV_BASE);
}
/* Auxiliary buffer prepared in hantro_h264_dec_init(). */
vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, VDPU_REG_QTABLE_BASE);
}
int rockchip_vpu2_h264_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf;
u32 reg;
int ret;
/* Prepare the H264 decoder context. */
ret = hantro_h264_dec_prepare_run(ctx);
if (ret)
return ret;
src_buf = hantro_get_src_buf(ctx);
set_params(ctx, src_buf);
set_ref(ctx);
set_buffers(ctx, src_buf);
hantro_end_prepare_run(ctx);
/* Start decoding! */
reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1);
vdpu_write(vpu, reg, VDPU_SWREG(57));
return 0;
}
@@ -0,0 +1,197 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*
* JPEG encoder
* ------------
* The VPU JPEG encoder produces JPEG baseline sequential format.
* The quantization coefficients are 8-bit values, complying with
* the baseline specification. Therefore, it requires
* luma and chroma quantization tables. The hardware does entropy
* encoding using internal Huffman tables, as specified in the JPEG
* specification.
*
* In other words, only the luma and chroma quantization tables are
* required for the encoding operation.
*
* Quantization luma table values are written to registers
* VEPU_swreg_0-VEPU_swreg_15, and chroma table values to
* VEPU_swreg_16-VEPU_swreg_31. A special order is needed, neither
* zigzag, nor linear.
*/
#include <linux/unaligned.h>
#include <media/v4l2-mem2mem.h>
#include "hantro_jpeg.h"
#include "hantro.h"
#include "hantro_v4l2.h"
#include "hantro_hw.h"
#include "rockchip_vpu2_regs.h"
#define VEPU_JPEG_QUANT_TABLE_COUNT 16
static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
u32 overfill_r, overfill_b;
u32 reg;
/*
* The format width and height are already macroblock aligned
* by .vidioc_s_fmt_vid_cap_mplane() callback. Destination
* format width and height can be further modified by
* .vidioc_s_selection(), and the width is 4-aligned.
*/
overfill_r = ctx->src_fmt.width - ctx->dst_fmt.width;
overfill_b = ctx->src_fmt.height - ctx->dst_fmt.height;
reg = VEPU_REG_IN_IMG_CTRL_ROW_LEN(ctx->src_fmt.width);
vepu_write_relaxed(vpu, reg, VEPU_REG_INPUT_LUMA_INFO);
reg = VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r / 4) |
VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b);
/*
* This register controls the input crop, as the offset
* from the right/bottom within the last macroblock. The offset from the
* right must be divided by 4 and so the crop must be aligned to 4 pixels
* horizontally.
*/
vepu_write_relaxed(vpu, reg, VEPU_REG_ENC_OVER_FILL_STRM_OFFSET);
reg = VEPU_REG_IN_IMG_CTRL_FMT(ctx->vpu_src_fmt->enc_fmt);
vepu_write_relaxed(vpu, reg, VEPU_REG_ENC_CTRL1);
}
static void rockchip_vpu2_jpeg_enc_set_buffers(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
struct vb2_buffer *src_buf,
struct vb2_buffer *dst_buf)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
dma_addr_t src[3];
u32 size_left;
size_left = vb2_plane_size(dst_buf, 0) - ctx->vpu_dst_fmt->header_size;
if (WARN_ON(vb2_plane_size(dst_buf, 0) < ctx->vpu_dst_fmt->header_size))
size_left = 0;
WARN_ON(pix_fmt->num_planes > 3);
vepu_write_relaxed(vpu, vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
ctx->vpu_dst_fmt->header_size,
VEPU_REG_ADDR_OUTPUT_STREAM);
vepu_write_relaxed(vpu, size_left, VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
vepu_write_relaxed(vpu, src[0], VEPU_REG_ADDR_IN_PLANE_0);
} else if (pix_fmt->num_planes == 2) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
src[1] = vb2_dma_contig_plane_dma_addr(src_buf, 1);
vepu_write_relaxed(vpu, src[0], VEPU_REG_ADDR_IN_PLANE_0);
vepu_write_relaxed(vpu, src[1], VEPU_REG_ADDR_IN_PLANE_1);
} else {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
src[1] = vb2_dma_contig_plane_dma_addr(src_buf, 1);
src[2] = vb2_dma_contig_plane_dma_addr(src_buf, 2);
vepu_write_relaxed(vpu, src[0], VEPU_REG_ADDR_IN_PLANE_0);
vepu_write_relaxed(vpu, src[1], VEPU_REG_ADDR_IN_PLANE_1);
vepu_write_relaxed(vpu, src[2], VEPU_REG_ADDR_IN_PLANE_2);
}
}
static void
rockchip_vpu2_jpeg_enc_set_qtable(struct hantro_dev *vpu,
unsigned char *luma_qtable,
unsigned char *chroma_qtable)
{
u32 reg, i;
__be32 *luma_qtable_p;
__be32 *chroma_qtable_p;
luma_qtable_p = (__be32 *)luma_qtable;
chroma_qtable_p = (__be32 *)chroma_qtable;
/*
* Quantization table registers must be written in contiguous blocks.
* DO NOT collapse the below two "for" loops into one.
*/
for (i = 0; i < VEPU_JPEG_QUANT_TABLE_COUNT; i++) {
reg = get_unaligned_be32(&luma_qtable_p[i]);
vepu_write_relaxed(vpu, reg, VEPU_REG_JPEG_LUMA_QUAT(i));
}
for (i = 0; i < VEPU_JPEG_QUANT_TABLE_COUNT; i++) {
reg = get_unaligned_be32(&chroma_qtable_p[i]);
vepu_write_relaxed(vpu, reg, VEPU_REG_JPEG_CHROMA_QUAT(i));
}
}
int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
struct hantro_jpeg_ctx jpeg_ctx;
u32 reg;
src_buf = hantro_get_src_buf(ctx);
dst_buf = hantro_get_dst_buf(ctx);
hantro_start_prepare_run(ctx);
memset(&jpeg_ctx, 0, sizeof(jpeg_ctx));
jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
if (!jpeg_ctx.buffer)
return -ENOMEM;
jpeg_ctx.width = ctx->dst_fmt.width;
jpeg_ctx.height = ctx->dst_fmt.height;
jpeg_ctx.quality = ctx->jpeg_quality;
hantro_jpeg_header_assemble(&jpeg_ctx);
/* Switch to JPEG encoder mode before writing registers */
vepu_write_relaxed(vpu, VEPU_REG_ENCODE_FORMAT_JPEG,
VEPU_REG_ENCODE_START);
rockchip_vpu2_set_src_img_ctrl(vpu, ctx);
rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf,
&dst_buf->vb2_buf);
rockchip_vpu2_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable,
jpeg_ctx.hw_chroma_qtable);
reg = VEPU_REG_OUTPUT_SWAP32
| VEPU_REG_OUTPUT_SWAP16
| VEPU_REG_OUTPUT_SWAP8
| VEPU_REG_INPUT_SWAP8
| VEPU_REG_INPUT_SWAP16
| VEPU_REG_INPUT_SWAP32;
/* Make sure that all registers are written at this point. */
vepu_write(vpu, reg, VEPU_REG_DATA_ENDIAN);
reg = VEPU_REG_AXI_CTRL_BURST_LEN(16);
vepu_write_relaxed(vpu, reg, VEPU_REG_AXI_CTRL);
reg = VEPU_REG_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width))
| VEPU_REG_MB_HEIGHT(MB_HEIGHT(ctx->src_fmt.height))
| VEPU_REG_FRAME_TYPE_INTRA
| VEPU_REG_ENCODE_FORMAT_JPEG
| VEPU_REG_ENCODE_ENABLE;
/* Kick the watchdog and start encoding */
hantro_end_prepare_run(ctx);
vepu_write(vpu, reg, VEPU_REG_ENCODE_START);
return 0;
}
void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
u32 bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8;
struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx);
vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
ctx->vpu_dst_fmt->header_size + bytesused);
}
@@ -0,0 +1,248 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*/
#include <linux/unaligned.h>
#include <linux/bitfield.h>
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
#define VDPU_SWREG(nr) ((nr) * 4)
#define VDPU_REG_DEC_OUT_BASE VDPU_SWREG(63)
#define VDPU_REG_RLC_VLC_BASE VDPU_SWREG(64)
#define VDPU_REG_QTABLE_BASE VDPU_SWREG(61)
#define VDPU_REG_REFER0_BASE VDPU_SWREG(131)
#define VDPU_REG_REFER2_BASE VDPU_SWREG(134)
#define VDPU_REG_REFER3_BASE VDPU_SWREG(135)
#define VDPU_REG_REFER1_BASE VDPU_SWREG(148)
#define VDPU_REG_DEC_E(v) ((v) ? BIT(0) : 0)
#define VDPU_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(11) : 0)
#define VDPU_REG_DEC_SCMD_DIS(v) ((v) ? BIT(10) : 0)
#define VDPU_REG_FILTERING_DIS(v) ((v) ? BIT(8) : 0)
#define VDPU_REG_DEC_LATENCY(v) (((v) << 1) & GENMASK(6, 1))
#define VDPU_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25))
#define VDPU_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0))
#define VDPU_REG_APF_THRESHOLD(v) (((v) << 17) & GENMASK(30, 17))
#define VDPU_REG_STARTMB_X(v) (((v) << 8) & GENMASK(16, 8))
#define VDPU_REG_STARTMB_Y(v) (((v) << 0) & GENMASK(7, 0))
#define VDPU_REG_DEC_MODE(v) (((v) << 0) & GENMASK(3, 0))
#define VDPU_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(5) : 0)
#define VDPU_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(4) : 0)
#define VDPU_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(3) : 0)
#define VDPU_REG_DEC_INSWAP32_E(v) ((v) ? BIT(2) : 0)
#define VDPU_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(1) : 0)
#define VDPU_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(0) : 0)
#define VDPU_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(22) : 0)
#define VDPU_REG_DEC_MAX_BURST(v) (((v) << 16) & GENMASK(20, 16))
#define VDPU_REG_DEC_AXI_WR_ID(v) (((v) << 8) & GENMASK(15, 8))
#define VDPU_REG_DEC_AXI_RD_ID(v) (((v) << 0) & GENMASK(7, 0))
#define VDPU_REG_RLC_MODE_E(v) ((v) ? BIT(20) : 0)
#define VDPU_REG_PIC_INTERLACE_E(v) ((v) ? BIT(17) : 0)
#define VDPU_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(16) : 0)
#define VDPU_REG_PIC_B_E(v) ((v) ? BIT(15) : 0)
#define VDPU_REG_PIC_INTER_E(v) ((v) ? BIT(14) : 0)
#define VDPU_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(13) : 0)
#define VDPU_REG_FWD_INTERLACE_E(v) ((v) ? BIT(12) : 0)
#define VDPU_REG_WRITE_MVS_E(v) ((v) ? BIT(10) : 0)
#define VDPU_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(5) : 0)
#define VDPU_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(4) : 0)
#define VDPU_REG_PIC_MB_WIDTH(v) (((v) << 23) & GENMASK(31, 23))
#define VDPU_REG_PIC_MB_HEIGHT_P(v) (((v) << 11) & GENMASK(18, 11))
#define VDPU_REG_ALT_SCAN_E(v) ((v) ? BIT(6) : 0)
#define VDPU_REG_TOPFIELDFIRST_E(v) ((v) ? BIT(5) : 0)
#define VDPU_REG_STRM_START_BIT(v) (((v) << 26) & GENMASK(31, 26))
#define VDPU_REG_QSCALE_TYPE(v) ((v) ? BIT(24) : 0)
#define VDPU_REG_CON_MV_E(v) ((v) ? BIT(4) : 0)
#define VDPU_REG_INTRA_DC_PREC(v) (((v) << 2) & GENMASK(3, 2))
#define VDPU_REG_INTRA_VLC_TAB(v) ((v) ? BIT(1) : 0)
#define VDPU_REG_FRAME_PRED_DCT(v) ((v) ? BIT(0) : 0)
#define VDPU_REG_ALT_SCAN_FLAG_E(v) ((v) ? BIT(19) : 0)
#define VDPU_REG_FCODE_FWD_HOR(v) (((v) << 15) & GENMASK(18, 15))
#define VDPU_REG_FCODE_FWD_VER(v) (((v) << 11) & GENMASK(14, 11))
#define VDPU_REG_FCODE_BWD_HOR(v) (((v) << 7) & GENMASK(10, 7))
#define VDPU_REG_FCODE_BWD_VER(v) (((v) << 3) & GENMASK(6, 3))
#define VDPU_REG_MV_ACCURACY_FWD(v) ((v) ? BIT(2) : 0)
#define VDPU_REG_MV_ACCURACY_BWD(v) ((v) ? BIT(1) : 0)
static void
rockchip_vpu2_mpeg2_dec_set_quantisation(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
struct v4l2_ctrl_mpeg2_quantisation *q;
q = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_MPEG2_QUANTISATION);
hantro_mpeg2_dec_copy_qtable(ctx->mpeg2_dec.qtable.cpu, q);
vdpu_write_relaxed(vpu, ctx->mpeg2_dec.qtable.dma, VDPU_REG_QTABLE_BASE);
}
static void
rockchip_vpu2_mpeg2_dec_set_buffers(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
struct vb2_buffer *src_buf,
struct vb2_buffer *dst_buf,
const struct v4l2_ctrl_mpeg2_sequence *seq,
const struct v4l2_ctrl_mpeg2_picture *pic)
{
dma_addr_t forward_addr = 0, backward_addr = 0;
dma_addr_t current_addr, addr;
switch (pic->picture_coding_type) {
case V4L2_MPEG2_PIC_CODING_TYPE_B:
backward_addr = hantro_get_ref(ctx, pic->backward_ref_ts);
fallthrough;
case V4L2_MPEG2_PIC_CODING_TYPE_P:
forward_addr = hantro_get_ref(ctx, pic->forward_ref_ts);
}
/* Source bitstream buffer */
addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
vdpu_write_relaxed(vpu, addr, VDPU_REG_RLC_VLC_BASE);
/* Destination frame buffer */
addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
current_addr = addr;
if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD)
addr += ALIGN(ctx->dst_fmt.width, 16);
vdpu_write_relaxed(vpu, addr, VDPU_REG_DEC_OUT_BASE);
if (!forward_addr)
forward_addr = current_addr;
if (!backward_addr)
backward_addr = current_addr;
/* Set forward ref frame (top/bottom field) */
if (pic->picture_structure == V4L2_MPEG2_PIC_FRAME ||
pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B ||
(pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD &&
pic->flags & V4L2_MPEG2_PIC_TOP_FIELD) ||
(pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD &&
!(pic->flags & V4L2_MPEG2_PIC_TOP_FIELD))) {
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER1_BASE);
} else if (pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) {
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, current_addr, VDPU_REG_REFER1_BASE);
} else if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD) {
vdpu_write_relaxed(vpu, current_addr, VDPU_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER1_BASE);
}
/* Set backward ref frame (top/bottom field) */
vdpu_write_relaxed(vpu, backward_addr, VDPU_REG_REFER2_BASE);
vdpu_write_relaxed(vpu, backward_addr, VDPU_REG_REFER3_BASE);
}
int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
const struct v4l2_ctrl_mpeg2_sequence *seq;
const struct v4l2_ctrl_mpeg2_picture *pic;
u32 reg;
src_buf = hantro_get_src_buf(ctx);
dst_buf = hantro_get_dst_buf(ctx);
hantro_start_prepare_run(ctx);
seq = hantro_get_ctrl(ctx,
V4L2_CID_STATELESS_MPEG2_SEQUENCE);
pic = hantro_get_ctrl(ctx,
V4L2_CID_STATELESS_MPEG2_PICTURE);
reg = VDPU_REG_DEC_ADV_PRE_DIS(0) |
VDPU_REG_DEC_SCMD_DIS(0) |
VDPU_REG_FILTERING_DIS(1) |
VDPU_REG_DEC_LATENCY(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(50));
reg = VDPU_REG_INIT_QP(1) |
VDPU_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(51));
reg = VDPU_REG_APF_THRESHOLD(8) |
VDPU_REG_STARTMB_X(0) |
VDPU_REG_STARTMB_Y(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(52));
reg = VDPU_REG_DEC_MODE(5);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(53));
reg = VDPU_REG_DEC_STRENDIAN_E(1) |
VDPU_REG_DEC_STRSWAP32_E(1) |
VDPU_REG_DEC_OUTSWAP32_E(1) |
VDPU_REG_DEC_INSWAP32_E(1) |
VDPU_REG_DEC_OUT_ENDIAN(1) |
VDPU_REG_DEC_IN_ENDIAN(1);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(54));
reg = VDPU_REG_DEC_DATA_DISC_E(0) |
VDPU_REG_DEC_MAX_BURST(16) |
VDPU_REG_DEC_AXI_WR_ID(0) |
VDPU_REG_DEC_AXI_RD_ID(0);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(56));
reg = VDPU_REG_RLC_MODE_E(0) |
VDPU_REG_PIC_INTERLACE_E(!(seq->flags & V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE)) |
VDPU_REG_PIC_FIELDMODE_E(pic->picture_structure != V4L2_MPEG2_PIC_FRAME) |
VDPU_REG_PIC_B_E(pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B) |
VDPU_REG_PIC_INTER_E(pic->picture_coding_type != V4L2_MPEG2_PIC_CODING_TYPE_I) |
VDPU_REG_PIC_TOPFIELD_E(pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) |
VDPU_REG_FWD_INTERLACE_E(0) |
VDPU_REG_WRITE_MVS_E(0) |
VDPU_REG_DEC_TIMEOUT_E(1) |
VDPU_REG_DEC_CLK_GATE_E(1);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(57));
reg = VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->dst_fmt.width)) |
VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->dst_fmt.height)) |
VDPU_REG_ALT_SCAN_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
VDPU_REG_TOPFIELDFIRST_E(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(120));
reg = VDPU_REG_STRM_START_BIT(0) |
VDPU_REG_QSCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE) |
VDPU_REG_CON_MV_E(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV) |
VDPU_REG_INTRA_DC_PREC(pic->intra_dc_precision) |
VDPU_REG_INTRA_VLC_TAB(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC) |
VDPU_REG_FRAME_PRED_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(122));
reg = VDPU_REG_ALT_SCAN_FLAG_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
VDPU_REG_FCODE_FWD_HOR(pic->f_code[0][0]) |
VDPU_REG_FCODE_FWD_VER(pic->f_code[0][1]) |
VDPU_REG_FCODE_BWD_HOR(pic->f_code[1][0]) |
VDPU_REG_FCODE_BWD_VER(pic->f_code[1][1]) |
VDPU_REG_MV_ACCURACY_FWD(1) |
VDPU_REG_MV_ACCURACY_BWD(1);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(136));
rockchip_vpu2_mpeg2_dec_set_quantisation(vpu, ctx);
rockchip_vpu2_mpeg2_dec_set_buffers(vpu, ctx, &src_buf->vb2_buf,
&dst_buf->vb2_buf, seq, pic);
/* Kick the watchdog and start decoding */
hantro_end_prepare_run(ctx);
reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1);
vdpu_write(vpu, reg, VDPU_SWREG(57));
return 0;
}
@@ -0,0 +1,600 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Rockchip VPU codec vp8 decode driver
*
* Copyright (C) 2014 Rockchip Electronics Co., Ltd.
* ZhiChao Yu <zhichao.yu@rock-chips.com>
*
* Copyright (C) 2014 Google LLC.
* Tomasz Figa <tfiga@chromium.org>
*
* Copyright (C) 2015 Rockchip Electronics Co., Ltd.
* Alpha Lin <alpha.lin@rock-chips.com>
*/
#include <media/v4l2-mem2mem.h>
#include "hantro_hw.h"
#include "hantro.h"
#include "hantro_g1_regs.h"
#define VDPU_REG_DEC_CTRL0 0x0c8
#define VDPU_REG_STREAM_LEN 0x0cc
#define VDPU_REG_DEC_FORMAT 0x0d4
#define VDPU_REG_DEC_CTRL0_DEC_MODE(x) (((x) & 0xf) << 0)
#define VDPU_REG_DATA_ENDIAN 0x0d8
#define VDPU_REG_CONFIG_DEC_STRENDIAN_E BIT(5)
#define VDPU_REG_CONFIG_DEC_STRSWAP32_E BIT(4)
#define VDPU_REG_CONFIG_DEC_OUTSWAP32_E BIT(3)
#define VDPU_REG_CONFIG_DEC_INSWAP32_E BIT(2)
#define VDPU_REG_CONFIG_DEC_OUT_ENDIAN BIT(1)
#define VDPU_REG_CONFIG_DEC_IN_ENDIAN BIT(0)
#define VDPU_REG_AXI_CTRL 0x0e0
#define VDPU_REG_CONFIG_DEC_MAX_BURST(x) (((x) & 0x1f) << 16)
#define VDPU_REG_EN_FLAGS 0x0e4
#define VDPU_REG_DEC_CTRL0_PIC_INTER_E BIT(14)
#define VDPU_REG_CONFIG_DEC_TIMEOUT_E BIT(5)
#define VDPU_REG_CONFIG_DEC_CLK_GATE_E BIT(4)
#define VDPU_REG_PRED_FLT 0x0ec
#define VDPU_REG_ADDR_QTABLE 0x0f4
#define VDPU_REG_ADDR_DST 0x0fc
#define VDPU_REG_ADDR_STR 0x100
#define VDPU_REG_VP8_PIC_MB_SIZE 0x1e0
#define VDPU_REG_VP8_DCT_START_BIT 0x1e4
#define VDPU_REG_DEC_CTRL4_VC1_HEIGHT_EXT BIT(13)
#define VDPU_REG_DEC_CTRL4_BILIN_MC_E BIT(12)
#define VDPU_REG_VP8_CTRL0 0x1e8
#define VDPU_REG_VP8_DATA_VAL 0x1f0
#define VDPU_REG_PRED_FLT7 0x1f4
#define VDPU_REG_PRED_FLT8 0x1f8
#define VDPU_REG_PRED_FLT9 0x1fc
#define VDPU_REG_PRED_FLT10 0x200
#define VDPU_REG_FILTER_LEVEL 0x204
#define VDPU_REG_VP8_QUANTER0 0x208
#define VDPU_REG_VP8_ADDR_REF0 0x20c
#define VDPU_REG_FILTER_MB_ADJ 0x210
#define VDPU_REG_REF_PIC_FILT_TYPE_E BIT(31)
#define VDPU_REG_REF_PIC_FILT_SHARPNESS(x) (((x) & 0x7) << 28)
#define VDPU_REG_FILTER_REF_ADJ 0x214
#define VDPU_REG_VP8_ADDR_REF2_5(i) (0x218 + ((i) * 0x4))
#define VDPU_REG_VP8_GREF_SIGN_BIAS BIT(0)
#define VDPU_REG_VP8_AREF_SIGN_BIAS BIT(0)
#define VDPU_REG_VP8_DCT_BASE(i) \
(0x230 + ((((i) < 5) ? (i) : ((i) + 1)) * 0x4))
#define VDPU_REG_VP8_ADDR_CTRL_PART 0x244
#define VDPU_REG_VP8_SEGMENT_VAL 0x254
#define VDPU_REG_FWD_PIC1_SEGMENT_BASE(x) ((x) << 0)
#define VDPU_REG_FWD_PIC1_SEGMENT_UPD_E BIT(1)
#define VDPU_REG_FWD_PIC1_SEGMENT_E BIT(0)
#define VDPU_REG_VP8_DCT_START_BIT2 0x258
#define VDPU_REG_VP8_QUANTER1 0x25c
#define VDPU_REG_VP8_QUANTER2 0x260
#define VDPU_REG_PRED_FLT1 0x264
#define VDPU_REG_PRED_FLT2 0x268
#define VDPU_REG_PRED_FLT3 0x26c
#define VDPU_REG_PRED_FLT4 0x270
#define VDPU_REG_PRED_FLT5 0x274
#define VDPU_REG_PRED_FLT6 0x278
static const struct hantro_reg vp8_dec_dct_base[8] = {
{ VDPU_REG_ADDR_STR, 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(0), 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(1), 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(2), 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(3), 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(4), 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(5), 0, 0xffffffff },
{ VDPU_REG_VP8_DCT_BASE(6), 0, 0xffffffff },
};
static const struct hantro_reg vp8_dec_lf_level[4] = {
{ VDPU_REG_FILTER_LEVEL, 18, 0x3f },
{ VDPU_REG_FILTER_LEVEL, 12, 0x3f },
{ VDPU_REG_FILTER_LEVEL, 6, 0x3f },
{ VDPU_REG_FILTER_LEVEL, 0, 0x3f },
};
static const struct hantro_reg vp8_dec_mb_adj[4] = {
{ VDPU_REG_FILTER_MB_ADJ, 21, 0x7f },
{ VDPU_REG_FILTER_MB_ADJ, 14, 0x7f },
{ VDPU_REG_FILTER_MB_ADJ, 7, 0x7f },
{ VDPU_REG_FILTER_MB_ADJ, 0, 0x7f },
};
static const struct hantro_reg vp8_dec_ref_adj[4] = {
{ VDPU_REG_FILTER_REF_ADJ, 21, 0x7f },
{ VDPU_REG_FILTER_REF_ADJ, 14, 0x7f },
{ VDPU_REG_FILTER_REF_ADJ, 7, 0x7f },
{ VDPU_REG_FILTER_REF_ADJ, 0, 0x7f },
};
static const struct hantro_reg vp8_dec_quant[4] = {
{ VDPU_REG_VP8_QUANTER0, 11, 0x7ff },
{ VDPU_REG_VP8_QUANTER0, 0, 0x7ff },
{ VDPU_REG_VP8_QUANTER1, 11, 0x7ff },
{ VDPU_REG_VP8_QUANTER1, 0, 0x7ff },
};
static const struct hantro_reg vp8_dec_quant_delta[5] = {
{ VDPU_REG_VP8_QUANTER0, 27, 0x1f },
{ VDPU_REG_VP8_QUANTER0, 22, 0x1f },
{ VDPU_REG_VP8_QUANTER1, 27, 0x1f },
{ VDPU_REG_VP8_QUANTER1, 22, 0x1f },
{ VDPU_REG_VP8_QUANTER2, 27, 0x1f },
};
static const struct hantro_reg vp8_dec_dct_start_bits[8] = {
{ VDPU_REG_VP8_CTRL0, 26, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT, 26, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT, 20, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT2, 24, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT2, 18, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT2, 12, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT2, 6, 0x3f },
{ VDPU_REG_VP8_DCT_START_BIT2, 0, 0x3f },
};
static const struct hantro_reg vp8_dec_pred_bc_tap[8][6] = {
{
{ 0, 0, 0},
{ VDPU_REG_PRED_FLT, 22, 0x3ff },
{ VDPU_REG_PRED_FLT, 12, 0x3ff },
{ VDPU_REG_PRED_FLT, 2, 0x3ff },
{ VDPU_REG_PRED_FLT1, 22, 0x3ff },
{ 0, 0, 0},
}, {
{ 0, 0, 0},
{ VDPU_REG_PRED_FLT1, 12, 0x3ff },
{ VDPU_REG_PRED_FLT1, 2, 0x3ff },
{ VDPU_REG_PRED_FLT2, 22, 0x3ff },
{ VDPU_REG_PRED_FLT2, 12, 0x3ff },
{ 0, 0, 0},
}, {
{ VDPU_REG_PRED_FLT10, 10, 0x3 },
{ VDPU_REG_PRED_FLT2, 2, 0x3ff },
{ VDPU_REG_PRED_FLT3, 22, 0x3ff },
{ VDPU_REG_PRED_FLT3, 12, 0x3ff },
{ VDPU_REG_PRED_FLT3, 2, 0x3ff },
{ VDPU_REG_PRED_FLT10, 8, 0x3},
}, {
{ 0, 0, 0},
{ VDPU_REG_PRED_FLT4, 22, 0x3ff },
{ VDPU_REG_PRED_FLT4, 12, 0x3ff },
{ VDPU_REG_PRED_FLT4, 2, 0x3ff },
{ VDPU_REG_PRED_FLT5, 22, 0x3ff },
{ 0, 0, 0},
}, {
{ VDPU_REG_PRED_FLT10, 6, 0x3 },
{ VDPU_REG_PRED_FLT5, 12, 0x3ff },
{ VDPU_REG_PRED_FLT5, 2, 0x3ff },
{ VDPU_REG_PRED_FLT6, 22, 0x3ff },
{ VDPU_REG_PRED_FLT6, 12, 0x3ff },
{ VDPU_REG_PRED_FLT10, 4, 0x3 },
}, {
{ 0, 0, 0},
{ VDPU_REG_PRED_FLT6, 2, 0x3ff },
{ VDPU_REG_PRED_FLT7, 22, 0x3ff },
{ VDPU_REG_PRED_FLT7, 12, 0x3ff },
{ VDPU_REG_PRED_FLT7, 2, 0x3ff },
{ 0, 0, 0},
}, {
{ VDPU_REG_PRED_FLT10, 2, 0x3 },
{ VDPU_REG_PRED_FLT8, 22, 0x3ff },
{ VDPU_REG_PRED_FLT8, 12, 0x3ff },
{ VDPU_REG_PRED_FLT8, 2, 0x3ff },
{ VDPU_REG_PRED_FLT9, 22, 0x3ff },
{ VDPU_REG_PRED_FLT10, 0, 0x3 },
}, {
{ 0, 0, 0},
{ VDPU_REG_PRED_FLT9, 12, 0x3ff },
{ VDPU_REG_PRED_FLT9, 2, 0x3ff },
{ VDPU_REG_PRED_FLT10, 22, 0x3ff },
{ VDPU_REG_PRED_FLT10, 12, 0x3ff },
{ 0, 0, 0},
},
};
static const struct hantro_reg vp8_dec_mb_start_bit = {
.base = VDPU_REG_VP8_CTRL0,
.shift = 18,
.mask = 0x3f
};
static const struct hantro_reg vp8_dec_mb_aligned_data_len = {
.base = VDPU_REG_VP8_DATA_VAL,
.shift = 0,
.mask = 0x3fffff
};
static const struct hantro_reg vp8_dec_num_dct_partitions = {
.base = VDPU_REG_VP8_DATA_VAL,
.shift = 24,
.mask = 0xf
};
static const struct hantro_reg vp8_dec_stream_len = {
.base = VDPU_REG_STREAM_LEN,
.shift = 0,
.mask = 0xffffff
};
static const struct hantro_reg vp8_dec_mb_width = {
.base = VDPU_REG_VP8_PIC_MB_SIZE,
.shift = 23,
.mask = 0x1ff
};
static const struct hantro_reg vp8_dec_mb_height = {
.base = VDPU_REG_VP8_PIC_MB_SIZE,
.shift = 11,
.mask = 0xff
};
static const struct hantro_reg vp8_dec_mb_width_ext = {
.base = VDPU_REG_VP8_PIC_MB_SIZE,
.shift = 3,
.mask = 0x7
};
static const struct hantro_reg vp8_dec_mb_height_ext = {
.base = VDPU_REG_VP8_PIC_MB_SIZE,
.shift = 0,
.mask = 0x7
};
static const struct hantro_reg vp8_dec_bool_range = {
.base = VDPU_REG_VP8_CTRL0,
.shift = 0,
.mask = 0xff
};
static const struct hantro_reg vp8_dec_bool_value = {
.base = VDPU_REG_VP8_CTRL0,
.shift = 8,
.mask = 0xff
};
static const struct hantro_reg vp8_dec_filter_disable = {
.base = VDPU_REG_DEC_CTRL0,
.shift = 8,
.mask = 1
};
static const struct hantro_reg vp8_dec_skip_mode = {
.base = VDPU_REG_DEC_CTRL0,
.shift = 9,
.mask = 1
};
static const struct hantro_reg vp8_dec_start_dec = {
.base = VDPU_REG_EN_FLAGS,
.shift = 0,
.mask = 1
};
static void cfg_lf(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
const struct v4l2_vp8_segment *seg = &hdr->segment;
const struct v4l2_vp8_loop_filter *lf = &hdr->lf;
struct hantro_dev *vpu = ctx->dev;
unsigned int i;
u32 reg;
if (!(seg->flags & V4L2_VP8_SEGMENT_FLAG_ENABLED)) {
hantro_reg_write(vpu, &vp8_dec_lf_level[0], lf->level);
} else if (seg->flags & V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE) {
for (i = 0; i < 4; i++) {
u32 lf_level = clamp(lf->level + seg->lf_update[i],
0, 63);
hantro_reg_write(vpu, &vp8_dec_lf_level[i], lf_level);
}
} else {
for (i = 0; i < 4; i++)
hantro_reg_write(vpu, &vp8_dec_lf_level[i],
seg->lf_update[i]);
}
reg = VDPU_REG_REF_PIC_FILT_SHARPNESS(lf->sharpness_level);
if (lf->flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE)
reg |= VDPU_REG_REF_PIC_FILT_TYPE_E;
vdpu_write_relaxed(vpu, reg, VDPU_REG_FILTER_MB_ADJ);
if (lf->flags & V4L2_VP8_LF_ADJ_ENABLE) {
for (i = 0; i < 4; i++) {
hantro_reg_write(vpu, &vp8_dec_mb_adj[i],
lf->mb_mode_delta[i]);
hantro_reg_write(vpu, &vp8_dec_ref_adj[i],
lf->ref_frm_delta[i]);
}
}
}
static void cfg_qp(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
const struct v4l2_vp8_quantization *q = &hdr->quant;
const struct v4l2_vp8_segment *seg = &hdr->segment;
struct hantro_dev *vpu = ctx->dev;
unsigned int i;
if (!(seg->flags & V4L2_VP8_SEGMENT_FLAG_ENABLED)) {
hantro_reg_write(vpu, &vp8_dec_quant[0], q->y_ac_qi);
} else if (seg->flags & V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE) {
for (i = 0; i < 4; i++) {
u32 quant = clamp(q->y_ac_qi + seg->quant_update[i],
0, 127);
hantro_reg_write(vpu, &vp8_dec_quant[i], quant);
}
} else {
for (i = 0; i < 4; i++)
hantro_reg_write(vpu, &vp8_dec_quant[i],
seg->quant_update[i]);
}
hantro_reg_write(vpu, &vp8_dec_quant_delta[0], q->y_dc_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[1], q->y2_dc_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[2], q->y2_ac_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[3], q->uv_dc_delta);
hantro_reg_write(vpu, &vp8_dec_quant_delta[4], q->uv_ac_delta);
}
static void cfg_parts(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *vb2_src;
u32 first_part_offset = V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) ? 10 : 3;
u32 mb_size, mb_offset_bytes, mb_offset_bits, mb_start_bits;
u32 dct_size_part_size, dct_part_offset;
dma_addr_t src_dma;
u32 dct_part_total_len = 0;
u32 count = 0;
unsigned int i;
vb2_src = hantro_get_src_buf(ctx);
src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0);
/*
* Calculate control partition mb data info
* @first_part_header_bits: bits offset of mb data from first
* part start pos
* @mb_offset_bits: bits offset of mb data from src_dma
* base addr
* @mb_offset_byte: bytes offset of mb data from src_dma
* base addr
* @mb_start_bits: bits offset of mb data from mb data
* 64bits alignment addr
*/
mb_offset_bits = first_part_offset * 8 +
hdr->first_part_header_bits + 8;
mb_offset_bytes = mb_offset_bits / 8;
mb_start_bits = mb_offset_bits -
(mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) * 8;
mb_size = hdr->first_part_size -
(mb_offset_bytes - first_part_offset) +
(mb_offset_bytes & DEC_8190_ALIGN_MASK);
/* Macroblock data aligned base addr */
vdpu_write_relaxed(vpu, (mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) +
src_dma, VDPU_REG_VP8_ADDR_CTRL_PART);
hantro_reg_write(vpu, &vp8_dec_mb_start_bit, mb_start_bits);
hantro_reg_write(vpu, &vp8_dec_mb_aligned_data_len, mb_size);
/*
* Calculate DCT partition info
* @dct_size_part_size: Containing sizes of DCT part, every DCT part
* has 3 bytes to store its size, except the last
* DCT part
* @dct_part_offset: bytes offset of DCT parts from src_dma base addr
* @dct_part_total_len: total size of all DCT parts
*/
dct_size_part_size = (hdr->num_dct_parts - 1) * 3;
dct_part_offset = first_part_offset + hdr->first_part_size;
for (i = 0; i < hdr->num_dct_parts; i++)
dct_part_total_len += hdr->dct_part_sizes[i];
dct_part_total_len += dct_size_part_size;
dct_part_total_len += (dct_part_offset & DEC_8190_ALIGN_MASK);
/* Number of DCT partitions */
hantro_reg_write(vpu, &vp8_dec_num_dct_partitions,
hdr->num_dct_parts - 1);
/* DCT partition length */
hantro_reg_write(vpu, &vp8_dec_stream_len, dct_part_total_len);
/* DCT partitions base address */
for (i = 0; i < hdr->num_dct_parts; i++) {
u32 byte_offset = dct_part_offset + dct_size_part_size + count;
u32 base_addr = byte_offset + src_dma;
hantro_reg_write(vpu, &vp8_dec_dct_base[i],
base_addr & (~DEC_8190_ALIGN_MASK));
hantro_reg_write(vpu, &vp8_dec_dct_start_bits[i],
(byte_offset & DEC_8190_ALIGN_MASK) * 8);
count += hdr->dct_part_sizes[i];
}
}
/*
* prediction filter taps
* normal 6-tap filters
*/
static void cfg_tap(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
struct hantro_dev *vpu = ctx->dev;
int i, j;
if ((hdr->version & 0x03) != 0)
return; /* Tap filter not used. */
for (i = 0; i < 8; i++) {
for (j = 0; j < 6; j++) {
if (vp8_dec_pred_bc_tap[i][j].base != 0)
hantro_reg_write(vpu,
&vp8_dec_pred_bc_tap[i][j],
hantro_vp8_dec_mc_filter[i][j]);
}
}
}
static void cfg_ref(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr,
struct vb2_v4l2_buffer *vb2_dst)
{
struct hantro_dev *vpu = ctx->dev;
dma_addr_t ref;
ref = hantro_get_ref(ctx, hdr->last_frame_ts);
if (!ref) {
vpu_debug(0, "failed to find last frame ts=%llu\n",
hdr->last_frame_ts);
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
}
vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF0);
ref = hantro_get_ref(ctx, hdr->golden_frame_ts);
if (!ref && hdr->golden_frame_ts)
vpu_debug(0, "failed to find golden frame ts=%llu\n",
hdr->golden_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN)
ref |= VDPU_REG_VP8_GREF_SIGN_BIAS;
vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF2_5(2));
ref = hantro_get_ref(ctx, hdr->alt_frame_ts);
if (!ref && hdr->alt_frame_ts)
vpu_debug(0, "failed to find alt frame ts=%llu\n",
hdr->alt_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT)
ref |= VDPU_REG_VP8_AREF_SIGN_BIAS;
vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF2_5(3));
}
static void cfg_buffers(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr,
struct vb2_v4l2_buffer *vb2_dst)
{
const struct v4l2_vp8_segment *seg = &hdr->segment;
struct hantro_dev *vpu = ctx->dev;
dma_addr_t dst_dma;
u32 reg;
/* Set probability table buffer address */
vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma,
VDPU_REG_ADDR_QTABLE);
/* Set segment map address */
reg = VDPU_REG_FWD_PIC1_SEGMENT_BASE(ctx->vp8_dec.segment_map.dma);
if (seg->flags & V4L2_VP8_SEGMENT_FLAG_ENABLED) {
reg |= VDPU_REG_FWD_PIC1_SEGMENT_E;
if (seg->flags & V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP)
reg |= VDPU_REG_FWD_PIC1_SEGMENT_UPD_E;
}
vdpu_write_relaxed(vpu, reg, VDPU_REG_VP8_SEGMENT_VAL);
/* set output frame buffer address */
dst_dma = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
vdpu_write_relaxed(vpu, dst_dma, VDPU_REG_ADDR_DST);
}
int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp8_frame *hdr;
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *vb2_dst;
size_t height = ctx->dst_fmt.height;
size_t width = ctx->dst_fmt.width;
u32 mb_width, mb_height;
u32 reg;
hantro_start_prepare_run(ctx);
hdr = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_VP8_FRAME);
if (WARN_ON(!hdr))
return -EINVAL;
/* Reset segment_map buffer in keyframe */
if (V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) && ctx->vp8_dec.segment_map.cpu)
memset(ctx->vp8_dec.segment_map.cpu, 0,
ctx->vp8_dec.segment_map.size);
hantro_vp8_prob_update(ctx, hdr);
/*
* Extensive testing shows that the hardware does not properly
* clear the internal state from previous a decoding run. This
* causes corruption in decoded frames for multi-instance use cases.
* A soft reset before programming the registers has been found
* to resolve those problems.
*/
ctx->codec_ops->reset(ctx);
reg = VDPU_REG_CONFIG_DEC_TIMEOUT_E
| VDPU_REG_CONFIG_DEC_CLK_GATE_E;
if (!V4L2_VP8_FRAME_IS_KEY_FRAME(hdr))
reg |= VDPU_REG_DEC_CTRL0_PIC_INTER_E;
vdpu_write_relaxed(vpu, reg, VDPU_REG_EN_FLAGS);
reg = VDPU_REG_CONFIG_DEC_STRENDIAN_E
| VDPU_REG_CONFIG_DEC_INSWAP32_E
| VDPU_REG_CONFIG_DEC_STRSWAP32_E
| VDPU_REG_CONFIG_DEC_OUTSWAP32_E
| VDPU_REG_CONFIG_DEC_IN_ENDIAN
| VDPU_REG_CONFIG_DEC_OUT_ENDIAN;
vdpu_write_relaxed(vpu, reg, VDPU_REG_DATA_ENDIAN);
reg = VDPU_REG_CONFIG_DEC_MAX_BURST(16);
vdpu_write_relaxed(vpu, reg, VDPU_REG_AXI_CTRL);
reg = VDPU_REG_DEC_CTRL0_DEC_MODE(10);
vdpu_write_relaxed(vpu, reg, VDPU_REG_DEC_FORMAT);
if (!(hdr->flags & V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF))
hantro_reg_write(vpu, &vp8_dec_skip_mode, 1);
if (hdr->lf.level == 0)
hantro_reg_write(vpu, &vp8_dec_filter_disable, 1);
/* Frame dimensions */
mb_width = MB_WIDTH(width);
mb_height = MB_HEIGHT(height);
hantro_reg_write(vpu, &vp8_dec_mb_width, mb_width);
hantro_reg_write(vpu, &vp8_dec_mb_height, mb_height);
hantro_reg_write(vpu, &vp8_dec_mb_width_ext, mb_width >> 9);
hantro_reg_write(vpu, &vp8_dec_mb_height_ext, mb_height >> 8);
/* Boolean decoder */
hantro_reg_write(vpu, &vp8_dec_bool_range, hdr->coder_state.range);
hantro_reg_write(vpu, &vp8_dec_bool_value, hdr->coder_state.value);
reg = vdpu_read(vpu, VDPU_REG_VP8_DCT_START_BIT);
if (hdr->version != 3)
reg |= VDPU_REG_DEC_CTRL4_VC1_HEIGHT_EXT;
if (hdr->version & 0x3)
reg |= VDPU_REG_DEC_CTRL4_BILIN_MC_E;
vdpu_write_relaxed(vpu, reg, VDPU_REG_VP8_DCT_START_BIT);
cfg_lf(ctx, hdr);
cfg_qp(ctx, hdr);
cfg_parts(ctx, hdr);
cfg_tap(ctx, hdr);
vb2_dst = hantro_get_dst_buf(ctx);
cfg_ref(ctx, hdr, vb2_dst);
cfg_buffers(ctx, hdr, vb2_dst);
hantro_end_prepare_run(ctx);
hantro_reg_write(vpu, &vp8_dec_start_dec, 1);
return 0;
}
@@ -0,0 +1,600 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
* Alpha Lin <alpha.lin@rock-chips.com>
*/
#ifndef ROCKCHIP_VPU2_REGS_H_
#define ROCKCHIP_VPU2_REGS_H_
/* Encoder registers. */
#define VEPU_REG_VP8_QUT_1ST(i) (0x000 + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_DC_Y2(x) (((x) & 0x3fff) << 16)
#define VEPU_REG_VP8_QUT_DC_Y1(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_QUT_2ND(i) (0x004 + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_AC_Y1(x) (((x) & 0x3fff) << 16)
#define VEPU_REG_VP8_QUT_DC_CHR(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_QUT_3RD(i) (0x008 + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_AC_CHR(x) (((x) & 0x3fff) << 16)
#define VEPU_REG_VP8_QUT_AC_Y2(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_QUT_4TH(i) (0x00c + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_ZB_DC_CHR(x) (((x) & 0x1ff) << 18)
#define VEPU_REG_VP8_QUT_ZB_DC_Y2(x) (((x) & 0x1ff) << 9)
#define VEPU_REG_VP8_QUT_ZB_DC_Y1(x) (((x) & 0x1ff) << 0)
#define VEPU_REG_VP8_QUT_5TH(i) (0x010 + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_ZB_AC_CHR(x) (((x) & 0x1ff) << 18)
#define VEPU_REG_VP8_QUT_ZB_AC_Y2(x) (((x) & 0x1ff) << 9)
#define VEPU_REG_VP8_QUT_ZB_AC_Y1(x) (((x) & 0x1ff) << 0)
#define VEPU_REG_VP8_QUT_6TH(i) (0x014 + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_RND_DC_CHR(x) (((x) & 0xff) << 16)
#define VEPU_REG_VP8_QUT_RND_DC_Y2(x) (((x) & 0xff) << 8)
#define VEPU_REG_VP8_QUT_RND_DC_Y1(x) (((x) & 0xff) << 0)
#define VEPU_REG_VP8_QUT_7TH(i) (0x018 + ((i) * 0x24))
#define VEPU_REG_VP8_QUT_RND_AC_CHR(x) (((x) & 0xff) << 16)
#define VEPU_REG_VP8_QUT_RND_AC_Y2(x) (((x) & 0xff) << 8)
#define VEPU_REG_VP8_QUT_RND_AC_Y1(x) (((x) & 0xff) << 0)
#define VEPU_REG_VP8_QUT_8TH(i) (0x01c + ((i) * 0x24))
#define VEPU_REG_VP8_SEG_FILTER_LEVEL(x) (((x) & 0x3f) << 25)
#define VEPU_REG_VP8_DEQUT_DC_CHR(x) (((x) & 0xff) << 17)
#define VEPU_REG_VP8_DEQUT_DC_Y2(x) (((x) & 0x1ff) << 8)
#define VEPU_REG_VP8_DEQUT_DC_Y1(x) (((x) & 0xff) << 0)
#define VEPU_REG_VP8_QUT_9TH(i) (0x020 + ((i) * 0x24))
#define VEPU_REG_VP8_DEQUT_AC_CHR(x) (((x) & 0x1ff) << 18)
#define VEPU_REG_VP8_DEQUT_AC_Y2(x) (((x) & 0x1ff) << 9)
#define VEPU_REG_VP8_DEQUT_AC_Y1(x) (((x) & 0x1ff) << 0)
#define VEPU_REG_ADDR_VP8_SEG_MAP 0x06c
#define VEPU_REG_VP8_INTRA_4X4_PENALTY(i) (0x070 + ((i) * 0x4))
#define VEPU_REG_VP8_INTRA_4X4_PENALTY_0(x) (((x) & 0xfff) << 0)
#define VEPU_REG_VP8_INTRA_4x4_PENALTY_1(x) (((x) & 0xfff) << 16)
#define VEPU_REG_VP8_INTRA_16X16_PENALTY(i) (0x084 + ((i) * 0x4))
#define VEPU_REG_VP8_INTRA_16X16_PENALTY_0(x) (((x) & 0xfff) << 0)
#define VEPU_REG_VP8_INTRA_16X16_PENALTY_1(x) (((x) & 0xfff) << 16)
#define VEPU_REG_VP8_CONTROL 0x0a0
#define VEPU_REG_VP8_LF_MODE_DELTA_BPRED(x) (((x) & 0x1f) << 24)
#define VEPU_REG_VP8_LF_REF_DELTA_INTRA_MB(x) (((x) & 0x7f) << 16)
#define VEPU_REG_VP8_INTER_TYPE_BIT_COST(x) (((x) & 0xfff) << 0)
#define VEPU_REG_VP8_REF_FRAME_VAL 0x0a4
#define VEPU_REG_VP8_COEF_DMV_PENALTY(x) (((x) & 0xfff) << 16)
#define VEPU_REG_VP8_REF_FRAME(x) (((x) & 0xfff) << 0)
#define VEPU_REG_VP8_LOOP_FILTER_REF_DELTA 0x0a8
#define VEPU_REG_VP8_LF_REF_DELTA_ALT_REF(x) (((x) & 0x7f) << 16)
#define VEPU_REG_VP8_LF_REF_DELTA_LAST_REF(x) (((x) & 0x7f) << 8)
#define VEPU_REG_VP8_LF_REF_DELTA_GOLDEN(x) (((x) & 0x7f) << 0)
#define VEPU_REG_VP8_LOOP_FILTER_MODE_DELTA 0x0ac
#define VEPU_REG_VP8_LF_MODE_DELTA_SPLITMV(x) (((x) & 0x7f) << 16)
#define VEPU_REG_VP8_LF_MODE_DELTA_ZEROMV(x) (((x) & 0x7f) << 8)
#define VEPU_REG_VP8_LF_MODE_DELTA_NEWMV(x) (((x) & 0x7f) << 0)
#define VEPU_REG_JPEG_LUMA_QUAT(i) (0x000 + ((i) * 0x4))
#define VEPU_REG_JPEG_CHROMA_QUAT(i) (0x040 + ((i) * 0x4))
#define VEPU_REG_INTRA_SLICE_BITMAP(i) (0x0b0 + ((i) * 0x4))
#define VEPU_REG_ADDR_VP8_DCT_PART(i) (0x0b0 + ((i) * 0x4))
#define VEPU_REG_INTRA_AREA_CTRL 0x0b8
#define VEPU_REG_INTRA_AREA_TOP(x) (((x) & 0xff) << 24)
#define VEPU_REG_INTRA_AREA_BOTTOM(x) (((x) & 0xff) << 16)
#define VEPU_REG_INTRA_AREA_LEFT(x) (((x) & 0xff) << 8)
#define VEPU_REG_INTRA_AREA_RIGHT(x) (((x) & 0xff) << 0)
#define VEPU_REG_CIR_INTRA_CTRL 0x0bc
#define VEPU_REG_CIR_INTRA_FIRST_MB(x) (((x) & 0xffff) << 16)
#define VEPU_REG_CIR_INTRA_INTERVAL(x) (((x) & 0xffff) << 0)
#define VEPU_REG_ADDR_IN_PLANE_0 0x0c0
#define VEPU_REG_ADDR_IN_PLANE_1 0x0c4
#define VEPU_REG_ADDR_IN_PLANE_2 0x0c8
#define VEPU_REG_STR_HDR_REM_MSB 0x0cc
#define VEPU_REG_STR_HDR_REM_LSB 0x0d0
#define VEPU_REG_STR_BUF_LIMIT 0x0d4
#define VEPU_REG_AXI_CTRL 0x0d8
#define VEPU_REG_AXI_CTRL_READ_ID(x) (((x) & 0xff) << 24)
#define VEPU_REG_AXI_CTRL_WRITE_ID(x) (((x) & 0xff) << 16)
#define VEPU_REG_AXI_CTRL_BURST_LEN(x) (((x) & 0x3f) << 8)
#define VEPU_REG_AXI_CTRL_INCREMENT_MODE(x) (((x) & 0x01) << 2)
#define VEPU_REG_AXI_CTRL_BIRST_DISCARD(x) (((x) & 0x01) << 1)
#define VEPU_REG_AXI_CTRL_BIRST_DISABLE BIT(0)
#define VEPU_QP_ADJUST_MAD_DELTA_ROI 0x0dc
#define VEPU_REG_ROI_QP_DELTA_1 (((x) & 0xf) << 12)
#define VEPU_REG_ROI_QP_DELTA_2 (((x) & 0xf) << 8)
#define VEPU_REG_MAD_QP_ADJUSTMENT (((x) & 0xf) << 0)
#define VEPU_REG_ADDR_REF_LUMA 0x0e0
#define VEPU_REG_ADDR_REF_CHROMA 0x0e4
#define VEPU_REG_QP_SUM_DIV2 0x0e8
#define VEPU_REG_QP_SUM(x) (((x) & 0x001fffff) * 2)
#define VEPU_REG_ENC_CTRL0 0x0ec
#define VEPU_REG_DISABLE_QUARTER_PIXEL_MV BIT(28)
#define VEPU_REG_DEBLOCKING_FILTER_MODE(x) (((x) & 0x3) << 24)
#define VEPU_REG_CABAC_INIT_IDC(x) (((x) & 0x3) << 21)
#define VEPU_REG_ENTROPY_CODING_MODE BIT(20)
#define VEPU_REG_H264_TRANS8X8_MODE BIT(17)
#define VEPU_REG_H264_INTER4X4_MODE BIT(16)
#define VEPU_REG_H264_STREAM_MODE BIT(15)
#define VEPU_REG_H264_SLICE_SIZE(x) (((x) & 0x7f) << 8)
#define VEPU_REG_ENC_OVER_FILL_STRM_OFFSET 0x0f0
#define VEPU_REG_STREAM_START_OFFSET(x) (((x) & 0x3f) << 16)
#define VEPU_REG_SKIP_MACROBLOCK_PENALTY(x) (((x) & 0xff) << 8)
#define VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(x) (((x) & 0x3) << 4)
#define VEPU_REG_IN_IMG_CTRL_OVRFLB(x) (((x) & 0xf) << 0)
#define VEPU_REG_INPUT_LUMA_INFO 0x0f4
#define VEPU_REG_IN_IMG_CHROMA_OFFSET(x) (((x) & 0x7) << 20)
#define VEPU_REG_IN_IMG_LUMA_OFFSET(x) (((x) & 0x7) << 16)
#define VEPU_REG_IN_IMG_CTRL_ROW_LEN(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_RLC_SUM 0x0f8
#define VEPU_REG_RLC_SUM_OUT(x) (((x) & 0x007fffff) * 4)
#define VEPU_REG_SPLIT_PENALTY_4X4 0x0f8
#define VEPU_REG_VP8_SPLIT_PENALTY_4X4 (((x) & 0x1ff) << 19)
#define VEPU_REG_ADDR_REC_LUMA 0x0fc
#define VEPU_REG_ADDR_REC_CHROMA 0x100
#define VEPU_REG_CHECKPOINT(i) (0x104 + ((i) * 0x4))
#define VEPU_REG_CHECKPOINT_CHECK0(x) (((x) & 0xffff))
#define VEPU_REG_CHECKPOINT_CHECK1(x) (((x) & 0xffff) << 16)
#define VEPU_REG_CHECKPOINT_RESULT(x) \
((((x) >> (16 - 16 * ((i) & 1))) & 0xffff) * 32)
#define VEPU_REG_VP8_SEG0_QUANT_AC_Y1 0x104
#define VEPU_REG_VP8_SEG0_RND_AC_Y1(x) (((x) & 0xff) << 23)
#define VEPU_REG_VP8_SEG0_ZBIN_AC_Y1(x) (((x) & 0x1ff) << 14)
#define VEPU_REG_VP8_SEG0_QUT_AC_Y1(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_SEG0_QUANT_DC_Y2 0x108
#define VEPU_REG_VP8_SEG0_RND_DC_Y2(x) (((x) & 0xff) << 23)
#define VEPU_REG_VP8_SEG0_ZBIN_DC_Y2(x) (((x) & 0x1ff) << 14)
#define VEPU_REG_VP8_SEG0_QUT_DC_Y2(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_SEG0_QUANT_AC_Y2 0x10c
#define VEPU_REG_VP8_SEG0_RND_AC_Y2(x) (((x) & 0xff) << 23)
#define VEPU_REG_VP8_SEG0_ZBIN_AC_Y2(x) (((x) & 0x1ff) << 14)
#define VEPU_REG_VP8_SEG0_QUT_AC_Y2(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_SEG0_QUANT_DC_CHR 0x110
#define VEPU_REG_VP8_SEG0_RND_DC_CHR(x) (((x) & 0xff) << 23)
#define VEPU_REG_VP8_SEG0_ZBIN_DC_CHR(x) (((x) & 0x1ff) << 14)
#define VEPU_REG_VP8_SEG0_QUT_DC_CHR(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_SEG0_QUANT_AC_CHR 0x114
#define VEPU_REG_VP8_SEG0_RND_AC_CHR(x) (((x) & 0xff) << 23)
#define VEPU_REG_VP8_SEG0_ZBIN_AC_CHR(x) (((x) & 0x1ff) << 14)
#define VEPU_REG_VP8_SEG0_QUT_AC_CHR(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_VP8_SEG0_QUANT_DQUT 0x118
#define VEPU_REG_VP8_MV_REF_IDX1(x) (((x) & 0x03) << 26)
#define VEPU_REG_VP8_SEG0_DQUT_DC_Y2(x) (((x) & 0x1ff) << 17)
#define VEPU_REG_VP8_SEG0_DQUT_AC_Y1(x) (((x) & 0x1ff) << 8)
#define VEPU_REG_VP8_SEG0_DQUT_DC_Y1(x) (((x) & 0xff) << 0)
#define VEPU_REG_CHKPT_WORD_ERR(i) (0x118 + ((i) * 0x4))
#define VEPU_REG_CHKPT_WORD_ERR_CHK0(x) (((x) & 0xffff))
#define VEPU_REG_CHKPT_WORD_ERR_CHK1(x) (((x) & 0xffff) << 16)
#define VEPU_REG_VP8_SEG0_QUANT_DQUT_1 0x11c
#define VEPU_REG_VP8_SEGMENT_MAP_UPDATE BIT(30)
#define VEPU_REG_VP8_SEGMENT_EN BIT(29)
#define VEPU_REG_VP8_MV_REF_IDX2_EN BIT(28)
#define VEPU_REG_VP8_MV_REF_IDX2(x) (((x) & 0x03) << 26)
#define VEPU_REG_VP8_SEG0_DQUT_AC_CHR(x) (((x) & 0x1ff) << 17)
#define VEPU_REG_VP8_SEG0_DQUT_DC_CHR(x) (((x) & 0xff) << 9)
#define VEPU_REG_VP8_SEG0_DQUT_AC_Y2(x) (((x) & 0x1ff) << 0)
#define VEPU_REG_VP8_BOOL_ENC_VALUE 0x120
#define VEPU_REG_CHKPT_DELTA_QP 0x124
#define VEPU_REG_CHKPT_DELTA_QP_CHK0(x) (((x) & 0x0f) << 0)
#define VEPU_REG_CHKPT_DELTA_QP_CHK1(x) (((x) & 0x0f) << 4)
#define VEPU_REG_CHKPT_DELTA_QP_CHK2(x) (((x) & 0x0f) << 8)
#define VEPU_REG_CHKPT_DELTA_QP_CHK3(x) (((x) & 0x0f) << 12)
#define VEPU_REG_CHKPT_DELTA_QP_CHK4(x) (((x) & 0x0f) << 16)
#define VEPU_REG_CHKPT_DELTA_QP_CHK5(x) (((x) & 0x0f) << 20)
#define VEPU_REG_CHKPT_DELTA_QP_CHK6(x) (((x) & 0x0f) << 24)
#define VEPU_REG_VP8_ENC_CTRL2 0x124
#define VEPU_REG_VP8_ZERO_MV_PENALTY_FOR_REF2(x) (((x) & 0xff) << 24)
#define VEPU_REG_VP8_FILTER_SHARPNESS(x) (((x) & 0x07) << 21)
#define VEPU_REG_VP8_FILTER_LEVEL(x) (((x) & 0x3f) << 15)
#define VEPU_REG_VP8_DCT_PARTITION_CNT(x) (((x) & 0x03) << 13)
#define VEPU_REG_VP8_BOOL_ENC_VALUE_BITS(x) (((x) & 0x1f) << 8)
#define VEPU_REG_VP8_BOOL_ENC_RANGE(x) (((x) & 0xff) << 0)
#define VEPU_REG_ENC_CTRL1 0x128
#define VEPU_REG_MAD_THRESHOLD(x) (((x) & 0x3f) << 24)
#define VEPU_REG_COMPLETED_SLICES(x) (((x) & 0xff) << 16)
#define VEPU_REG_IN_IMG_CTRL_FMT(x) (((x) & 0xf) << 4)
#define VEPU_REG_IN_IMG_ROTATE_MODE(x) (((x) & 0x3) << 2)
#define VEPU_REG_SIZE_TABLE_PRESENT BIT(0)
#define VEPU_REG_INTRA_INTER_MODE 0x12c
#define VEPU_REG_INTRA16X16_MODE(x) (((x) & 0xffff) << 16)
#define VEPU_REG_INTER_MODE(x) (((x) & 0xffff) << 0)
#define VEPU_REG_ENC_CTRL2 0x130
#define VEPU_REG_PPS_INIT_QP(x) (((x) & 0x3f) << 26)
#define VEPU_REG_SLICE_FILTER_ALPHA(x) (((x) & 0xf) << 22)
#define VEPU_REG_SLICE_FILTER_BETA(x) (((x) & 0xf) << 18)
#define VEPU_REG_CHROMA_QP_OFFSET(x) (((x) & 0x1f) << 13)
#define VEPU_REG_FILTER_DISABLE BIT(5)
#define VEPU_REG_IDR_PIC_ID(x) (((x) & 0xf) << 1)
#define VEPU_REG_CONSTRAINED_INTRA_PREDICTION BIT(0)
#define VEPU_REG_ADDR_OUTPUT_STREAM 0x134
#define VEPU_REG_ADDR_OUTPUT_CTRL 0x138
#define VEPU_REG_ADDR_NEXT_PIC 0x13c
#define VEPU_REG_ADDR_MV_OUT 0x140
#define VEPU_REG_ADDR_CABAC_TBL 0x144
#define VEPU_REG_ROI1 0x148
#define VEPU_REG_ROI1_TOP_MB(x) (((x) & 0xff) << 24)
#define VEPU_REG_ROI1_BOTTOM_MB(x) (((x) & 0xff) << 16)
#define VEPU_REG_ROI1_LEFT_MB(x) (((x) & 0xff) << 8)
#define VEPU_REG_ROI1_RIGHT_MB(x) (((x) & 0xff) << 0)
#define VEPU_REG_ROI2 0x14c
#define VEPU_REG_ROI2_TOP_MB(x) (((x) & 0xff) << 24)
#define VEPU_REG_ROI2_BOTTOM_MB(x) (((x) & 0xff) << 16)
#define VEPU_REG_ROI2_LEFT_MB(x) (((x) & 0xff) << 8)
#define VEPU_REG_ROI2_RIGHT_MB(x) (((x) & 0xff) << 0)
#define VEPU_REG_STABLE_MATRIX(i) (0x150 + ((i) * 0x4))
#define VEPU_REG_STABLE_MOTION_SUM 0x174
#define VEPU_REG_STABILIZATION_OUTPUT 0x178
#define VEPU_REG_STABLE_MIN_VALUE(x) (((x) & 0xffffff) << 8)
#define VEPU_REG_STABLE_MODE_SEL(x) (((x) & 0x3) << 6)
#define VEPU_REG_STABLE_HOR_GMV(x) (((x) & 0x3f) << 0)
#define VEPU_REG_RGB2YUV_CONVERSION_COEF1 0x17c
#define VEPU_REG_RGB2YUV_CONVERSION_COEFB(x) (((x) & 0xffff) << 16)
#define VEPU_REG_RGB2YUV_CONVERSION_COEFA(x) (((x) & 0xffff) << 0)
#define VEPU_REG_RGB2YUV_CONVERSION_COEF2 0x180
#define VEPU_REG_RGB2YUV_CONVERSION_COEFE(x) (((x) & 0xffff) << 16)
#define VEPU_REG_RGB2YUV_CONVERSION_COEFC(x) (((x) & 0xffff) << 0)
#define VEPU_REG_RGB2YUV_CONVERSION_COEF3 0x184
#define VEPU_REG_RGB2YUV_CONVERSION_COEFF(x) (((x) & 0xffff) << 0)
#define VEPU_REG_RGB_MASK_MSB 0x188
#define VEPU_REG_RGB_MASK_B_MSB(x) (((x) & 0x1f) << 16)
#define VEPU_REG_RGB_MASK_G_MSB(x) (((x) & 0x1f) << 8)
#define VEPU_REG_RGB_MASK_R_MSB(x) (((x) & 0x1f) << 0)
#define VEPU_REG_MV_PENALTY 0x18c
#define VEPU_REG_1MV_PENALTY(x) (((x) & 0x3ff) << 21)
#define VEPU_REG_QMV_PENALTY(x) (((x) & 0x3ff) << 11)
#define VEPU_REG_4MV_PENALTY(x) (((x) & 0x3ff) << 1)
#define VEPU_REG_SPLIT_MV_MODE_EN BIT(0)
#define VEPU_REG_QP_VAL 0x190
#define VEPU_REG_H264_LUMA_INIT_QP(x) (((x) & 0x3f) << 26)
#define VEPU_REG_H264_QP_MAX(x) (((x) & 0x3f) << 20)
#define VEPU_REG_H264_QP_MIN(x) (((x) & 0x3f) << 14)
#define VEPU_REG_H264_CHKPT_DISTANCE(x) (((x) & 0xfff) << 0)
#define VEPU_REG_VP8_SEG0_QUANT_DC_Y1 0x190
#define VEPU_REG_VP8_SEG0_RND_DC_Y1(x) (((x) & 0xff) << 23)
#define VEPU_REG_VP8_SEG0_ZBIN_DC_Y1(x) (((x) & 0x1ff) << 14)
#define VEPU_REG_VP8_SEG0_QUT_DC_Y1(x) (((x) & 0x3fff) << 0)
#define VEPU_REG_MVC_RELATE 0x198
#define VEPU_REG_ZERO_MV_FAVOR_D2(x) (((x) & 0xf) << 20)
#define VEPU_REG_PENALTY_4X4MV(x) (((x) & 0x1ff) << 11)
#define VEPU_REG_MVC_VIEW_ID(x) (((x) & 0x7) << 8)
#define VEPU_REG_MVC_ANCHOR_PIC_FLAG BIT(7)
#define VEPU_REG_MVC_PRIORITY_ID(x) (((x) & 0x7) << 4)
#define VEPU_REG_MVC_TEMPORAL_ID(x) (((x) & 0x7) << 1)
#define VEPU_REG_MVC_INTER_VIEW_FLAG BIT(0)
#define VEPU_REG_ENCODE_START 0x19c
#define VEPU_REG_MB_HEIGHT(x) (((x) & 0x1ff) << 20)
#define VEPU_REG_MB_WIDTH(x) (((x) & 0x1ff) << 8)
#define VEPU_REG_FRAME_TYPE_INTER (0x0 << 6)
#define VEPU_REG_FRAME_TYPE_INTRA (0x1 << 6)
#define VEPU_REG_FRAME_TYPE_MVCINTER (0x2 << 6)
#define VEPU_REG_ENCODE_FORMAT_JPEG (0x2 << 4)
#define VEPU_REG_ENCODE_FORMAT_H264 (0x3 << 4)
#define VEPU_REG_ENCODE_ENABLE BIT(0)
#define VEPU_REG_MB_CTRL 0x1a0
#define VEPU_REG_MB_CNT_OUT(x) (((x) & 0xffff) << 16)
#define VEPU_REG_MB_CNT_SET(x) (((x) & 0xffff) << 0)
#define VEPU_REG_DATA_ENDIAN 0x1a4
#define VEPU_REG_INPUT_SWAP8 BIT(31)
#define VEPU_REG_INPUT_SWAP16 BIT(30)
#define VEPU_REG_INPUT_SWAP32 BIT(29)
#define VEPU_REG_OUTPUT_SWAP8 BIT(28)
#define VEPU_REG_OUTPUT_SWAP16 BIT(27)
#define VEPU_REG_OUTPUT_SWAP32 BIT(26)
#define VEPU_REG_TEST_IRQ BIT(24)
#define VEPU_REG_TEST_COUNTER(x) (((x) & 0xf) << 20)
#define VEPU_REG_TEST_REG BIT(19)
#define VEPU_REG_TEST_MEMORY BIT(18)
#define VEPU_REG_TEST_LEN(x) (((x) & 0x3ffff) << 0)
#define VEPU_REG_ENC_CTRL3 0x1a8
#define VEPU_REG_PPS_ID(x) (((x) & 0xff) << 24)
#define VEPU_REG_INTRA_PRED_MODE(x) (((x) & 0xff) << 16)
#define VEPU_REG_FRAME_NUM(x) (((x) & 0xffff) << 0)
#define VEPU_REG_ENC_CTRL4 0x1ac
#define VEPU_REG_MV_PENALTY_16X8_8X16(x) (((x) & 0x3ff) << 20)
#define VEPU_REG_MV_PENALTY_8X8(x) (((x) & 0x3ff) << 10)
#define VEPU_REG_MV_PENALTY_8X4_4X8(x) (((x) & 0x3ff) << 0)
#define VEPU_REG_ADDR_VP8_PROB_CNT 0x1b0
#define VEPU_REG_INTERRUPT 0x1b4
#define VEPU_REG_INTERRUPT_NON BIT(28)
#define VEPU_REG_MV_WRITE_EN BIT(24)
#define VEPU_REG_RECON_WRITE_DIS BIT(20)
#define VEPU_REG_INTERRUPT_SLICE_READY_EN BIT(16)
#define VEPU_REG_CLK_GATING_EN BIT(12)
#define VEPU_REG_INTERRUPT_TIMEOUT_EN BIT(10)
#define VEPU_REG_INTERRUPT_RESET BIT(9)
#define VEPU_REG_INTERRUPT_DIS_BIT BIT(8)
#define VEPU_REG_INTERRUPT_TIMEOUT BIT(6)
#define VEPU_REG_INTERRUPT_BUFFER_FULL BIT(5)
#define VEPU_REG_INTERRUPT_BUS_ERROR BIT(4)
#define VEPU_REG_INTERRUPT_FUSE BIT(3)
#define VEPU_REG_INTERRUPT_SLICE_READY BIT(2)
#define VEPU_REG_INTERRUPT_FRAME_READY BIT(1)
#define VEPU_REG_INTERRUPT_BIT BIT(0)
#define VEPU_REG_DMV_PENALTY_TBL(i) (0x1E0 + ((i) * 0x4))
#define VEPU_REG_DMV_PENALTY_TABLE_BIT(x, i) ((x) << (i) * 8)
#define VEPU_REG_DMV_Q_PIXEL_PENALTY_TBL(i) (0x260 + ((i) * 0x4))
#define VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(x, i) ((x) << (i) * 8)
/* vpu decoder register */
#define VDPU_REG_DEC_CTRL0 0x0c8 // 50
#define VDPU_REG_REF_BUF_CTRL2_REFBU2_PICID(x) (((x) & 0x1f) << 25)
#define VDPU_REG_REF_BUF_CTRL2_REFBU2_THR(x) (((x) & 0xfff) << 13)
#define VDPU_REG_CONFIG_TILED_MODE_LSB BIT(12)
#define VDPU_REG_CONFIG_DEC_ADV_PRE_DIS BIT(11)
#define VDPU_REG_CONFIG_DEC_SCMD_DIS BIT(10)
#define VDPU_REG_DEC_CTRL0_SKIP_MODE BIT(9)
#define VDPU_REG_DEC_CTRL0_FILTERING_DIS BIT(8)
#define VDPU_REG_DEC_CTRL0_PIC_FIXED_QUANT BIT(7)
#define VDPU_REG_CONFIG_DEC_LATENCY(x) (((x) & 0x3f) << 1)
#define VDPU_REG_CONFIG_TILED_MODE_MSB(x) BIT(0)
#define VDPU_REG_CONFIG_DEC_OUT_TILED_E BIT(0)
#define VDPU_REG_STREAM_LEN 0x0cc
#define VDPU_REG_DEC_CTRL3_INIT_QP(x) (((x) & 0x3f) << 25)
#define VDPU_REG_DEC_STREAM_LEN_HI BIT(24)
#define VDPU_REG_DEC_CTRL3_STREAM_LEN(x) (((x) & 0xffffff) << 0)
#define VDPU_REG_ERROR_CONCEALMENT 0x0d0
#define VDPU_REG_REF_BUF_CTRL2_APF_THRESHOLD(x) (((x) & 0x3fff) << 17)
#define VDPU_REG_ERR_CONC_STARTMB_X(x) (((x) & 0x1ff) << 8)
#define VDPU_REG_ERR_CONC_STARTMB_Y(x) (((x) & 0xff) << 0)
#define VDPU_REG_DEC_FORMAT 0x0d4
#define VDPU_REG_DEC_CTRL0_DEC_MODE(x) (((x) & 0xf) << 0)
#define VDPU_REG_DATA_ENDIAN 0x0d8
#define VDPU_REG_CONFIG_DEC_STRENDIAN_E BIT(5)
#define VDPU_REG_CONFIG_DEC_STRSWAP32_E BIT(4)
#define VDPU_REG_CONFIG_DEC_OUTSWAP32_E BIT(3)
#define VDPU_REG_CONFIG_DEC_INSWAP32_E BIT(2)
#define VDPU_REG_CONFIG_DEC_OUT_ENDIAN BIT(1)
#define VDPU_REG_CONFIG_DEC_IN_ENDIAN BIT(0)
#define VDPU_REG_INTERRUPT 0x0dc
#define VDPU_REG_INTERRUPT_DEC_TIMEOUT BIT(13)
#define VDPU_REG_INTERRUPT_DEC_ERROR_INT BIT(12)
#define VDPU_REG_INTERRUPT_DEC_PIC_INF BIT(10)
#define VDPU_REG_INTERRUPT_DEC_SLICE_INT BIT(9)
#define VDPU_REG_INTERRUPT_DEC_ASO_INT BIT(8)
#define VDPU_REG_INTERRUPT_DEC_BUFFER_INT BIT(6)
#define VDPU_REG_INTERRUPT_DEC_BUS_INT BIT(5)
#define VDPU_REG_INTERRUPT_DEC_RDY_INT BIT(4)
#define VDPU_REG_INTERRUPT_DEC_IRQ_DIS BIT(1)
#define VDPU_REG_INTERRUPT_DEC_IRQ BIT(0)
#define VDPU_REG_AXI_CTRL 0x0e0
#define VDPU_REG_AXI_DEC_SEL BIT(23)
#define VDPU_REG_CONFIG_DEC_DATA_DISC_E BIT(22)
#define VDPU_REG_PARAL_BUS_E(x) BIT(21)
#define VDPU_REG_CONFIG_DEC_MAX_BURST(x) (((x) & 0x1f) << 16)
#define VDPU_REG_DEC_CTRL0_DEC_AXI_WR_ID(x) (((x) & 0xff) << 8)
#define VDPU_REG_CONFIG_DEC_AXI_RD_ID(x) (((x) & 0xff) << 0)
#define VDPU_REG_EN_FLAGS 0x0e4
#define VDPU_REG_AHB_HLOCK_E BIT(31)
#define VDPU_REG_CACHE_E BIT(29)
#define VDPU_REG_PREFETCH_SINGLE_CHANNEL_E BIT(28)
#define VDPU_REG_INTRA_3_CYCLE_ENHANCE BIT(27)
#define VDPU_REG_INTRA_DOUBLE_SPEED BIT(26)
#define VDPU_REG_INTER_DOUBLE_SPEED BIT(25)
#define VDPU_REG_DEC_CTRL3_START_CODE_E BIT(22)
#define VDPU_REG_DEC_CTRL3_CH_8PIX_ILEAV_E BIT(21)
#define VDPU_REG_DEC_CTRL0_RLC_MODE_E BIT(20)
#define VDPU_REG_DEC_CTRL0_DIVX3_E BIT(19)
#define VDPU_REG_DEC_CTRL0_PJPEG_E BIT(18)
#define VDPU_REG_DEC_CTRL0_PIC_INTERLACE_E BIT(17)
#define VDPU_REG_DEC_CTRL0_PIC_FIELDMODE_E BIT(16)
#define VDPU_REG_DEC_CTRL0_PIC_B_E BIT(15)
#define VDPU_REG_DEC_CTRL0_PIC_INTER_E BIT(14)
#define VDPU_REG_DEC_CTRL0_PIC_TOPFIELD_E BIT(13)
#define VDPU_REG_DEC_CTRL0_FWD_INTERLACE_E BIT(12)
#define VDPU_REG_DEC_CTRL0_SORENSON_E BIT(11)
#define VDPU_REG_DEC_CTRL0_WRITE_MVS_E BIT(10)
#define VDPU_REG_DEC_CTRL0_REF_TOPFIELD_E BIT(9)
#define VDPU_REG_DEC_CTRL0_REFTOPFIRST_E BIT(8)
#define VDPU_REG_DEC_CTRL0_SEQ_MBAFF_E BIT(7)
#define VDPU_REG_DEC_CTRL0_PICORD_COUNT_E BIT(6)
#define VDPU_REG_CONFIG_DEC_TIMEOUT_E BIT(5)
#define VDPU_REG_CONFIG_DEC_CLK_GATE_E BIT(4)
#define VDPU_REG_DEC_CTRL0_DEC_OUT_DIS BIT(2)
#define VDPU_REG_REF_BUF_CTRL2_REFBU2_BUF_E BIT(1)
#define VDPU_REG_INTERRUPT_DEC_E BIT(0)
#define VDPU_REG_SOFT_RESET 0x0e8
#define VDPU_REG_PRED_FLT 0x0ec
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_0(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_1(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_2(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_ADDITIONAL_CHROMA_ADDRESS 0x0f0
#define VDPU_REG_ADDR_QTABLE 0x0f4
#define VDPU_REG_DIRECT_MV_ADDR 0x0f8
#define VDPU_REG_ADDR_DST 0x0fc
#define VDPU_REG_ADDR_STR 0x100
#define VDPU_REG_REFBUF_RELATED 0x104
#define VDPU_REG_FWD_PIC(i) (0x128 + ((i) * 0x4))
#define VDPU_REG_FWD_PIC_PINIT_RLIST_F5(x) (((x) & 0x1f) << 25)
#define VDPU_REG_FWD_PIC_PINIT_RLIST_F4(x) (((x) & 0x1f) << 20)
#define VDPU_REG_FWD_PIC_PINIT_RLIST_F3(x) (((x) & 0x1f) << 15)
#define VDPU_REG_FWD_PIC_PINIT_RLIST_F2(x) (((x) & 0x1f) << 10)
#define VDPU_REG_FWD_PIC_PINIT_RLIST_F1(x) (((x) & 0x1f) << 5)
#define VDPU_REG_FWD_PIC_PINIT_RLIST_F0(x) (((x) & 0x1f) << 0)
#define VDPU_REG_REF_PIC(i) (0x130 + ((i) * 0x4))
#define VDPU_REG_REF_PIC_REFER1_NBR(x) (((x) & 0xffff) << 16)
#define VDPU_REG_REF_PIC_REFER0_NBR(x) (((x) & 0xffff) << 0)
#define VDPU_REG_H264_ADDR_REF(i) (0x150 + ((i) * 0x4))
#define VDPU_REG_ADDR_REF_FIELD_E BIT(1)
#define VDPU_REG_ADDR_REF_TOPC_E BIT(0)
#define VDPU_REG_INITIAL_REF_PIC_LIST0 0x190
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F5(x) (((x) & 0x1f) << 25)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F4(x) (((x) & 0x1f) << 20)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F3(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F2(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F1(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F0(x) (((x) & 0x1f) << 0)
#define VDPU_REG_INITIAL_REF_PIC_LIST1 0x194
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F11(x) (((x) & 0x1f) << 25)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F10(x) (((x) & 0x1f) << 20)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F9(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F8(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F7(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F6(x) (((x) & 0x1f) << 0)
#define VDPU_REG_INITIAL_REF_PIC_LIST2 0x198
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F15(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F14(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F13(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F12(x) (((x) & 0x1f) << 0)
#define VDPU_REG_INITIAL_REF_PIC_LIST3 0x19c
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B5(x) (((x) & 0x1f) << 25)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B4(x) (((x) & 0x1f) << 20)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B3(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B2(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B1(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B0(x) (((x) & 0x1f) << 0)
#define VDPU_REG_INITIAL_REF_PIC_LIST4 0x1a0
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B11(x) (((x) & 0x1f) << 25)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B10(x) (((x) & 0x1f) << 20)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B9(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B8(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B7(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B6(x) (((x) & 0x1f) << 0)
#define VDPU_REG_INITIAL_REF_PIC_LIST5 0x1a4
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B15(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B14(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B13(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B12(x) (((x) & 0x1f) << 0)
#define VDPU_REG_INITIAL_REF_PIC_LIST6 0x1a8
#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F3(x) (((x) & 0x1f) << 15)
#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F2(x) (((x) & 0x1f) << 10)
#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F1(x) (((x) & 0x1f) << 5)
#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F0(x) (((x) & 0x1f) << 0)
#define VDPU_REG_LT_REF 0x1ac
#define VDPU_REG_VALID_REF 0x1b0
#define VDPU_REG_H264_PIC_MB_SIZE 0x1b8
#define VDPU_REG_DEC_CTRL2_CH_QP_OFFSET2(x) (((x) & 0x1f) << 22)
#define VDPU_REG_DEC_CTRL2_CH_QP_OFFSET(x) (((x) & 0x1f) << 17)
#define VDPU_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(x) (((x) & 0xff) << 9)
#define VDPU_REG_DEC_CTRL1_PIC_MB_WIDTH(x) (((x) & 0x1ff) << 0)
#define VDPU_REG_H264_CTRL 0x1bc
#define VDPU_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(x) (((x) & 0x3) << 16)
#define VDPU_REG_DEC_CTRL1_REF_FRAMES(x) (((x) & 0x1f) << 0)
#define VDPU_REG_CURRENT_FRAME 0x1c0
#define VDPU_REG_DEC_CTRL5_FILT_CTRL_PRES BIT(31)
#define VDPU_REG_DEC_CTRL5_RDPIC_CNT_PRES BIT(30)
#define VDPU_REG_DEC_CTRL4_FRAMENUM_LEN(x) (((x) & 0x1f) << 16)
#define VDPU_REG_DEC_CTRL4_FRAMENUM(x) (((x) & 0xffff) << 0)
#define VDPU_REG_REF_FRAME 0x1c4
#define VDPU_REG_DEC_CTRL5_REFPIC_MK_LEN(x) (((x) & 0x7ff) << 16)
#define VDPU_REG_DEC_CTRL5_IDR_PIC_ID(x) (((x) & 0xffff) << 0)
#define VDPU_REG_DEC_CTRL6 0x1c8
#define VDPU_REG_DEC_CTRL6_PPS_ID(x) (((x) & 0xff) << 24)
#define VDPU_REG_DEC_CTRL6_REFIDX1_ACTIVE(x) (((x) & 0x1f) << 19)
#define VDPU_REG_DEC_CTRL6_REFIDX0_ACTIVE(x) (((x) & 0x1f) << 14)
#define VDPU_REG_DEC_CTRL6_POC_LENGTH(x) (((x) & 0xff) << 0)
#define VDPU_REG_ENABLE_FLAG 0x1cc
#define VDPU_REG_DEC_CTRL5_IDR_PIC_E BIT(8)
#define VDPU_REG_DEC_CTRL4_DIR_8X8_INFER_E BIT(7)
#define VDPU_REG_DEC_CTRL4_BLACKWHITE_E BIT(6)
#define VDPU_REG_DEC_CTRL4_CABAC_E BIT(5)
#define VDPU_REG_DEC_CTRL4_WEIGHT_PRED_E BIT(4)
#define VDPU_REG_DEC_CTRL5_CONST_INTRA_E BIT(3)
#define VDPU_REG_DEC_CTRL5_8X8TRANS_FLAG_E BIT(2)
#define VDPU_REG_DEC_CTRL2_TYPE1_QUANT_E BIT(1)
#define VDPU_REG_DEC_CTRL2_FIELDPIC_FLAG_E BIT(0)
#define VDPU_REG_VP8_PIC_MB_SIZE 0x1e0
#define VDPU_REG_DEC_PIC_MB_WIDTH(x) (((x) & 0x1ff) << 23)
#define VDPU_REG_DEC_MB_WIDTH_OFF(x) (((x) & 0xf) << 19)
#define VDPU_REG_DEC_PIC_MB_HEIGHT_P(x) (((x) & 0xff) << 11)
#define VDPU_REG_DEC_MB_HEIGHT_OFF(x) (((x) & 0xf) << 7)
#define VDPU_REG_DEC_CTRL1_PIC_MB_W_EXT(x) (((x) & 0x7) << 3)
#define VDPU_REG_DEC_CTRL1_PIC_MB_H_EXT(x) (((x) & 0x7) << 0)
#define VDPU_REG_VP8_DCT_START_BIT 0x1e4
#define VDPU_REG_DEC_CTRL4_DCT1_START_BIT(x) (((x) & 0x3f) << 26)
#define VDPU_REG_DEC_CTRL4_DCT2_START_BIT(x) (((x) & 0x3f) << 20)
#define VDPU_REG_DEC_CTRL4_VC1_HEIGHT_EXT BIT(13)
#define VDPU_REG_DEC_CTRL4_BILIN_MC_E BIT(12)
#define VDPU_REG_VP8_CTRL0 0x1e8
#define VDPU_REG_DEC_CTRL2_STRM_START_BIT(x) (((x) & 0x3f) << 26)
#define VDPU_REG_DEC_CTRL2_STRM1_START_BIT(x) (((x) & 0x3f) << 18)
#define VDPU_REG_DEC_CTRL2_BOOLEAN_VALUE(x) (((x) & 0xff) << 8)
#define VDPU_REG_DEC_CTRL2_BOOLEAN_RANGE(x) (((x) & 0xff) << 0)
#define VDPU_REG_VP8_DATA_VAL 0x1f0
#define VDPU_REG_DEC_CTRL6_COEFFS_PART_AM(x) (((x) & 0xf) << 24)
#define VDPU_REG_DEC_CTRL6_STREAM1_LEN(x) (((x) & 0xffffff) << 0)
#define VDPU_REG_PRED_FLT7 0x1f4
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_1(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_2(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_3(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT8 0x1f8
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_0(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_1(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_2(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT9 0x1fc
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_3(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_0(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_1(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT10 0x200
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_2(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_3(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_BD_REF_PIC_PRED_TAP_2_M1(x) (((x) & 0x3) << 10)
#define VDPU_REG_BD_REF_PIC_PRED_TAP_2_4(x) (((x) & 0x3) << 8)
#define VDPU_REG_BD_REF_PIC_PRED_TAP_4_M1(x) (((x) & 0x3) << 6)
#define VDPU_REG_BD_REF_PIC_PRED_TAP_4_4(x) (((x) & 0x3) << 4)
#define VDPU_REG_BD_REF_PIC_PRED_TAP_6_M1(x) (((x) & 0x3) << 2)
#define VDPU_REG_BD_REF_PIC_PRED_TAP_6_4(x) (((x) & 0x3) << 0)
#define VDPU_REG_FILTER_LEVEL 0x204
#define VDPU_REG_REF_PIC_LF_LEVEL_0(x) (((x) & 0x3f) << 18)
#define VDPU_REG_REF_PIC_LF_LEVEL_1(x) (((x) & 0x3f) << 12)
#define VDPU_REG_REF_PIC_LF_LEVEL_2(x) (((x) & 0x3f) << 6)
#define VDPU_REG_REF_PIC_LF_LEVEL_3(x) (((x) & 0x3f) << 0)
#define VDPU_REG_VP8_QUANTER0 0x208
#define VDPU_REG_REF_PIC_QUANT_DELTA_0(x) (((x) & 0x1f) << 27)
#define VDPU_REG_REF_PIC_QUANT_DELTA_1(x) (((x) & 0x1f) << 22)
#define VDPU_REG_REF_PIC_QUANT_0(x) (((x) & 0x7ff) << 11)
#define VDPU_REG_REF_PIC_QUANT_1(x) (((x) & 0x7ff) << 0)
#define VDPU_REG_VP8_ADDR_REF0 0x20c
#define VDPU_REG_FILTER_MB_ADJ 0x210
#define VDPU_REG_REF_PIC_FILT_TYPE_E BIT(31)
#define VDPU_REG_REF_PIC_FILT_SHARPNESS(x) (((x) & 0x7) << 28)
#define VDPU_REG_FILT_MB_ADJ_0(x) (((x) & 0x7f) << 21)
#define VDPU_REG_FILT_MB_ADJ_1(x) (((x) & 0x7f) << 14)
#define VDPU_REG_FILT_MB_ADJ_2(x) (((x) & 0x7f) << 7)
#define VDPU_REG_FILT_MB_ADJ_3(x) (((x) & 0x7f) << 0)
#define VDPU_REG_FILTER_REF_ADJ 0x214
#define VDPU_REG_REF_PIC_ADJ_0(x) (((x) & 0x7f) << 21)
#define VDPU_REG_REF_PIC_ADJ_1(x) (((x) & 0x7f) << 14)
#define VDPU_REG_REF_PIC_ADJ_2(x) (((x) & 0x7f) << 7)
#define VDPU_REG_REF_PIC_ADJ_3(x) (((x) & 0x7f) << 0)
#define VDPU_REG_VP8_ADDR_REF2_5(i) (0x218 + ((i) * 0x4))
#define VDPU_REG_VP8_GREF_SIGN_BIAS BIT(0)
#define VDPU_REG_VP8_AREF_SIGN_BIAS BIT(0)
#define VDPU_REG_VP8_DCT_BASE(i) (0x230 + ((i) * 0x4))
#define VDPU_REG_VP8_ADDR_CTRL_PART 0x244
#define VDPU_REG_VP8_ADDR_REF1 0x250
#define VDPU_REG_VP8_SEGMENT_VAL 0x254
#define VDPU_REG_FWD_PIC1_SEGMENT_BASE(x) ((x) << 0)
#define VDPU_REG_FWD_PIC1_SEGMENT_UPD_E BIT(1)
#define VDPU_REG_FWD_PIC1_SEGMENT_E BIT(0)
#define VDPU_REG_VP8_DCT_START_BIT2 0x258
#define VDPU_REG_DEC_CTRL7_DCT3_START_BIT(x) (((x) & 0x3f) << 24)
#define VDPU_REG_DEC_CTRL7_DCT4_START_BIT(x) (((x) & 0x3f) << 18)
#define VDPU_REG_DEC_CTRL7_DCT5_START_BIT(x) (((x) & 0x3f) << 12)
#define VDPU_REG_DEC_CTRL7_DCT6_START_BIT(x) (((x) & 0x3f) << 6)
#define VDPU_REG_DEC_CTRL7_DCT7_START_BIT(x) (((x) & 0x3f) << 0)
#define VDPU_REG_VP8_QUANTER1 0x25c
#define VDPU_REG_REF_PIC_QUANT_DELTA_2(x) (((x) & 0x1f) << 27)
#define VDPU_REG_REF_PIC_QUANT_DELTA_3(x) (((x) & 0x1f) << 22)
#define VDPU_REG_REF_PIC_QUANT_2(x) (((x) & 0x7ff) << 11)
#define VDPU_REG_REF_PIC_QUANT_3(x) (((x) & 0x7ff) << 0)
#define VDPU_REG_VP8_QUANTER2 0x260
#define VDPU_REG_REF_PIC_QUANT_DELTA_4(x) (((x) & 0x1f) << 27)
#define VDPU_REG_REF_PIC_QUANT_4(x) (((x) & 0x7ff) << 11)
#define VDPU_REG_REF_PIC_QUANT_5(x) (((x) & 0x7ff) << 0)
#define VDPU_REG_PRED_FLT1 0x264
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_3(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_0(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_1(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT2 0x268
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_2(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_3(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_0(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT3 0x26c
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_1(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_2(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_3(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT4 0x270
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_0(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_1(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_2(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT5 0x274
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_3(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_0(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_1(x) (((x) & 0x3ff) << 2)
#define VDPU_REG_PRED_FLT6 0x278
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_2(x) (((x) & 0x3ff) << 22)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_3(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_0(x) (((x) & 0x3ff) << 2)
#endif /* ROCKCHIP_VPU2_REGS_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,477 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, Collabora
*
* Author: Benjamin Gaignard <benjamin.gaignard@collabora.com>
*/
#ifndef _ROCKCHIP_VPU981_REGS_H_
#define _ROCKCHIP_VPU981_REGS_H_
#include "hantro.h"
#define AV1_SWREG(nr) ((nr) * 4)
#define AV1_DEC_REG(b, s, m) \
((const struct hantro_reg) { \
.base = AV1_SWREG(b), \
.shift = s, \
.mask = m, \
})
#define AV1_REG_INTERRUPT AV1_SWREG(1)
#define AV1_REG_INTERRUPT_DEC_RDY_INT BIT(12)
#define AV1_REG_CONFIG AV1_SWREG(2)
#define AV1_REG_CONFIG_DEC_CLK_GATE_E BIT(10)
#define av1_dec_e AV1_DEC_REG(1, 0, 0x1)
#define av1_dec_abort_e AV1_DEC_REG(1, 5, 0x1)
#define av1_dec_tile_int_e AV1_DEC_REG(1, 7, 0x1)
#define av1_dec_clk_gate_e AV1_DEC_REG(2, 10, 0x1)
#define av1_dec_out_ec_bypass AV1_DEC_REG(3, 8, 0x1)
#define av1_write_mvs_e AV1_DEC_REG(3, 12, 0x1)
#define av1_filtering_dis AV1_DEC_REG(3, 14, 0x1)
#define av1_dec_out_dis AV1_DEC_REG(3, 15, 0x1)
#define av1_dec_out_ec_byte_word AV1_DEC_REG(3, 16, 0x1)
#define av1_skip_mode AV1_DEC_REG(3, 26, 0x1)
#define av1_dec_mode AV1_DEC_REG(3, 27, 0x1f)
#define av1_ref_frames AV1_DEC_REG(4, 0, 0xf)
#define av1_pic_height_in_cbs AV1_DEC_REG(4, 6, 0x1fff)
#define av1_pic_width_in_cbs AV1_DEC_REG(4, 19, 0x1fff)
#define av1_ref_scaling_enable AV1_DEC_REG(5, 0, 0x1)
#define av1_filt_level_base_gt32 AV1_DEC_REG(5, 1, 0x1)
#define av1_error_resilient AV1_DEC_REG(5, 2, 0x1)
#define av1_force_interger_mv AV1_DEC_REG(5, 3, 0x1)
#define av1_allow_intrabc AV1_DEC_REG(5, 4, 0x1)
#define av1_allow_screen_content_tools AV1_DEC_REG(5, 5, 0x1)
#define av1_reduced_tx_set_used AV1_DEC_REG(5, 6, 0x1)
#define av1_enable_dual_filter AV1_DEC_REG(5, 7, 0x1)
#define av1_enable_jnt_comp AV1_DEC_REG(5, 8, 0x1)
#define av1_allow_filter_intra AV1_DEC_REG(5, 9, 0x1)
#define av1_enable_intra_edge_filter AV1_DEC_REG(5, 10, 0x1)
#define av1_tempor_mvp_e AV1_DEC_REG(5, 11, 0x1)
#define av1_allow_interintra AV1_DEC_REG(5, 12, 0x1)
#define av1_allow_masked_compound AV1_DEC_REG(5, 13, 0x1)
#define av1_enable_cdef AV1_DEC_REG(5, 14, 0x1)
#define av1_switchable_motion_mode AV1_DEC_REG(5, 15, 0x1)
#define av1_show_frame AV1_DEC_REG(5, 16, 0x1)
#define av1_superres_is_scaled AV1_DEC_REG(5, 17, 0x1)
#define av1_allow_warp AV1_DEC_REG(5, 18, 0x1)
#define av1_disable_cdf_update AV1_DEC_REG(5, 19, 0x1)
#define av1_preskip_segid AV1_DEC_REG(5, 20, 0x1)
#define av1_delta_lf_present AV1_DEC_REG(5, 21, 0x1)
#define av1_delta_lf_multi AV1_DEC_REG(5, 22, 0x1)
#define av1_delta_lf_res_log AV1_DEC_REG(5, 23, 0x3)
#define av1_strm_start_bit AV1_DEC_REG(5, 25, 0x7f)
#define av1_stream_len AV1_DEC_REG(6, 0, 0xffffffff)
#define av1_delta_q_present AV1_DEC_REG(7, 0, 0x1)
#define av1_delta_q_res_log AV1_DEC_REG(7, 1, 0x3)
#define av1_cdef_damping AV1_DEC_REG(7, 3, 0x3)
#define av1_cdef_bits AV1_DEC_REG(7, 5, 0x3)
#define av1_apply_grain AV1_DEC_REG(7, 7, 0x1)
#define av1_num_y_points_b AV1_DEC_REG(7, 8, 0x1)
#define av1_num_cb_points_b AV1_DEC_REG(7, 9, 0x1)
#define av1_num_cr_points_b AV1_DEC_REG(7, 10, 0x1)
#define av1_overlap_flag AV1_DEC_REG(7, 11, 0x1)
#define av1_clip_to_restricted_range AV1_DEC_REG(7, 12, 0x1)
#define av1_chroma_scaling_from_luma AV1_DEC_REG(7, 13, 0x1)
#define av1_random_seed AV1_DEC_REG(7, 14, 0xffff)
#define av1_blackwhite_e AV1_DEC_REG(7, 30, 0x1)
#define av1_scaling_shift AV1_DEC_REG(8, 0, 0xf)
#define av1_bit_depth_c_minus8 AV1_DEC_REG(8, 4, 0x3)
#define av1_bit_depth_y_minus8 AV1_DEC_REG(8, 6, 0x3)
#define av1_quant_base_qindex AV1_DEC_REG(8, 8, 0xff)
#define av1_idr_pic_e AV1_DEC_REG(8, 16, 0x1)
#define av1_superres_pic_width AV1_DEC_REG(8, 17, 0x7fff)
#define av1_ref4_sign_bias AV1_DEC_REG(9, 2, 0x1)
#define av1_ref5_sign_bias AV1_DEC_REG(9, 3, 0x1)
#define av1_ref6_sign_bias AV1_DEC_REG(9, 4, 0x1)
#define av1_mf1_type AV1_DEC_REG(9, 5, 0x7)
#define av1_mf2_type AV1_DEC_REG(9, 8, 0x7)
#define av1_mf3_type AV1_DEC_REG(9, 11, 0x7)
#define av1_scale_denom_minus9 AV1_DEC_REG(9, 14, 0x7)
#define av1_last_active_seg AV1_DEC_REG(9, 17, 0x7)
#define av1_context_update_tile_id AV1_DEC_REG(9, 20, 0xfff)
#define av1_tile_transpose AV1_DEC_REG(10, 0, 0x1)
#define av1_tile_enable AV1_DEC_REG(10, 1, 0x1)
#define av1_multicore_full_width AV1_DEC_REG(10, 2, 0xff)
#define av1_num_tile_rows_8k AV1_DEC_REG(10, 10, 0x7f)
#define av1_num_tile_cols_8k AV1_DEC_REG(10, 17, 0x7f)
#define av1_multicore_tile_start_x AV1_DEC_REG(10, 24, 0xff)
#define av1_use_temporal3_mvs AV1_DEC_REG(11, 0, 0x1)
#define av1_use_temporal2_mvs AV1_DEC_REG(11, 1, 0x1)
#define av1_use_temporal1_mvs AV1_DEC_REG(11, 2, 0x1)
#define av1_use_temporal0_mvs AV1_DEC_REG(11, 3, 0x1)
#define av1_comp_pred_mode AV1_DEC_REG(11, 4, 0x3)
#define av1_high_prec_mv_e AV1_DEC_REG(11, 7, 0x1)
#define av1_mcomp_filt_type AV1_DEC_REG(11, 8, 0x7)
#define av1_multicore_expect_context_update AV1_DEC_REG(11, 11, 0x1)
#define av1_multicore_sbx_offset AV1_DEC_REG(11, 12, 0x7f)
#define av1_multicore_tile_col AV1_DEC_REG(11, 19, 0x7f)
#define av1_transform_mode AV1_DEC_REG(11, 27, 0x7)
#define av1_dec_tile_size_mag AV1_DEC_REG(11, 30, 0x3)
#define av1_seg_quant_sign AV1_DEC_REG(12, 2, 0xff)
#define av1_max_cb_size AV1_DEC_REG(12, 10, 0x7)
#define av1_min_cb_size AV1_DEC_REG(12, 13, 0x7)
#define av1_comp_pred_fixed_ref AV1_DEC_REG(12, 16, 0x7)
#define av1_multicore_tile_width AV1_DEC_REG(12, 19, 0x7f)
#define av1_pic_height_pad AV1_DEC_REG(12, 26, 0x7)
#define av1_pic_width_pad AV1_DEC_REG(12, 29, 0x7)
#define av1_segment_e AV1_DEC_REG(13, 0, 0x1)
#define av1_segment_upd_e AV1_DEC_REG(13, 1, 0x1)
#define av1_segment_temp_upd_e AV1_DEC_REG(13, 2, 0x1)
#define av1_comp_pred_var_ref0_av1 AV1_DEC_REG(13, 3, 0x7)
#define av1_comp_pred_var_ref1_av1 AV1_DEC_REG(13, 6, 0x7)
#define av1_lossless_e AV1_DEC_REG(13, 9, 0x1)
#define av1_qp_delta_ch_ac_av1 AV1_DEC_REG(13, 11, 0x7f)
#define av1_qp_delta_ch_dc_av1 AV1_DEC_REG(13, 18, 0x7f)
#define av1_qp_delta_y_dc_av1 AV1_DEC_REG(13, 25, 0x7f)
#define av1_quant_seg0 AV1_DEC_REG(14, 0, 0xff)
#define av1_filt_level_seg0 AV1_DEC_REG(14, 8, 0x3f)
#define av1_skip_seg0 AV1_DEC_REG(14, 14, 0x1)
#define av1_refpic_seg0 AV1_DEC_REG(14, 15, 0xf)
#define av1_filt_level_delta0_seg0 AV1_DEC_REG(14, 19, 0x7f)
#define av1_filt_level0 AV1_DEC_REG(14, 26, 0x3f)
#define av1_quant_seg1 AV1_DEC_REG(15, 0, 0xff)
#define av1_filt_level_seg1 AV1_DEC_REG(15, 8, 0x3f)
#define av1_skip_seg1 AV1_DEC_REG(15, 14, 0x1)
#define av1_refpic_seg1 AV1_DEC_REG(15, 15, 0xf)
#define av1_filt_level_delta0_seg1 AV1_DEC_REG(15, 19, 0x7f)
#define av1_filt_level1 AV1_DEC_REG(15, 26, 0x3f)
#define av1_quant_seg2 AV1_DEC_REG(16, 0, 0xff)
#define av1_filt_level_seg2 AV1_DEC_REG(16, 8, 0x3f)
#define av1_skip_seg2 AV1_DEC_REG(16, 14, 0x1)
#define av1_refpic_seg2 AV1_DEC_REG(16, 15, 0xf)
#define av1_filt_level_delta0_seg2 AV1_DEC_REG(16, 19, 0x7f)
#define av1_filt_level2 AV1_DEC_REG(16, 26, 0x3f)
#define av1_quant_seg3 AV1_DEC_REG(17, 0, 0xff)
#define av1_filt_level_seg3 AV1_DEC_REG(17, 8, 0x3f)
#define av1_skip_seg3 AV1_DEC_REG(17, 14, 0x1)
#define av1_refpic_seg3 AV1_DEC_REG(17, 15, 0xf)
#define av1_filt_level_delta0_seg3 AV1_DEC_REG(17, 19, 0x7f)
#define av1_filt_level3 AV1_DEC_REG(17, 26, 0x3f)
#define av1_quant_seg4 AV1_DEC_REG(18, 0, 0xff)
#define av1_filt_level_seg4 AV1_DEC_REG(18, 8, 0x3f)
#define av1_skip_seg4 AV1_DEC_REG(18, 14, 0x1)
#define av1_refpic_seg4 AV1_DEC_REG(18, 15, 0xf)
#define av1_filt_level_delta0_seg4 AV1_DEC_REG(18, 19, 0x7f)
#define av1_lr_type AV1_DEC_REG(18, 26, 0x3f)
#define av1_quant_seg5 AV1_DEC_REG(19, 0, 0xff)
#define av1_filt_level_seg5 AV1_DEC_REG(19, 8, 0x3f)
#define av1_skip_seg5 AV1_DEC_REG(19, 14, 0x1)
#define av1_refpic_seg5 AV1_DEC_REG(19, 15, 0xf)
#define av1_filt_level_delta0_seg5 AV1_DEC_REG(19, 19, 0x7f)
#define av1_lr_unit_size AV1_DEC_REG(19, 26, 0x3f)
#define av1_filt_level_delta1_seg0 AV1_DEC_REG(20, 0, 0x7f)
#define av1_filt_level_delta2_seg0 AV1_DEC_REG(20, 7, 0x7f)
#define av1_filt_level_delta3_seg0 AV1_DEC_REG(20, 14, 0x7f)
#define av1_global_mv_seg0 AV1_DEC_REG(20, 21, 0x1)
#define av1_mf1_last_offset AV1_DEC_REG(20, 22, 0x1ff)
#define av1_filt_level_delta1_seg1 AV1_DEC_REG(21, 0, 0x7f)
#define av1_filt_level_delta2_seg1 AV1_DEC_REG(21, 7, 0x7f)
#define av1_filt_level_delta3_seg1 AV1_DEC_REG(21, 14, 0x7f)
#define av1_global_mv_seg1 AV1_DEC_REG(21, 21, 0x1)
#define av1_mf1_last2_offset AV1_DEC_REG(21, 22, 0x1ff)
#define av1_filt_level_delta1_seg2 AV1_DEC_REG(22, 0, 0x7f)
#define av1_filt_level_delta2_seg2 AV1_DEC_REG(22, 7, 0x7f)
#define av1_filt_level_delta3_seg2 AV1_DEC_REG(22, 14, 0x7f)
#define av1_global_mv_seg2 AV1_DEC_REG(22, 21, 0x1)
#define av1_mf1_last3_offset AV1_DEC_REG(22, 22, 0x1ff)
#define av1_filt_level_delta1_seg3 AV1_DEC_REG(23, 0, 0x7f)
#define av1_filt_level_delta2_seg3 AV1_DEC_REG(23, 7, 0x7f)
#define av1_filt_level_delta3_seg3 AV1_DEC_REG(23, 14, 0x7f)
#define av1_global_mv_seg3 AV1_DEC_REG(23, 21, 0x1)
#define av1_mf1_golden_offset AV1_DEC_REG(23, 22, 0x1ff)
#define av1_filt_level_delta1_seg4 AV1_DEC_REG(24, 0, 0x7f)
#define av1_filt_level_delta2_seg4 AV1_DEC_REG(24, 7, 0x7f)
#define av1_filt_level_delta3_seg4 AV1_DEC_REG(24, 14, 0x7f)
#define av1_global_mv_seg4 AV1_DEC_REG(24, 21, 0x1)
#define av1_mf1_bwdref_offset AV1_DEC_REG(24, 22, 0x1ff)
#define av1_filt_level_delta1_seg5 AV1_DEC_REG(25, 0, 0x7f)
#define av1_filt_level_delta2_seg5 AV1_DEC_REG(25, 7, 0x7f)
#define av1_filt_level_delta3_seg5 AV1_DEC_REG(25, 14, 0x7f)
#define av1_global_mv_seg5 AV1_DEC_REG(25, 21, 0x1)
#define av1_mf1_altref2_offset AV1_DEC_REG(25, 22, 0x1ff)
#define av1_filt_level_delta1_seg6 AV1_DEC_REG(26, 0, 0x7f)
#define av1_filt_level_delta2_seg6 AV1_DEC_REG(26, 7, 0x7f)
#define av1_filt_level_delta3_seg6 AV1_DEC_REG(26, 14, 0x7f)
#define av1_global_mv_seg6 AV1_DEC_REG(26, 21, 0x1)
#define av1_mf1_altref_offset AV1_DEC_REG(26, 22, 0x1ff)
#define av1_filt_level_delta1_seg7 AV1_DEC_REG(27, 0, 0x7f)
#define av1_filt_level_delta2_seg7 AV1_DEC_REG(27, 7, 0x7f)
#define av1_filt_level_delta3_seg7 AV1_DEC_REG(27, 14, 0x7f)
#define av1_global_mv_seg7 AV1_DEC_REG(27, 21, 0x1)
#define av1_mf2_last_offset AV1_DEC_REG(27, 22, 0x1ff)
#define av1_cb_offset AV1_DEC_REG(28, 0, 0x1ff)
#define av1_cb_luma_mult AV1_DEC_REG(28, 9, 0xff)
#define av1_cb_mult AV1_DEC_REG(28, 17, 0xff)
#define av1_quant_delta_v_dc AV1_DEC_REG(28, 25, 0x7f)
#define av1_cr_offset AV1_DEC_REG(29, 0, 0x1ff)
#define av1_cr_luma_mult AV1_DEC_REG(29, 9, 0xff)
#define av1_cr_mult AV1_DEC_REG(29, 17, 0xff)
#define av1_quant_delta_v_ac AV1_DEC_REG(29, 25, 0x7f)
#define av1_filt_ref_adj_5 AV1_DEC_REG(30, 0, 0x7f)
#define av1_filt_ref_adj_4 AV1_DEC_REG(30, 7, 0x7f)
#define av1_filt_mb_adj_1 AV1_DEC_REG(30, 14, 0x7f)
#define av1_filt_mb_adj_0 AV1_DEC_REG(30, 21, 0x7f)
#define av1_filt_sharpness AV1_DEC_REG(30, 28, 0x7)
#define av1_quant_seg6 AV1_DEC_REG(31, 0, 0xff)
#define av1_filt_level_seg6 AV1_DEC_REG(31, 8, 0x3f)
#define av1_skip_seg6 AV1_DEC_REG(31, 14, 0x1)
#define av1_refpic_seg6 AV1_DEC_REG(31, 15, 0xf)
#define av1_filt_level_delta0_seg6 AV1_DEC_REG(31, 19, 0x7f)
#define av1_skip_ref0 AV1_DEC_REG(31, 26, 0xf)
#define av1_quant_seg7 AV1_DEC_REG(32, 0, 0xff)
#define av1_filt_level_seg7 AV1_DEC_REG(32, 8, 0x3f)
#define av1_skip_seg7 AV1_DEC_REG(32, 14, 0x1)
#define av1_refpic_seg7 AV1_DEC_REG(32, 15, 0xf)
#define av1_filt_level_delta0_seg7 AV1_DEC_REG(32, 19, 0x7f)
#define av1_skip_ref1 AV1_DEC_REG(32, 26, 0xf)
#define av1_ref0_height AV1_DEC_REG(33, 0, 0xffff)
#define av1_ref0_width AV1_DEC_REG(33, 16, 0xffff)
#define av1_ref1_height AV1_DEC_REG(34, 0, 0xffff)
#define av1_ref1_width AV1_DEC_REG(34, 16, 0xffff)
#define av1_ref2_height AV1_DEC_REG(35, 0, 0xffff)
#define av1_ref2_width AV1_DEC_REG(35, 16, 0xffff)
#define av1_ref0_ver_scale AV1_DEC_REG(36, 0, 0xffff)
#define av1_ref0_hor_scale AV1_DEC_REG(36, 16, 0xffff)
#define av1_ref1_ver_scale AV1_DEC_REG(37, 0, 0xffff)
#define av1_ref1_hor_scale AV1_DEC_REG(37, 16, 0xffff)
#define av1_ref2_ver_scale AV1_DEC_REG(38, 0, 0xffff)
#define av1_ref2_hor_scale AV1_DEC_REG(38, 16, 0xffff)
#define av1_ref3_ver_scale AV1_DEC_REG(39, 0, 0xffff)
#define av1_ref3_hor_scale AV1_DEC_REG(39, 16, 0xffff)
#define av1_ref4_ver_scale AV1_DEC_REG(40, 0, 0xffff)
#define av1_ref4_hor_scale AV1_DEC_REG(40, 16, 0xffff)
#define av1_ref5_ver_scale AV1_DEC_REG(41, 0, 0xffff)
#define av1_ref5_hor_scale AV1_DEC_REG(41, 16, 0xffff)
#define av1_ref6_ver_scale AV1_DEC_REG(42, 0, 0xffff)
#define av1_ref6_hor_scale AV1_DEC_REG(42, 16, 0xffff)
#define av1_ref3_height AV1_DEC_REG(43, 0, 0xffff)
#define av1_ref3_width AV1_DEC_REG(43, 16, 0xffff)
#define av1_ref4_height AV1_DEC_REG(44, 0, 0xffff)
#define av1_ref4_width AV1_DEC_REG(44, 16, 0xffff)
#define av1_ref5_height AV1_DEC_REG(45, 0, 0xffff)
#define av1_ref5_width AV1_DEC_REG(45, 16, 0xffff)
#define av1_ref6_height AV1_DEC_REG(46, 0, 0xffff)
#define av1_ref6_width AV1_DEC_REG(46, 16, 0xffff)
#define av1_mf2_last2_offset AV1_DEC_REG(47, 0, 0x1ff)
#define av1_mf2_last3_offset AV1_DEC_REG(47, 9, 0x1ff)
#define av1_mf2_golden_offset AV1_DEC_REG(47, 18, 0x1ff)
#define av1_qmlevel_y AV1_DEC_REG(47, 27, 0xf)
#define av1_mf2_bwdref_offset AV1_DEC_REG(48, 0, 0x1ff)
#define av1_mf2_altref2_offset AV1_DEC_REG(48, 9, 0x1ff)
#define av1_mf2_altref_offset AV1_DEC_REG(48, 18, 0x1ff)
#define av1_qmlevel_u AV1_DEC_REG(48, 27, 0xf)
#define av1_filt_ref_adj_6 AV1_DEC_REG(49, 0, 0x7f)
#define av1_filt_ref_adj_7 AV1_DEC_REG(49, 7, 0x7f)
#define av1_qmlevel_v AV1_DEC_REG(49, 14, 0xf)
#define av1_superres_chroma_step AV1_DEC_REG(51, 0, 0x3fff)
#define av1_superres_luma_step AV1_DEC_REG(51, 14, 0x3fff)
#define av1_superres_init_chroma_subpel_x AV1_DEC_REG(52, 0, 0x3fff)
#define av1_superres_init_luma_subpel_x AV1_DEC_REG(52, 14, 0x3fff)
#define av1_cdef_chroma_secondary_strength AV1_DEC_REG(53, 0, 0xffff)
#define av1_cdef_luma_secondary_strength AV1_DEC_REG(53, 16, 0xffff)
#define av1_apf_threshold AV1_DEC_REG(55, 0, 0xffff)
#define av1_apf_single_pu_mode AV1_DEC_REG(55, 30, 0x1)
#define av1_apf_disable AV1_DEC_REG(55, 31, 0x1)
#define av1_dec_max_burst AV1_DEC_REG(58, 0, 0xff)
#define av1_dec_buswidth AV1_DEC_REG(58, 8, 0x7)
#define av1_dec_multicore_mode AV1_DEC_REG(58, 11, 0x3)
#define av1_dec_axi_wd_id_e AV1_DEC_REG(58, 13, 0x1)
#define av1_dec_axi_rd_id_e AV1_DEC_REG(58, 14, 0x1)
#define av1_dec_mc_polltime AV1_DEC_REG(58, 17, 0x3ff)
#define av1_dec_mc_pollmode AV1_DEC_REG(58, 27, 0x3)
#define av1_filt_ref_adj_3 AV1_DEC_REG(59, 0, 0x7f)
#define av1_filt_ref_adj_2 AV1_DEC_REG(59, 7, 0x7f)
#define av1_filt_ref_adj_1 AV1_DEC_REG(59, 14, 0x7f)
#define av1_filt_ref_adj_0 AV1_DEC_REG(59, 21, 0x7f)
#define av1_ref0_sign_bias AV1_DEC_REG(59, 28, 0x1)
#define av1_ref1_sign_bias AV1_DEC_REG(59, 29, 0x1)
#define av1_ref2_sign_bias AV1_DEC_REG(59, 30, 0x1)
#define av1_ref3_sign_bias AV1_DEC_REG(59, 31, 0x1)
#define av1_cur_last_roffset AV1_DEC_REG(184, 0, 0x1ff)
#define av1_cur_last_offset AV1_DEC_REG(184, 9, 0x1ff)
#define av1_mf3_last_offset AV1_DEC_REG(184, 18, 0x1ff)
#define av1_ref0_gm_mode AV1_DEC_REG(184, 27, 0x3)
#define av1_cur_last2_roffset AV1_DEC_REG(185, 0, 0x1ff)
#define av1_cur_last2_offset AV1_DEC_REG(185, 9, 0x1ff)
#define av1_mf3_last2_offset AV1_DEC_REG(185, 18, 0x1ff)
#define av1_ref1_gm_mode AV1_DEC_REG(185, 27, 0x3)
#define av1_cur_last3_roffset AV1_DEC_REG(186, 0, 0x1ff)
#define av1_cur_last3_offset AV1_DEC_REG(186, 9, 0x1ff)
#define av1_mf3_last3_offset AV1_DEC_REG(186, 18, 0x1ff)
#define av1_ref2_gm_mode AV1_DEC_REG(186, 27, 0x3)
#define av1_cur_golden_roffset AV1_DEC_REG(187, 0, 0x1ff)
#define av1_cur_golden_offset AV1_DEC_REG(187, 9, 0x1ff)
#define av1_mf3_golden_offset AV1_DEC_REG(187, 18, 0x1ff)
#define av1_ref3_gm_mode AV1_DEC_REG(187, 27, 0x3)
#define av1_cur_bwdref_roffset AV1_DEC_REG(188, 0, 0x1ff)
#define av1_cur_bwdref_offset AV1_DEC_REG(188, 9, 0x1ff)
#define av1_mf3_bwdref_offset AV1_DEC_REG(188, 18, 0x1ff)
#define av1_ref4_gm_mode AV1_DEC_REG(188, 27, 0x3)
#define av1_cur_altref2_roffset AV1_DEC_REG(257, 0, 0x1ff)
#define av1_cur_altref2_offset AV1_DEC_REG(257, 9, 0x1ff)
#define av1_mf3_altref2_offset AV1_DEC_REG(257, 18, 0x1ff)
#define av1_ref5_gm_mode AV1_DEC_REG(257, 27, 0x3)
#define av1_strm_buffer_len AV1_DEC_REG(258, 0, 0xffffffff)
#define av1_strm_start_offset AV1_DEC_REG(259, 0, 0xffffffff)
#define av1_ppd_blend_exist AV1_DEC_REG(260, 21, 0x1)
#define av1_ppd_dith_exist AV1_DEC_REG(260, 23, 0x1)
#define av1_ablend_crop_e AV1_DEC_REG(260, 24, 0x1)
#define av1_pp_format_p010_e AV1_DEC_REG(260, 25, 0x1)
#define av1_pp_format_customer1_e AV1_DEC_REG(260, 26, 0x1)
#define av1_pp_crop_exist AV1_DEC_REG(260, 27, 0x1)
#define av1_pp_up_level AV1_DEC_REG(260, 28, 0x1)
#define av1_pp_down_level AV1_DEC_REG(260, 29, 0x3)
#define av1_pp_exist AV1_DEC_REG(260, 31, 0x1)
#define av1_cur_altref_roffset AV1_DEC_REG(262, 0, 0x1ff)
#define av1_cur_altref_offset AV1_DEC_REG(262, 9, 0x1ff)
#define av1_mf3_altref_offset AV1_DEC_REG(262, 18, 0x1ff)
#define av1_ref6_gm_mode AV1_DEC_REG(262, 27, 0x3)
#define av1_cdef_luma_primary_strength AV1_DEC_REG(263, 0, 0xffffffff)
#define av1_cdef_chroma_primary_strength AV1_DEC_REG(264, 0, 0xffffffff)
#define av1_axi_arqos AV1_DEC_REG(265, 0, 0xf)
#define av1_axi_awqos AV1_DEC_REG(265, 4, 0xf)
#define av1_axi_wr_ostd_threshold AV1_DEC_REG(265, 8, 0x3ff)
#define av1_axi_rd_ostd_threshold AV1_DEC_REG(265, 18, 0x3ff)
#define av1_axi_wr_4k_dis AV1_DEC_REG(265, 31, 0x1)
#define av1_128bit_mode AV1_DEC_REG(266, 5, 0x1)
#define av1_wr_shaper_bypass AV1_DEC_REG(266, 10, 0x1)
#define av1_error_conceal_e AV1_DEC_REG(266, 30, 0x1)
#define av1_superres_chroma_step_invra AV1_DEC_REG(298, 0, 0xffff)
#define av1_superres_luma_step_invra AV1_DEC_REG(298, 16, 0xffff)
#define av1_dec_alignment AV1_DEC_REG(314, 0, 0xffff)
#define av1_ext_timeout_cycles AV1_DEC_REG(318, 0, 0x7fffffff)
#define av1_ext_timeout_override_e AV1_DEC_REG(318, 31, 0x1)
#define av1_timeout_cycles AV1_DEC_REG(319, 0, 0x7fffffff)
#define av1_timeout_override_e AV1_DEC_REG(319, 31, 0x1)
#define av1_pp_out_e AV1_DEC_REG(320, 0, 0x1)
#define av1_pp_cr_first AV1_DEC_REG(320, 1, 0x1)
#define av1_pp_out_mode AV1_DEC_REG(320, 2, 0x1)
#define av1_pp_out_tile_e AV1_DEC_REG(320, 3, 0x1)
#define av1_pp_status AV1_DEC_REG(320, 4, 0xf)
#define av1_pp_in_blk_size AV1_DEC_REG(320, 8, 0x7)
#define av1_pp_out_p010_fmt AV1_DEC_REG(320, 11, 0x3)
#define av1_pp_out_rgb_fmt AV1_DEC_REG(320, 13, 0x1f)
#define av1_rgb_range_max AV1_DEC_REG(320, 18, 0xfff)
#define av1_pp_rgb_planar AV1_DEC_REG(320, 30, 0x1)
#define av1_scale_hratio AV1_DEC_REG(322, 0, 0x3ffff)
#define av1_pp_out_format AV1_DEC_REG(322, 18, 0x1f)
#define av1_ver_scale_mode AV1_DEC_REG(322, 23, 0x3)
#define av1_hor_scale_mode AV1_DEC_REG(322, 25, 0x3)
#define av1_pp_in_format AV1_DEC_REG(322, 27, 0x1f)
#define av1_pp_out_c_stride AV1_DEC_REG(329, 0, 0xffff)
#define av1_pp_out_y_stride AV1_DEC_REG(329, 16, 0xffff)
#define av1_pp_in_height AV1_DEC_REG(331, 0, 0xffff)
#define av1_pp_in_width AV1_DEC_REG(331, 16, 0xffff)
#define av1_pp_out_height AV1_DEC_REG(332, 0, 0xffff)
#define av1_pp_out_width AV1_DEC_REG(332, 16, 0xffff)
#define av1_pp1_dup_ver AV1_DEC_REG(394, 0, 0xff)
#define av1_pp1_dup_hor AV1_DEC_REG(394, 8, 0xff)
#define av1_pp0_dup_ver AV1_DEC_REG(394, 16, 0xff)
#define av1_pp0_dup_hor AV1_DEC_REG(394, 24, 0xff)
#define AV1_TILE_OUT_LU (AV1_SWREG(65))
#define AV1_REFERENCE_Y(i) (AV1_SWREG(67) + ((i) * 0x8))
#define AV1_SEGMENTATION (AV1_SWREG(81))
#define AV1_GLOBAL_MODEL (AV1_SWREG(83))
#define AV1_CDEF_COL (AV1_SWREG(85))
#define AV1_SR_COL (AV1_SWREG(89))
#define AV1_LR_COL (AV1_SWREG(91))
#define AV1_FILM_GRAIN (AV1_SWREG(95))
#define AV1_TILE_OUT_CH (AV1_SWREG(99))
#define AV1_REFERENCE_CB(i) (AV1_SWREG(101) + ((i) * 0x8))
#define AV1_TILE_OUT_MV (AV1_SWREG(133))
#define AV1_REFERENCE_MV(i) (AV1_SWREG(135) + ((i) * 0x8))
#define AV1_TILE_BASE (AV1_SWREG(167))
#define AV1_INPUT_STREAM (AV1_SWREG(169))
#define AV1_PROP_TABLE_OUT (AV1_SWREG(171))
#define AV1_PROP_TABLE (AV1_SWREG(173))
#define AV1_MC_SYNC_CURR (AV1_SWREG(175))
#define AV1_MC_SYNC_LEFT (AV1_SWREG(177))
#define AV1_DB_DATA_COL (AV1_SWREG(179))
#define AV1_DB_CTRL_COL (AV1_SWREG(183))
#define AV1_PP_OUT_LU (AV1_SWREG(326))
#define AV1_PP_OUT_CH (AV1_SWREG(328))
#endif /* _ROCKCHIP_VPU981_REGS_H_ */
@@ -0,0 +1,818 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
* Jeffy Chen <jeffy.chen@rock-chips.com>
*/
#include <linux/clk.h>
#include "hantro.h"
#include "hantro_jpeg.h"
#include "hantro_g1_regs.h"
#include "hantro_h1_regs.h"
#include "rockchip_vpu2_regs.h"
#include "rockchip_vpu981_regs.h"
#define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000)
#define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000)
#define ROCKCHIP_VPU981_MIN_SIZE 64
/*
* Supported formats.
*/
static const struct hantro_fmt rockchip_vpu_enc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_YUV420M,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUV420P,
},
{
.fourcc = V4L2_PIX_FMT_NV12M,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUV420SP,
},
{
.fourcc = V4L2_PIX_FMT_YUYV,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUYV422,
},
{
.fourcc = V4L2_PIX_FMT_UYVY,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_UYVY422,
},
{
.fourcc = V4L2_PIX_FMT_JPEG,
.codec_mode = HANTRO_MODE_JPEG_ENC,
.max_depth = 2,
.header_size = JPEG_HEADER_SIZE,
.frmsize = {
.min_width = 96,
.max_width = 8192,
.step_width = MB_DIM,
.min_height = 32,
.max_height = 8192,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_YUYV,
.codec_mode = HANTRO_MODE_NONE,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rockchip_vpu981_postproc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.postprocessed = true,
.frmsize = {
.min_width = ROCKCHIP_VPU981_MIN_SIZE,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = ROCKCHIP_VPU981_MIN_SIZE,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_NV15,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.postprocessed = true,
.frmsize = {
.min_width = ROCKCHIP_VPU981_MIN_SIZE,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = ROCKCHIP_VPU981_MIN_SIZE,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_P010,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.postprocessed = true,
.frmsize = {
.min_width = ROCKCHIP_VPU981_MIN_SIZE,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = ROCKCHIP_VPU981_MIN_SIZE,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rk3066_vpu_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.codec_mode = HANTRO_MODE_H264_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rk3288_vpu_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.codec_mode = HANTRO_MODE_H264_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rockchip_vdpu2_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.codec_mode = HANTRO_MODE_H264_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rk3399_vpu_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt rockchip_vpu981_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12_4L4,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.frmsize = {
.min_width = ROCKCHIP_VPU981_MIN_SIZE,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = ROCKCHIP_VPU981_MIN_SIZE,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_NV15_4L4,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.frmsize = {
.min_width = ROCKCHIP_VPU981_MIN_SIZE,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = ROCKCHIP_VPU981_MIN_SIZE,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_AV1_FRAME,
.codec_mode = HANTRO_MODE_AV1_DEC,
.max_depth = 2,
.frmsize = {
.min_width = ROCKCHIP_VPU981_MIN_SIZE,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = ROCKCHIP_VPU981_MIN_SIZE,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
};
static irqreturn_t rockchip_vpu1_vepu_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
enum vb2_buffer_state state;
u32 status;
status = vepu_read(vpu, H1_REG_INTERRUPT);
state = (status & H1_REG_INTERRUPT_FRAME_RDY) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
vepu_write(vpu, 0, H1_REG_INTERRUPT);
vepu_write(vpu, 0, H1_REG_AXI_CTRL);
hantro_irq_done(vpu, state);
return IRQ_HANDLED;
}
static irqreturn_t rockchip_vpu2_vdpu_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
enum vb2_buffer_state state;
u32 status;
status = vdpu_read(vpu, VDPU_REG_INTERRUPT);
state = (status & VDPU_REG_INTERRUPT_DEC_IRQ) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
vdpu_write(vpu, 0, VDPU_REG_INTERRUPT);
vdpu_write(vpu, 0, VDPU_REG_AXI_CTRL);
hantro_irq_done(vpu, state);
return IRQ_HANDLED;
}
static irqreturn_t rockchip_vpu2_vepu_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
enum vb2_buffer_state state;
u32 status;
status = vepu_read(vpu, VEPU_REG_INTERRUPT);
state = (status & VEPU_REG_INTERRUPT_FRAME_READY) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
vepu_write(vpu, 0, VEPU_REG_INTERRUPT);
vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
hantro_irq_done(vpu, state);
return IRQ_HANDLED;
}
static irqreturn_t rk3588_vpu981_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
enum vb2_buffer_state state;
u32 status;
status = vdpu_read(vpu, AV1_REG_INTERRUPT);
state = (status & AV1_REG_INTERRUPT_DEC_RDY_INT) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
vdpu_write(vpu, 0, AV1_REG_INTERRUPT);
vdpu_write(vpu, AV1_REG_CONFIG_DEC_CLK_GATE_E, AV1_REG_CONFIG);
hantro_irq_done(vpu, state);
return IRQ_HANDLED;
}
static int rk3036_vpu_hw_init(struct hantro_dev *vpu)
{
/* Bump ACLK to max. possible freq. to improve performance. */
clk_set_rate(vpu->clocks[0].clk, RK3066_ACLK_MAX_FREQ);
return 0;
}
static int rk3066_vpu_hw_init(struct hantro_dev *vpu)
{
/* Bump ACLKs to max. possible freq. to improve performance. */
clk_set_rate(vpu->clocks[0].clk, RK3066_ACLK_MAX_FREQ);
clk_set_rate(vpu->clocks[2].clk, RK3066_ACLK_MAX_FREQ);
return 0;
}
static int rockchip_vpu_hw_init(struct hantro_dev *vpu)
{
/* Bump ACLK to max. possible freq. to improve performance. */
clk_set_rate(vpu->clocks[0].clk, RK3288_ACLK_MAX_FREQ);
return 0;
}
static void rk3066_vpu_dec_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT);
vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
}
static void rockchip_vpu1_enc_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
vepu_write(vpu, H1_REG_INTERRUPT_DIS_BIT, H1_REG_INTERRUPT);
vepu_write(vpu, 0, H1_REG_ENC_CTRL);
vepu_write(vpu, 0, H1_REG_AXI_CTRL);
}
static void rockchip_vpu2_dec_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
vdpu_write(vpu, VDPU_REG_INTERRUPT_DEC_IRQ_DIS, VDPU_REG_INTERRUPT);
vdpu_write(vpu, 0, VDPU_REG_EN_FLAGS);
vdpu_write(vpu, 1, VDPU_REG_SOFT_RESET);
}
static void rockchip_vpu2_enc_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
vepu_write(vpu, VEPU_REG_INTERRUPT_DIS_BIT, VEPU_REG_INTERRUPT);
vepu_write(vpu, 0, VEPU_REG_ENCODE_START);
vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
}
/*
* Supported codec ops.
*/
static const struct hantro_codec_ops rk3036_vpu_codec_ops[] = {
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.reset = hantro_g1_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
[HANTRO_MODE_MPEG2_DEC] = {
.run = hantro_g1_mpeg2_dec_run,
.reset = hantro_g1_reset,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.reset = hantro_g1_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
};
static const struct hantro_codec_ops rk3066_vpu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = hantro_h1_jpeg_enc_run,
.reset = rockchip_vpu1_enc_reset,
.done = hantro_h1_jpeg_enc_done,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.reset = rk3066_vpu_dec_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
[HANTRO_MODE_MPEG2_DEC] = {
.run = hantro_g1_mpeg2_dec_run,
.reset = rk3066_vpu_dec_reset,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.reset = rk3066_vpu_dec_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
};
static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = hantro_h1_jpeg_enc_run,
.reset = rockchip_vpu1_enc_reset,
.done = hantro_h1_jpeg_enc_done,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.reset = hantro_g1_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
[HANTRO_MODE_MPEG2_DEC] = {
.run = hantro_g1_mpeg2_dec_run,
.reset = hantro_g1_reset,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.reset = hantro_g1_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
};
static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = rockchip_vpu2_jpeg_enc_run,
.reset = rockchip_vpu2_enc_reset,
.done = rockchip_vpu2_jpeg_enc_done,
},
[HANTRO_MODE_H264_DEC] = {
.run = rockchip_vpu2_h264_dec_run,
.reset = rockchip_vpu2_dec_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
[HANTRO_MODE_MPEG2_DEC] = {
.run = rockchip_vpu2_mpeg2_dec_run,
.reset = rockchip_vpu2_dec_reset,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = rockchip_vpu2_vp8_dec_run,
.reset = rockchip_vpu2_dec_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
};
static const struct hantro_codec_ops rk3568_vepu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = rockchip_vpu2_jpeg_enc_run,
.reset = rockchip_vpu2_enc_reset,
.done = rockchip_vpu2_jpeg_enc_done,
},
};
static const struct hantro_codec_ops rk3588_vpu981_codec_ops[] = {
[HANTRO_MODE_AV1_DEC] = {
.run = rockchip_vpu981_av1_dec_run,
.init = rockchip_vpu981_av1_dec_init,
.exit = rockchip_vpu981_av1_dec_exit,
.done = rockchip_vpu981_av1_dec_done,
},
};
/*
* VPU variant.
*/
static const struct hantro_irq rockchip_vdpu1_irqs[] = {
{ "vdpu", hantro_g1_irq },
};
static const struct hantro_irq rockchip_vpu1_irqs[] = {
{ "vepu", rockchip_vpu1_vepu_irq },
{ "vdpu", hantro_g1_irq },
};
static const struct hantro_irq rockchip_vdpu2_irqs[] = {
{ "vdpu", rockchip_vpu2_vdpu_irq },
};
static const struct hantro_irq rockchip_vpu2_irqs[] = {
{ "vepu", rockchip_vpu2_vepu_irq },
{ "vdpu", rockchip_vpu2_vdpu_irq },
};
static const struct hantro_irq rk3568_vepu_irqs[] = {
{ "vepu", rockchip_vpu2_vepu_irq },
};
static const char * const rk3066_vpu_clk_names[] = {
"aclk_vdpu", "hclk_vdpu",
"aclk_vepu", "hclk_vepu"
};
static const struct hantro_irq rk3588_vpu981_irqs[] = {
{ "vdpu", rk3588_vpu981_irq },
};
static const char * const rockchip_vpu_clk_names[] = {
"aclk", "hclk"
};
static const char * const rk3588_vpu981_vpu_clk_names[] = {
"aclk", "hclk",
};
/* VDPU1/VEPU1 */
const struct hantro_variant rk3036_vpu_variant = {
.dec_offset = 0x400,
.dec_fmts = rk3066_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rk3066_vpu_dec_fmts),
.postproc_fmts = rockchip_vpu1_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts),
.postproc_ops = &hantro_g1_postproc_ops,
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = rk3036_vpu_codec_ops,
.irqs = rockchip_vdpu1_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vdpu1_irqs),
.init = rk3036_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
/*
* Despite this variant has separate clocks for decoder and encoder,
* it's still required to enable all four of them for either decoding
* or encoding and we can't split it in separate g1/h1 variants.
*/
const struct hantro_variant rk3066_vpu_variant = {
.enc_offset = 0x0,
.enc_fmts = rockchip_vpu_enc_fmts,
.num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
.dec_offset = 0x400,
.dec_fmts = rk3066_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rk3066_vpu_dec_fmts),
.postproc_fmts = rockchip_vpu1_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts),
.postproc_ops = &hantro_g1_postproc_ops,
.codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
.codec_ops = rk3066_vpu_codec_ops,
.irqs = rockchip_vpu1_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vpu1_irqs),
.init = rk3066_vpu_hw_init,
.clk_names = rk3066_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rk3066_vpu_clk_names)
};
const struct hantro_variant rk3288_vpu_variant = {
.enc_offset = 0x0,
.enc_fmts = rockchip_vpu_enc_fmts,
.num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
.dec_offset = 0x400,
.dec_fmts = rk3288_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rk3288_vpu_dec_fmts),
.postproc_fmts = rockchip_vpu1_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts),
.postproc_ops = &hantro_g1_postproc_ops,
.codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
.codec_ops = rk3288_vpu_codec_ops,
.irqs = rockchip_vpu1_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vpu1_irqs),
.init = rockchip_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
/* VDPU2/VEPU2 */
const struct hantro_variant rk3328_vpu_variant = {
.dec_offset = 0x400,
.dec_fmts = rockchip_vdpu2_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rockchip_vdpu2_dec_fmts),
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = rk3399_vpu_codec_ops,
.irqs = rockchip_vdpu2_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vdpu2_irqs),
.init = rockchip_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names),
};
/*
* H.264 decoding explicitly disabled in RK3399.
* This ensures userspace applications use the Rockchip VDEC core,
* which has better performance.
*/
const struct hantro_variant rk3399_vpu_variant = {
.enc_offset = 0x0,
.enc_fmts = rockchip_vpu_enc_fmts,
.num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
.dec_offset = 0x400,
.dec_fmts = rk3399_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
.codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
HANTRO_VP8_DECODER,
.codec_ops = rk3399_vpu_codec_ops,
.irqs = rockchip_vpu2_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vpu2_irqs),
.init = rockchip_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
const struct hantro_variant rk3568_vepu_variant = {
.enc_offset = 0x0,
.enc_fmts = rockchip_vpu_enc_fmts,
.num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
.codec = HANTRO_JPEG_ENCODER,
.codec_ops = rk3568_vepu_codec_ops,
.irqs = rk3568_vepu_irqs,
.num_irqs = ARRAY_SIZE(rk3568_vepu_irqs),
.init = rockchip_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
const struct hantro_variant rk3568_vpu_variant = {
.dec_offset = 0x400,
.dec_fmts = rockchip_vdpu2_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rockchip_vdpu2_dec_fmts),
.codec = HANTRO_MPEG2_DECODER |
HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
.codec_ops = rk3399_vpu_codec_ops,
.irqs = rockchip_vdpu2_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vdpu2_irqs),
.init = rockchip_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
const struct hantro_variant px30_vpu_variant = {
.enc_offset = 0x0,
.enc_fmts = rockchip_vpu_enc_fmts,
.num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
.dec_offset = 0x400,
.dec_fmts = rockchip_vdpu2_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rockchip_vdpu2_dec_fmts),
.codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
.codec_ops = rk3399_vpu_codec_ops,
.irqs = rockchip_vpu2_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vpu2_irqs),
.init = rk3036_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
const struct hantro_variant rk3588_vpu981_variant = {
.dec_offset = 0x0,
.dec_fmts = rockchip_vpu981_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rockchip_vpu981_dec_fmts),
.postproc_fmts = rockchip_vpu981_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(rockchip_vpu981_postproc_fmts),
.postproc_ops = &rockchip_vpu981_postproc_ops,
.codec = HANTRO_AV1_DECODER,
.codec_ops = rk3588_vpu981_codec_ops,
.irqs = rk3588_vpu981_irqs,
.num_irqs = ARRAY_SIZE(rk3588_vpu981_irqs),
.clk_names = rk3588_vpu981_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rk3588_vpu981_vpu_clk_names)
};
@@ -0,0 +1,128 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VDEC driver
*
* Copyright (C) 2021 Collabora Ltd, Emil Velikov <emil.velikov@collabora.com>
*/
#include "hantro.h"
/*
* Supported formats.
*/
static const struct hantro_fmt sama5d4_vdec_postproc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_YUYV,
.codec_mode = HANTRO_MODE_NONE,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_HD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_HD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt sama5d4_vdec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_HD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_HD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_HD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_HD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_HD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_HD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.codec_mode = HANTRO_MODE_H264_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_HD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_HD_HEIGHT,
.step_height = MB_DIM,
},
},
};
/*
* Supported codec ops.
*/
static const struct hantro_codec_ops sama5d4_vdec_codec_ops[] = {
[HANTRO_MODE_MPEG2_DEC] = {
.run = hantro_g1_mpeg2_dec_run,
.reset = hantro_g1_reset,
.init = hantro_mpeg2_dec_init,
.exit = hantro_mpeg2_dec_exit,
},
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.reset = hantro_g1_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.reset = hantro_g1_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
};
static const struct hantro_irq sama5d4_irqs[] = {
{ "vdec", hantro_g1_irq },
};
static const char * const sama5d4_clk_names[] = { "vdec_clk" };
const struct hantro_variant sama5d4_vdec_variant = {
.dec_fmts = sama5d4_vdec_fmts,
.num_dec_fmts = ARRAY_SIZE(sama5d4_vdec_fmts),
.postproc_fmts = sama5d4_vdec_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(sama5d4_vdec_postproc_fmts),
.postproc_ops = &hantro_g1_postproc_ops,
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = sama5d4_vdec_codec_ops,
.irqs = sama5d4_irqs,
.num_irqs = ARRAY_SIZE(sama5d4_irqs),
.clk_names = sama5d4_clk_names,
.num_clocks = ARRAY_SIZE(sama5d4_clk_names),
};
@@ -0,0 +1,186 @@
// SPDX-License-Identifier: GPL-2.0
/*
* STM32MP25 video codec driver
*
* Copyright (C) STMicroelectronics SA 2024
* Authors: Hugues Fruchet <hugues.fruchet@foss.st.com>
* for STMicroelectronics.
*
*/
#include "hantro.h"
#include "hantro_jpeg.h"
#include "hantro_h1_regs.h"
/*
* Supported formats.
*/
static const struct hantro_fmt stm32mp25_vdec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
.codec_mode = HANTRO_MODE_VP8_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.codec_mode = HANTRO_MODE_H264_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_FHD_WIDTH,
.step_width = MB_DIM,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_FHD_HEIGHT,
.step_height = MB_DIM,
},
},
};
static const struct hantro_fmt stm32mp25_venc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_YUV420M,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUV420P,
},
{
.fourcc = V4L2_PIX_FMT_NV12M,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUV420SP,
},
{
.fourcc = V4L2_PIX_FMT_YUYV,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUYV422,
},
{
.fourcc = V4L2_PIX_FMT_UYVY,
.codec_mode = HANTRO_MODE_NONE,
.enc_fmt = ROCKCHIP_VPU_ENC_FMT_UYVY422,
},
{
.fourcc = V4L2_PIX_FMT_JPEG,
.codec_mode = HANTRO_MODE_JPEG_ENC,
.max_depth = 2,
.header_size = JPEG_HEADER_SIZE,
.frmsize = {
.min_width = 96,
.max_width = FMT_4K_WIDTH,
.step_width = MB_DIM,
.min_height = 96,
.max_height = FMT_4K_HEIGHT,
.step_height = MB_DIM,
},
},
};
static irqreturn_t stm32mp25_venc_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
enum vb2_buffer_state state;
u32 status;
status = vepu_read(vpu, H1_REG_INTERRUPT);
state = (status & H1_REG_INTERRUPT_FRAME_RDY) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
vepu_write(vpu, H1_REG_INTERRUPT_BIT, H1_REG_INTERRUPT);
hantro_irq_done(vpu, state);
return IRQ_HANDLED;
}
static void stm32mp25_venc_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
reset_control_reset(vpu->resets);
}
/*
* Supported codec ops.
*/
static const struct hantro_codec_ops stm32mp25_vdec_codec_ops[] = {
[HANTRO_MODE_VP8_DEC] = {
.run = hantro_g1_vp8_dec_run,
.reset = hantro_g1_reset,
.init = hantro_vp8_dec_init,
.exit = hantro_vp8_dec_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
.reset = hantro_g1_reset,
.init = hantro_h264_dec_init,
.exit = hantro_h264_dec_exit,
},
};
static const struct hantro_codec_ops stm32mp25_venc_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = hantro_h1_jpeg_enc_run,
.reset = stm32mp25_venc_reset,
.done = hantro_h1_jpeg_enc_done,
},
};
/*
* Variants.
*/
static const struct hantro_irq stm32mp25_vdec_irqs[] = {
{ "vdec", hantro_g1_irq },
};
static const char * const stm32mp25_vdec_clk_names[] = { "vdec-clk" };
const struct hantro_variant stm32mp25_vdec_variant = {
.dec_fmts = stm32mp25_vdec_fmts,
.num_dec_fmts = ARRAY_SIZE(stm32mp25_vdec_fmts),
.codec = HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
.codec_ops = stm32mp25_vdec_codec_ops,
.irqs = stm32mp25_vdec_irqs,
.num_irqs = ARRAY_SIZE(stm32mp25_vdec_irqs),
.clk_names = stm32mp25_vdec_clk_names,
.num_clocks = ARRAY_SIZE(stm32mp25_vdec_clk_names),
};
static const struct hantro_irq stm32mp25_venc_irqs[] = {
{ "venc", stm32mp25_venc_irq },
};
static const char * const stm32mp25_venc_clk_names[] = {
"venc-clk"
};
const struct hantro_variant stm32mp25_venc_variant = {
.enc_fmts = stm32mp25_venc_fmts,
.num_enc_fmts = ARRAY_SIZE(stm32mp25_venc_fmts),
.codec = HANTRO_JPEG_ENCODER,
.codec_ops = stm32mp25_venc_codec_ops,
.irqs = stm32mp25_venc_irqs,
.num_irqs = ARRAY_SIZE(stm32mp25_venc_irqs),
.clk_names = stm32mp25_venc_clk_names,
.num_clocks = ARRAY_SIZE(stm32mp25_venc_clk_names)
};
@@ -0,0 +1,129 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Allwinner Hantro G2 VPU codec driver
*
* Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@gmail.com>
*/
#include <linux/clk.h>
#include "hantro.h"
static const struct hantro_fmt sunxi_vpu_postproc_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.codec_mode = HANTRO_MODE_NONE,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 32,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
{
.fourcc = V4L2_PIX_FMT_P010,
.codec_mode = HANTRO_MODE_NONE,
.postprocessed = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 32,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
};
static const struct hantro_fmt sunxi_vpu_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12_4L4,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 32,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
{
.fourcc = V4L2_PIX_FMT_P010_4L4,
.codec_mode = HANTRO_MODE_NONE,
.match_depth = true,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 32,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
{
.fourcc = V4L2_PIX_FMT_VP9_FRAME,
.codec_mode = HANTRO_MODE_VP9_DEC,
.max_depth = 2,
.frmsize = {
.min_width = FMT_MIN_WIDTH,
.max_width = FMT_UHD_WIDTH,
.step_width = 32,
.min_height = FMT_MIN_HEIGHT,
.max_height = FMT_UHD_HEIGHT,
.step_height = 32,
},
},
};
static int sunxi_vpu_hw_init(struct hantro_dev *vpu)
{
clk_set_rate(vpu->clocks[0].clk, 300000000);
return 0;
}
static void sunxi_vpu_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
reset_control_reset(vpu->resets);
}
static const struct hantro_codec_ops sunxi_vpu_codec_ops[] = {
[HANTRO_MODE_VP9_DEC] = {
.run = hantro_g2_vp9_dec_run,
.done = hantro_g2_vp9_dec_done,
.reset = sunxi_vpu_reset,
.init = hantro_vp9_dec_init,
.exit = hantro_vp9_dec_exit,
},
};
static const struct hantro_irq sunxi_irqs[] = {
{ NULL, hantro_g2_irq },
};
static const char * const sunxi_clk_names[] = { "mod", "bus" };
const struct hantro_variant sunxi_vpu_variant = {
.dec_fmts = sunxi_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(sunxi_vpu_dec_fmts),
.postproc_fmts = sunxi_vpu_postproc_fmts,
.num_postproc_fmts = ARRAY_SIZE(sunxi_vpu_postproc_fmts),
.postproc_ops = &hantro_g2_postproc_ops,
.codec = HANTRO_VP9_DECODER,
.codec_ops = sunxi_vpu_codec_ops,
.init = sunxi_vpu_hw_init,
.irqs = sunxi_irqs,
.num_irqs = ARRAY_SIZE(sunxi_irqs),
.clk_names = sunxi_clk_names,
.num_clocks = ARRAY_SIZE(sunxi_clk_names),
.double_buffer = 1,
.legacy_regs = 1,
.late_postproc = 1,
};