/* * Rockchip VPU codec driver * * Copyright (C) 2014 Google, Inc. * Tomasz Figa * * Based on s5p-mfc driver by Samsung Electronics Co., Ltd. * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef ROCKCHIP_VPU_COMMON_H_ #define ROCKCHIP_VPU_COMMON_H_ /* Enable debugging by default for now. */ #define DEBUG #include #include #include #include #include #include #include #include #include "rockchip_vpu_hw.h" #define ROCKCHIP_VPU_NAME "rockchip-vpu" #define ROCKCHIP_VPU_DEC_NAME "rockchip-vpu-dec" #define ROCKCHIP_VPU_ENC_NAME "rockchip-vpu-enc" #define V4L2_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0x1000) #define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) #define ROCKCHIP_VPU_MAX_CTRLS 32 #define MB_DIM 16 #define MB_WIDTH(x_size) DIV_ROUND_UP(x_size, MB_DIM) #define MB_HEIGHT(y_size) DIV_ROUND_UP(y_size, MB_DIM) struct rockchip_vpu_ctx; struct rockchip_vpu_codec_ops; /** * struct rockchip_vpu_variant - information about VPU hardware variant * * @hw_id: Top 16 bits (product ID) of hardware ID register. * @name: Vpu name. * @codecs: Supported codecs of this vpu. * @enc_offset: Offset from VPU base to encoder registers. * @enc_reg_num: Number of registers of encoder block. * @dec_offset: Offset from VPU base to decoder registers. * @dec_reg_num: Number of registers of decoder block. */ struct rockchip_vpu_variant { char *name; unsigned codecs; unsigned enc_offset; unsigned enc_reg_num; unsigned dec_offset; unsigned dec_reg_num; }; /** * enum rockchip_vpu_codec_mode - codec operating mode. * @RK_VPU_CODEC_NONE: Used for RAW video formats. * @RK3288_VPU_CODEC_H264D: Rk3288 H264 decoder. * @RK3288_VPU_CODEC_H264E: Rk3288 H264 encoder. * @RK3288_VPU_CODEC_VP8D: Rk3288 VP8 decoder. * @RK3288_VPU_CODEC_VP8E: Rk3288 VP8 encoder. */ enum rockchip_vpu_codec_mode { RK_VPU_CODEC_NONE = (1 << 0), RK3288_VPU_CODEC_H264D = (1 << 1), RK3288_VPU_CODEC_H264E = (1 << 2), RK3288_VPU_CODEC_VP8D = (1 << 3), RK3288_VPU_CODEC_VP8E = (1 << 4), }; #define ROCKCHIP_VPU_DECODERS (RK3288_VPU_CODEC_H264D | RK3288_VPU_CODEC_VP8D) #define ROCKCHIP_VPU_ENCODERS (RK3288_VPU_CODEC_H264E | RK3288_VPU_CODEC_VP8E) #define RK3288_CODECS (RK_VPU_CODEC_NONE | RK3288_VPU_CODEC_H264D | RK3288_VPU_CODEC_H264E | RK3288_VPU_CODEC_VP8D | RK3288_VPU_CODEC_VP8E) /** * enum rockchip_vpu_plane - indices of planes inside a VB2 buffer. * @PLANE_Y: Plane containing luminance data (also denoted as Y). * @PLANE_CB_CR: Plane containing interleaved chrominance data (also * denoted as CbCr). * @PLANE_CB: Plane containing CB part of chrominance data. * @PLANE_CR: Plane containing CR part of chrominance data. */ enum rockchip_vpu_plane { PLANE_Y = 0, PLANE_CB_CR = 1, PLANE_CB = 1, PLANE_CR = 2, }; /** * struct rockchip_vpu_vp8e_buf_data - mode-specific per-buffer data * @dct_offset: Offset inside the buffer to DCT partition. * @hdr_size: Size of header data in the buffer. * @ext_hdr_size: Size of ext header data in the buffer. * @dct_size: Size of DCT partition in the buffer. * @header: Frame header to copy to destination buffer. */ struct rockchip_vpu_vp8e_buf_data { size_t dct_offset; size_t hdr_size; size_t ext_hdr_size; size_t dct_size; u8 header[ROCKCHIP_HEADER_SIZE]; }; /** * struct rockchip_vpu_h264e_buf_data - mode-specific per-buffer data * @sps_size: Size of sps data in the buffer. * @pps_size: Size of pps data in the buffer. * @slices_size: Size of slices data in the buffer. */ struct rockchip_vpu_h264e_buf_data { size_t sps_size; size_t pps_size; size_t slices_size; }; /** * struct rockchip_vpu_buf - Private data related to each VB2 buffer. * @vb: Pointer to related VB2 buffer. * @list: List head for queuing in buffer queue. */ struct rockchip_vpu_buf { struct vb2_v4l2_buffer vb; struct list_head list; /* Mode-specific data. */ union { struct rockchip_vpu_h264e_buf_data h264e; struct rockchip_vpu_vp8e_buf_data vp8e; }; }; /** * enum rockchip_vpu_state - bitwise flags indicating hardware state. * @VPU_RUNNING: The hardware has been programmed for operation * and is running at the moment. * @VPU_SUSPENDED: System is entering sleep state and no more runs * should be executed on hardware. */ enum rockchip_vpu_state { VPU_RUNNING = BIT(0), VPU_SUSPENDED = BIT(1), }; /** * struct rockchip_vpu_dev - driver data * @v4l2_dev: V4L2 device to register video devices for. * @vfd_dec: Video device for decoder. * @vfd_enc: Video device for encoder. * @pdev: Pointer to VPU platform device. * @dev: Pointer to device for convenient logging using * dev_ macros. * @alloc_ctx: VB2 allocator context * (for allocations without kernel mapping). * @alloc_ctx_vm: VB2 allocator context * (for allocations with kernel mapping). * @aclk: Handle of ACLK clock. * @hclk: Handle of HCLK clock. * @base: Mapped address of VPU registers. * @enc_base: Mapped address of VPU encoder register for convenience. * @dec_base: Mapped address of VPU decoder register for convenience. * @mapping: DMA IOMMU mapping. * @domain: DMA IOMMU domain. * @vpu_mutex: Mutex to synchronize V4L2 calls. * @irqlock: Spinlock to synchronize access to data structures * shared with interrupt handlers. * @state: Device state. * @ready_ctxs: List of contexts ready to run. * @variant: Hardware variant-specfic parameters. * @current_ctx: Context being currently processed by hardware. * @run_wq: Wait queue to wait for run completion. * @watchdog_work: Delayed work for hardware timeout handling. * @dummy_encode_ctx: Context used to run dummy frame encoding to initialize * encoder hardware state. * @dummy_encode_src: Source buffers used for dummy frame encoding. * @dummy_encode_dst: Desintation buffer used for dummy frame encoding. * @was_decoding: Indicates whether last run context was a decoder. */ struct rockchip_vpu_dev { struct v4l2_device v4l2_dev; struct video_device *vfd_dec; struct video_device *vfd_enc; struct platform_device *pdev; struct device *dev; void *alloc_ctx; void *alloc_ctx_vm; struct clk *aclk; struct clk *hclk; void __iomem *base; void __iomem *enc_base; void __iomem *dec_base; struct dma_iommu_mapping *mapping; struct iommu_domain *domain; struct mutex vpu_mutex; /* video_device lock */ spinlock_t irqlock; unsigned long state; struct list_head ready_ctxs; const struct rockchip_vpu_variant *variant; struct rockchip_vpu_ctx *current_ctx; wait_queue_head_t run_wq; struct delayed_work watchdog_work; struct rockchip_vpu_ctx *dummy_encode_ctx; struct rockchip_vpu_aux_buf dummy_encode_src[VIDEO_MAX_PLANES]; struct rockchip_vpu_aux_buf dummy_encode_dst; bool was_decoding; }; /** * struct rockchip_vpu_run_ops - per context operations on run data. * @prepare_run: Called when the context was selected for running * to prepare operating mode specific data. * @run_done: Called when hardware completed the run to collect * operating mode specific data from hardware and * finalize the processing. */ struct rockchip_vpu_run_ops { void (*prepare_run)(struct rockchip_vpu_ctx *); void (*run_done)(struct rockchip_vpu_ctx *, enum vb2_buffer_state); }; /** * struct rockchip_vpu_vp8e_run - per-run data specific to VP8 encoding. * @reg_params: Pointer to a buffer containing register values prepared * by user space. */ struct rockchip_vpu_vp8e_run { const struct rockchip_reg_params *reg_params; }; /** * struct rockchip_vpu_vp8d_run - per-run data specific to VP8 decoding. * @frame_hdr: Pointer to a buffer containing per-run frame data which * is needed by setting vpu register. */ struct rockchip_vpu_vp8d_run { const struct v4l2_ctrl_vp8_frame_hdr *frame_hdr; }; /** * struct rockchip_vpu_h264d_run - per-run data specific to H264 decoding. * @sps: Pointer to a buffer containing H264 SPS. * @pps: Pointer to a buffer containing H264 PPS. * @scaling_matrix: Pointer to a buffer containing scaling matrix. * @slice_param: Pointer to a buffer containing slice parameters array. * @decode_param: Pointer to a buffer containing decode parameters. * @dpb: Array of DPB entries reordered to keep POC order. * @dpb_map: Map of indices used in ref_pic_list_* into indices to * reordered DPB array. */ struct rockchip_vpu_h264d_run { const struct v4l2_ctrl_h264_sps *sps; const struct v4l2_ctrl_h264_pps *pps; const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; const struct v4l2_ctrl_h264_slice_param *slice_param; const struct v4l2_ctrl_h264_decode_param *decode_param; struct v4l2_h264_dpb_entry dpb[16]; u8 dpb_map[16]; }; /* struct for assemble bitstream */ struct stream_s { u8 *buffer; /* point to first byte of stream */ u8 *stream; /* Pointer to next byte of stream */ u32 size; /* Byte size of stream buffer */ u32 byte_cnt; /* Byte counter */ u32 bit_cnt; /* Bit counter */ u32 byte_buffer; /* Byte buffer */ u32 buffered_bits; /* Amount of bits in byte buffer, [0-7] */ s32 overflow; /* This will signal a buffer overflow */ }; void stream_put_bits(struct stream_s *buffer, s32 value, s32 number, const char *name); void stream_buffer_reset(struct stream_s *buffer); int stream_buffer_init(struct stream_s *buffer, u8 *stream, s32 size); /** * struct rockchip_vpu_h264e_run - per-run data specific to H264 encoding. */ struct rockchip_vpu_h264e_run { const struct rockchip_reg_params *reg_params; struct stream_s sps; struct stream_s pps; u32 hw_write_offset; }; /** * struct rockchip_vpu_run - per-run data for hardware code. * @src: Source buffer to be processed. * @dst: Destination buffer to be processed. * @priv_src: Hardware private source buffer. * @priv_dst: Hardware private destination buffer. */ struct rockchip_vpu_run { /* Generic for more than one operating mode. */ struct rockchip_vpu_buf *src; struct rockchip_vpu_buf *dst; struct rockchip_vpu_aux_buf priv_src; struct rockchip_vpu_aux_buf priv_dst; /* Specific for particular operating modes. */ union { struct rockchip_vpu_vp8e_run vp8e; struct rockchip_vpu_vp8d_run vp8d; struct rockchip_vpu_h264d_run h264d; struct rockchip_vpu_h264e_run h264e; /* Other modes will need different data. */ }; }; /** * struct rockchip_vpu_ctx - Context (instance) private data. * * @dev: VPU driver data to which the context belongs. * @fh: V4L2 file handler. * * @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. * * @vq_src: Videobuf2 source queue. * @src_queue: Internal source buffer queue. * @src_crop: Configured source crop rectangle (encoder-only). * @vq_dst: Videobuf2 destination queue * @dst_queue: Internal destination buffer queue. * @dst_bufs: Private buffers wrapping VB2 buffers (destination). * * @ctrls: Array containing pointer to registered controls. * @ctrl_handler: Control handler used to register controls. * @num_ctrls: Number of registered controls. * * @list: List head for queue of ready contexts. * * @run: Structure containing data about currently scheduled * processing run. * @run_ops: Set of operations related to currently scheduled run. * @hw: Structure containing hardware-related context. */ struct rockchip_vpu_ctx { struct rockchip_vpu_dev *dev; struct v4l2_fh fh; /* Format info */ struct rockchip_vpu_fmt *vpu_src_fmt; struct v4l2_pix_format_mplane src_fmt; struct rockchip_vpu_fmt *vpu_dst_fmt; struct v4l2_pix_format_mplane dst_fmt; /* VB2 queue data */ struct vb2_queue vq_src; struct list_head src_queue; struct v4l2_rect src_crop; struct vb2_queue vq_dst; struct list_head dst_queue; struct vb2_buffer *dst_bufs[VIDEO_MAX_FRAME]; /* Controls */ struct v4l2_ctrl *ctrls[ROCKCHIP_VPU_MAX_CTRLS]; struct v4l2_ctrl_handler ctrl_handler; unsigned num_ctrls; /* Various runtime data */ struct list_head list; struct rockchip_vpu_run run; const struct rockchip_vpu_run_ops *run_ops; struct rockchip_vpu_hw_ctx hw; }; /** * struct rockchip_vpu_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 rockchip_vpu_codec_mode. * @num_planes: Number of planes used by this format. * @depth: Depth of each plane in bits per pixel. * @enc_fmt: Format identifier for encoder registers. */ struct rockchip_vpu_fmt { char *name; u32 fourcc; enum rockchip_vpu_codec_mode codec_mode; int num_planes; u8 depth[VIDEO_MAX_PLANES]; enum rockchip_vpu_enc_fmt enc_fmt; }; /** * struct rockchip_vpu_control - information about controls to be registered. * @id: Control ID. * @type: Type of the control. * @name: Human readable name of the control. * @minimum: Minimum value of the control. * @maximum: Maximum value of the control. * @step: Control value increase step. * @menu_skip_mask: Mask of invalid menu positions. * @default_value: Initial value of the control. * @max_stores: Maximum number of configration stores. * @dims: Size of each dimension of compound control. * @elem_size: Size of individual element of compound control. * @is_volatile: Control is volatile. * @is_read_only: Control is read-only. * @can_store: Control uses configuration stores. * * See also struct v4l2_ctrl_config. */ struct rockchip_vpu_control { u32 id; enum v4l2_ctrl_type type; const char *name; s32 minimum; s32 maximum; s32 step; u32 menu_skip_mask; s32 default_value; s32 max_stores; u32 dims[V4L2_CTRL_MAX_DIMS]; u32 elem_size; bool is_volatile:1; bool is_read_only:1; bool can_store:1; }; /* Logging helpers */ /** * 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 debug; #define vpu_debug(level, fmt, args...) \ do { \ if (debug & BIT(level)) \ pr_debug("%s:%d: " fmt, \ __func__, __LINE__, ##args); \ } while (0) #define vpu_debug_enter() vpu_debug(5, "enter\n") #define vpu_debug_leave() vpu_debug(5, "leave\n") #define vpu_err(fmt, args...) \ pr_err("%s:%d: " fmt, __func__, __LINE__, ##args) static inline char *fmt2str(u32 fmt, char *str) { char a = fmt & 0xFF; char b = (fmt >> 8) & 0xFF; char c = (fmt >> 16) & 0xFF; char d = (fmt >> 24) & 0xFF; sprintf(str, "%c%c%c%c", a, b, c, d); return str; } /* Structure access helpers. */ static inline struct rockchip_vpu_ctx *fh_to_ctx(struct v4l2_fh *fh) { return container_of(fh, struct rockchip_vpu_ctx, fh); } static inline struct rockchip_vpu_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) { return container_of(ctrl->handler, struct rockchip_vpu_ctx, ctrl_handler); } static inline struct rockchip_vpu_buf *vb_to_buf(struct vb2_buffer *vb) { return container_of(to_vb2_v4l2_buffer(vb), struct rockchip_vpu_buf, vb); } static inline bool rockchip_vpu_ctx_is_encoder(struct rockchip_vpu_ctx *ctx) { return ctx->vpu_dst_fmt->codec_mode != RK_VPU_CODEC_NONE; } static inline bool rockchip_vpu_ctx_is_dummy_encode(struct rockchip_vpu_ctx *ctx) { struct rockchip_vpu_dev *dev = ctx->dev; return ctx == dev->dummy_encode_ctx; } static inline bool rockchip_vpu_dev_codec_support(struct rockchip_vpu_dev *dev, enum rockchip_vpu_codec_mode codec_mode) { return !!(codec_mode & dev->variant->codecs); } int rockchip_vpu_ctrls_setup(struct rockchip_vpu_ctx *ctx, const struct v4l2_ctrl_ops *ctrl_ops, struct rockchip_vpu_control *controls, unsigned num_ctrls, const char *const *(*get_menu)(u32)); void rockchip_vpu_ctrls_delete(struct rockchip_vpu_ctx *ctx); void rockchip_vpu_try_context(struct rockchip_vpu_dev *dev, struct rockchip_vpu_ctx *ctx); void rockchip_vpu_run_done(struct rockchip_vpu_ctx *ctx, enum vb2_buffer_state result); int rockchip_vpu_aux_buf_alloc(struct rockchip_vpu_dev *vpu, struct rockchip_vpu_aux_buf *buf, size_t size); void rockchip_vpu_aux_buf_free(struct rockchip_vpu_dev *vpu, struct rockchip_vpu_aux_buf *buf); /* Register accessors. */ static inline void vepu_write_relaxed(struct rockchip_vpu_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "MARK: set reg[%03d]: %08x\n", reg / 4, val); writel_relaxed(val, vpu->enc_base + reg); } static inline void vepu_write(struct rockchip_vpu_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "MARK: set reg[%03d]: %08x\n", reg / 4, val); writel(val, vpu->enc_base + reg); } static inline u32 vepu_read(struct rockchip_vpu_dev *vpu, u32 reg) { u32 val = readl(vpu->enc_base + reg); vpu_debug(6, "MARK: get reg[%03d]: %08x\n", reg / 4, val); return val; } static inline void vdpu_write_relaxed(struct rockchip_vpu_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "MARK: set reg[%03d]: %08x\n", reg / 4, val); writel_relaxed(val, vpu->dec_base + reg); } static inline void vdpu_write(struct rockchip_vpu_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "MARK: set reg[%03d]: %08x\n", reg / 4, val); writel(val, vpu->dec_base + reg); } static inline u32 vdpu_read(struct rockchip_vpu_dev *vpu, u32 reg) { u32 val = readl(vpu->dec_base + reg); vpu_debug(6, "MARK: get reg[%03d]: %08x\n", reg / 4, val); return val; } #endif /* ROCKCHIP_VPU_COMMON_H_ */