/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Coda multi-standard codec IP * * Copyright (C) 2012 Vista Silicon S.L. * Javier Martin, * Xavier Duret * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix */ #ifndef __CODA_H__ #define __CODA_H__ #include #include #include #include #include #include #include #include #include #include #include #include "coda_regs.h" #define CODA_MAX_FRAMEBUFFERS 19 #define FMO_SLICE_SAVE_BUF_SIZE (32) /* * This control allows applications to read the per-stream * (i.e. per-context) Macroblocks Error Count. This value * is CODA specific. */ #define V4L2_CID_CODA_MB_ERR_CNT (V4L2_CID_USER_CODA_BASE + 0) enum { V4L2_M2M_SRC = 0, V4L2_M2M_DST = 1, }; enum coda_inst_type { CODA_INST_ENCODER, CODA_INST_DECODER, }; enum coda_product { CODA_DX6 = 0xf001, CODA_HX4 = 0xf00a, CODA_7541 = 0xf012, CODA_960 = 0xf020, }; struct coda_video_device; struct coda_devtype { char *firmware[3]; enum coda_product product; const struct coda_codec *codecs; unsigned int num_codecs; const struct coda_video_device **vdevs; unsigned int num_vdevs; size_t workbuf_size; size_t tempbuf_size; size_t iram_size; }; struct coda_aux_buf { void *vaddr; dma_addr_t paddr; u32 size; struct debugfs_blob_wrapper blob; struct dentry *dentry; }; struct coda_dev { struct v4l2_device v4l2_dev; struct video_device vfd[6]; struct device *dev; const struct coda_devtype *devtype; int firmware; struct vdoa_data *vdoa; void __iomem *regs_base; struct clk *clk_per; struct clk *clk_ahb; struct reset_control *rstc; struct coda_aux_buf codebuf; struct coda_aux_buf tempbuf; struct coda_aux_buf workbuf; struct gen_pool *iram_pool; struct coda_aux_buf iram; struct mutex dev_mutex; struct mutex coda_mutex; struct workqueue_struct *workqueue; struct v4l2_m2m_dev *m2m_dev; struct ida ida; struct dentry *debugfs_root; struct ratelimit_state mb_err_rs; }; struct coda_codec { u32 mode; u32 src_fourcc; u32 dst_fourcc; u32 max_w; u32 max_h; }; struct coda_huff_tab; struct coda_params { u8 rot_mode; u8 h264_intra_qp; u8 h264_inter_qp; u8 h264_min_qp; u8 h264_max_qp; u8 h264_disable_deblocking_filter_idc; s8 h264_slice_alpha_c0_offset_div2; s8 h264_slice_beta_offset_div2; bool h264_constrained_intra_pred_flag; s8 h264_chroma_qp_index_offset; u8 h264_profile_idc; u8 h264_level_idc; u8 mpeg2_profile_idc; u8 mpeg2_level_idc; u8 mpeg4_intra_qp; u8 mpeg4_inter_qp; u8 gop_size; int intra_refresh; enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling; u8 jpeg_quality; u8 jpeg_restart_interval; u8 *jpeg_qmat_tab[3]; int jpeg_qmat_index[3]; int jpeg_huff_dc_index[3]; int jpeg_huff_ac_index[3]; u32 *jpeg_huff_data; struct coda_huff_tab *jpeg_huff_tab; int codec_mode; int codec_mode_aux; enum v4l2_mpeg_video_multi_slice_mode slice_mode; u32 framerate; u16 bitrate; u16 vbv_delay; u32 vbv_size; u32 slice_max_bits; u32 slice_max_mb; bool force_ipicture; bool gop_size_changed; bool bitrate_changed; bool framerate_changed; bool h264_intra_qp_changed; bool intra_refresh_changed; bool slice_mode_changed; bool frame_rc_enable; bool mb_rc_enable; }; struct coda_buffer_meta { struct list_head list; u32 sequence; struct v4l2_timecode timecode; u64 timestamp; unsigned int start; unsigned int end; bool last; }; /* Per-queue, driver-specific private data */ struct coda_q_data { unsigned int width; unsigned int height; unsigned int bytesperline; unsigned int sizeimage; unsigned int fourcc; struct v4l2_rect rect; }; struct coda_iram_info { u32 axi_sram_use; phys_addr_t buf_bit_use; phys_addr_t buf_ip_ac_dc_use; phys_addr_t buf_dbk_y_use; phys_addr_t buf_dbk_c_use; phys_addr_t buf_ovl_use; phys_addr_t buf_btp_use; phys_addr_t search_ram_paddr; int search_ram_size; int remaining; phys_addr_t next_paddr; }; #define GDI_LINEAR_FRAME_MAP 0 #define GDI_TILED_FRAME_MB_RASTER_MAP 1 struct coda_ctx; struct coda_context_ops { int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq); int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb); int (*start_streaming)(struct coda_ctx *ctx); int (*prepare_run)(struct coda_ctx *ctx); void (*finish_run)(struct coda_ctx *ctx); void (*run_timeout)(struct coda_ctx *ctx); void (*seq_init_work)(struct work_struct *work); void (*seq_end_work)(struct work_struct *work); void (*release)(struct coda_ctx *ctx); }; struct coda_internal_frame { struct coda_aux_buf buf; struct coda_buffer_meta meta; u32 type; u32 error; }; struct coda_ctx { struct coda_dev *dev; struct mutex buffer_mutex; struct work_struct pic_run_work; struct work_struct seq_init_work; struct work_struct seq_end_work; struct completion completion; const struct coda_video_device *cvd; const struct coda_context_ops *ops; int aborting; int initialized; int streamon_out; int streamon_cap; u32 qsequence; u32 osequence; u32 sequence_offset; struct coda_q_data q_data[2]; enum coda_inst_type inst_type; const struct coda_codec *codec; enum v4l2_colorspace colorspace; enum v4l2_xfer_func xfer_func; enum v4l2_ycbcr_encoding ycbcr_enc; enum v4l2_quantization quantization; struct coda_params params; struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *h264_profile_ctrl; struct v4l2_ctrl *h264_level_ctrl; struct v4l2_ctrl *mpeg2_profile_ctrl; struct v4l2_ctrl *mpeg2_level_ctrl; struct v4l2_ctrl *mpeg4_profile_ctrl; struct v4l2_ctrl *mpeg4_level_ctrl; struct v4l2_ctrl *mb_err_cnt_ctrl; struct v4l2_fh fh; int gopcounter; int runcounter; int jpeg_ecs_offset; char vpu_header[3][64]; int vpu_header_size[3]; struct kfifo bitstream_fifo; struct mutex bitstream_mutex; struct coda_aux_buf bitstream; bool hold; struct coda_aux_buf parabuf; struct coda_aux_buf psbuf; struct coda_aux_buf slicebuf; struct coda_internal_frame internal_frames[CODA_MAX_FRAMEBUFFERS]; struct list_head buffer_meta_list; spinlock_t buffer_meta_lock; int num_metas; unsigned int first_frame_sequence; struct coda_aux_buf workbuf; int num_internal_frames; int idx; int reg_idx; struct coda_iram_info iram_info; int tiled_map_type; u32 bit_stream_param; u32 frm_dis_flg; u32 frame_mem_ctrl; u32 para_change; int display_idx; struct dentry *debugfs_entry; bool use_bit; bool use_vdoa; struct vdoa_ctx *vdoa; /* * wakeup mutex used to serialize encoder stop command and finish_run, * ensures that finish_run always either flags the last returned buffer * or wakes up the capture queue to signal EOS afterwards. */ struct mutex wakeup_mutex; }; extern int coda_debug; #define coda_dbg(level, ctx, fmt, arg...) \ do { \ if (coda_debug >= (level)) \ v4l2_dbg((level), coda_debug, &(ctx)->dev->v4l2_dev, \ "%u: " fmt, (ctx)->idx, ##arg); \ } while (0) void coda_write(struct coda_dev *dev, u32 data, u32 reg); unsigned int coda_read(struct coda_dev *dev, u32 reg); void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, struct vb2_v4l2_buffer *buf, unsigned int reg_y); int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, size_t size, const char *name, struct dentry *parent); void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf); int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq); int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq); int coda_hw_reset(struct coda_ctx *ctx); void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list); void coda_set_gdi_regs(struct coda_ctx *ctx); static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx, enum v4l2_buf_type type) { switch (type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT: return &(ctx->q_data[V4L2_M2M_SRC]); case V4L2_BUF_TYPE_VIDEO_CAPTURE: return &(ctx->q_data[V4L2_M2M_DST]); default: return NULL; } } const char *coda_product_name(int product); int coda_check_firmware(struct coda_dev *dev); static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx) { return kfifo_len(&ctx->bitstream_fifo); } /* * The bitstream prefetcher needs to read at least 2 256 byte periods past * the desired bitstream position for all data to reach the decoder. */ static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos) { return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512; } bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos); int coda_bitstream_flush(struct coda_ctx *ctx); void coda_bit_stream_end_flag(struct coda_ctx *ctx); void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state); int coda_h264_filler_nal(int size, char *p); int coda_h264_padding(int size, char *p); int coda_h264_profile(int profile_idc); int coda_h264_level(int level_idc); int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb); int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf, int *size, int max_size); int coda_mpeg2_profile(int profile_idc); int coda_mpeg2_level(int level_idc); u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size); int coda_mpeg4_profile(int profile_idc); int coda_mpeg4_level(int level_idc); u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size); void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc, u8 level_idc); static inline int coda_jpeg_scale(int src, int dst) { return (dst <= src / 8) ? 3 : (dst <= src / 4) ? 2 : (dst <= src / 2) ? 1 : 0; } bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb); int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb); int coda_jpeg_write_tables(struct coda_ctx *ctx); void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality); extern const struct coda_context_ops coda_bit_encode_ops; extern const struct coda_context_ops coda_bit_decode_ops; extern const struct coda_context_ops coda9_jpeg_encode_ops; extern const struct coda_context_ops coda9_jpeg_decode_ops; irqreturn_t coda_irq_handler(int irq, void *data); irqreturn_t coda9_jpeg_irq_handler(int irq, void *data); #endif /* __CODA_H__ */