| /* |
| * Rockchip RK3288 VPU codec driver |
| * |
| * Copyright (C) 2014 Google, Inc. |
| * Tomasz Figa <tfiga@chromium.org> |
| * |
| * 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 RK3288_VPU_COMMON_H_ |
| #define RK3288_VPU_COMMON_H_ |
| |
| /* Enable debugging by default for now. */ |
| #define DEBUG |
| |
| #include <linux/platform_device.h> |
| #include <linux/videodev2.h> |
| #include <linux/wait.h> |
| |
| #include <media/v4l2-ctrls.h> |
| #include <media/v4l2-device.h> |
| #include <media/v4l2-ioctl.h> |
| #include <media/videobuf2-core.h> |
| #include <media/videobuf2-dma-contig.h> |
| |
| #include "rk3288_vpu_hw.h" |
| |
| #define RK3288_VPU_NAME "rk3288-vpu" |
| #define RK3288_VPU_DEC_NAME "rk3288-vpu-dec" |
| #define RK3288_VPU_ENC_NAME "rk3288-vpu-enc" |
| |
| #define V4L2_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0x1000) |
| |
| #define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) |
| |
| #define RK3288_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 rk3288_vpu_variant; |
| struct rk3288_vpu_ctx; |
| struct rk3288_vpu_codec_ops; |
| |
| /** |
| * enum rk3288_vpu_codec_mode - codec operating mode. |
| * @RK_VPU_CODEC_NONE: No operating mode. Used for RAW video formats. |
| * @RK_VPU_CODEC_H264D: H264 decoder. |
| * @RK_VPU_CODEC_VP8D: VP8 decoder. |
| * @RK_VPU_CODEC_H264E: H264 encoder. |
| * @RK_VPU_CODEC_VP8E: VP8 encoder. |
| */ |
| enum rk3288_vpu_codec_mode { |
| RK_VPU_CODEC_NONE = -1, |
| RK_VPU_CODEC_H264D, |
| RK_VPU_CODEC_VP8D, |
| RK_VPU_CODEC_H264E, |
| RK_VPU_CODEC_VP8E |
| }; |
| |
| /** |
| * enum rk3288_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 rk3288_vpu_plane { |
| PLANE_Y = 0, |
| PLANE_CB_CR = 1, |
| PLANE_CB = 1, |
| PLANE_CR = 2, |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_vpu_vp8e_buf_data { |
| size_t dct_offset; |
| size_t hdr_size; |
| size_t ext_hdr_size; |
| size_t dct_size; |
| u8 header[RK3288_HEADER_SIZE]; |
| }; |
| |
| /** |
| * struct rk3288_vpu_buf - Private data related to each VB2 buffer. |
| * @list: List head for queuing in buffer queue. |
| * @b: Pointer to related VB2 buffer. |
| * @flags: Buffer state. See enum rk3288_vpu_buf_flags. |
| */ |
| struct rk3288_vpu_buf { |
| struct vb2_buffer b; |
| struct list_head list; |
| |
| /* Mode-specific data. */ |
| union { |
| struct rk3288_vpu_vp8e_buf_data vp8e; |
| }; |
| }; |
| |
| /** |
| * enum rk3288_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 rk3288_vpu_state { |
| VPU_RUNNING = BIT(0), |
| VPU_SUSPENDED = BIT(1), |
| }; |
| |
| /** |
| * struct rk3288_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_vcodec: Handle of ACLK clock. |
| * @hclk_vcodec: 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. |
| * @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 rk3288_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_vcodec; |
| struct clk *hclk_vcodec; |
| void __iomem *base; |
| void __iomem *enc_base; |
| void __iomem *dec_base; |
| struct dma_iommu_mapping *mapping; |
| |
| struct mutex vpu_mutex; /* video_device lock */ |
| spinlock_t irqlock; |
| unsigned long state; |
| struct list_head ready_ctxs; |
| const struct rk3288_vpu_variant *variant; |
| struct rk3288_vpu_ctx *current_ctx; |
| wait_queue_head_t run_wq; |
| struct delayed_work watchdog_work; |
| struct rk3288_vpu_ctx *dummy_encode_ctx; |
| struct rk3288_vpu_aux_buf dummy_encode_src[VIDEO_MAX_PLANES]; |
| struct rk3288_vpu_aux_buf dummy_encode_dst; |
| bool was_decoding; |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_vpu_run_ops { |
| void (*prepare_run)(struct rk3288_vpu_ctx *); |
| void (*run_done)(struct rk3288_vpu_ctx *, enum vb2_buffer_state); |
| }; |
| |
| /** |
| * struct rk3288_vpu_vp8e_run - per-run data specific to VP8 encoding. |
| * @reg_params: Pointer to a buffer containing register values prepared |
| * by user space. |
| */ |
| struct rk3288_vpu_vp8e_run { |
| const struct rk3288_vp8e_reg_params *reg_params; |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_vpu_vp8d_run { |
| const struct v4l2_ctrl_vp8_frame_hdr *frame_hdr; |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_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 rk3288_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 rk3288_vpu_run { |
| /* Generic for more than one operating mode. */ |
| struct rk3288_vpu_buf *src; |
| struct rk3288_vpu_buf *dst; |
| |
| struct rk3288_vpu_aux_buf priv_src; |
| struct rk3288_vpu_aux_buf priv_dst; |
| |
| /* Specific for particular operating modes. */ |
| union { |
| struct rk3288_vpu_vp8e_run vp8e; |
| struct rk3288_vpu_vp8d_run vp8d; |
| struct rk3288_vpu_h264d_run h264d; |
| /* Other modes will need different data. */ |
| }; |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_vpu_ctx { |
| struct rk3288_vpu_dev *dev; |
| struct v4l2_fh fh; |
| |
| /* Format info */ |
| struct rk3288_vpu_fmt *vpu_src_fmt; |
| struct v4l2_pix_format_mplane src_fmt; |
| struct rk3288_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[RK3288_VPU_MAX_CTRLS]; |
| struct v4l2_ctrl_handler ctrl_handler; |
| unsigned num_ctrls; |
| |
| /* Various runtime data */ |
| struct list_head list; |
| |
| struct rk3288_vpu_run run; |
| const struct rk3288_vpu_run_ops *run_ops; |
| struct rk3288_vpu_hw_ctx hw; |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_vpu_codec_mode. |
| * @num_cplanes: Number of planes color planes (for raw formats). |
| * @num_mplanes: Number of memory planes (buffers). |
| * @depth: Depth of each plane in bits per pixel. |
| * @h_subsampling: Horizontal subsampling factor |
| * @v_subsampling: Vertical subsampling factor |
| * @enc_fmt: Format identifier for encoder registers. |
| */ |
| struct rk3288_vpu_fmt { |
| char *name; |
| u32 fourcc; |
| enum rk3288_vpu_codec_mode codec_mode; |
| int num_mplanes; |
| int num_cplanes; |
| u8 depth[VIDEO_MAX_PLANES]; |
| u8 h_subsampling[VIDEO_MAX_PLANES]; |
| u8 v_subsampling[VIDEO_MAX_PLANES]; |
| enum rk3288_vpu_enc_fmt enc_fmt; |
| }; |
| |
| /** |
| * struct rk3288_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 rk3288_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 rk3288_vpu_ctx *fh_to_ctx(struct v4l2_fh *fh) |
| { |
| return container_of(fh, struct rk3288_vpu_ctx, fh); |
| } |
| |
| static inline struct rk3288_vpu_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) |
| { |
| return container_of(ctrl->handler, struct rk3288_vpu_ctx, ctrl_handler); |
| } |
| |
| static inline struct rk3288_vpu_buf *vb_to_buf(struct vb2_buffer *vb) |
| { |
| return container_of(vb, struct rk3288_vpu_buf, b); |
| } |
| |
| static inline bool rk3288_vpu_ctx_is_encoder(struct rk3288_vpu_ctx *ctx) |
| { |
| return ctx->vpu_dst_fmt->codec_mode != RK_VPU_CODEC_NONE; |
| } |
| |
| static inline bool rk3288_vpu_ctx_is_dummy_encode(struct rk3288_vpu_ctx *ctx) |
| { |
| struct rk3288_vpu_dev *dev = ctx->dev; |
| |
| return ctx == dev->dummy_encode_ctx; |
| } |
| |
| void rk3288_vpu_update_planes(struct rk3288_vpu_fmt *fmt, |
| struct v4l2_pix_format_mplane *pix_fmt_mp); |
| int rk3288_vpu_ctrls_setup(struct rk3288_vpu_ctx *ctx, |
| const struct v4l2_ctrl_ops *ctrl_ops, |
| struct rk3288_vpu_control *controls, |
| unsigned num_ctrls, |
| const char *const *(*get_menu)(u32)); |
| void rk3288_vpu_ctrls_delete(struct rk3288_vpu_ctx *ctx); |
| |
| void rk3288_vpu_try_context(struct rk3288_vpu_dev *dev, |
| struct rk3288_vpu_ctx *ctx); |
| |
| void rk3288_vpu_run_done(struct rk3288_vpu_ctx *ctx, |
| enum vb2_buffer_state result); |
| |
| int rk3288_vpu_aux_buf_alloc(struct rk3288_vpu_dev *vpu, |
| struct rk3288_vpu_aux_buf *buf, size_t size); |
| void rk3288_vpu_aux_buf_free(struct rk3288_vpu_dev *vpu, |
| struct rk3288_vpu_aux_buf *buf); |
| |
| /* Register accessors. */ |
| static inline void vepu_write_relaxed(struct rk3288_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 rk3288_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 rk3288_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 rk3288_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 rk3288_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 rk3288_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 /* RK3288_VPU_COMMON_H_ */ |