/* * Coda multi-standard codec IP * * Copyright (C) 2012 Vista Silicon S.L. * Javier Martin, <javier.martin@vista-silicon.com> * Xavier Duret * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #ifndef __CODA_H__ #define __CODA_H__ #include <linux/debugfs.h> #include <linux/irqreturn.h> #include <linux/mutex.h> #include <linux/kfifo.h> #include <linux/videodev2.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fh.h> #include <media/videobuf2-core.h> #include "coda_regs.h" #define CODA_MAX_FRAMEBUFFERS 8 #define FMO_SLICE_SAVE_BUF_SIZE (32) 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_7541 = 0xf012, CODA_960 = 0xf020, }; struct coda_video_device; struct coda_devtype { char *firmware; 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[5]; struct platform_device *plat_dev; const struct coda_devtype *devtype; 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; spinlock_t irqlock; struct mutex dev_mutex; struct mutex coda_mutex; struct workqueue_struct *workqueue; struct v4l2_m2m_dev *m2m_dev; struct vb2_alloc_ctx *alloc_ctx; struct list_head instances; unsigned long instance_mask; struct dentry *debugfs_root; }; 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_deblk_enabled; u8 h264_deblk_alpha; u8 h264_deblk_beta; u8 mpeg4_intra_qp; u8 mpeg4_inter_qp; u8 gop_size; int intra_refresh; u8 jpeg_quality; u8 jpeg_restart_interval; u8 *jpeg_qmat_tab[3]; int codec_mode; int codec_mode_aux; enum v4l2_mpeg_video_multi_slice_mode slice_mode; u32 framerate; u16 bitrate; u32 slice_max_bits; u32 slice_max_mb; }; struct coda_buffer_meta { struct list_head list; u32 sequence; struct v4l2_timecode timecode; struct timeval timestamp; u32 start; u32 end; }; /* 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; }; struct gdi_tiled_map { int xy2ca_map[16]; int xy2ba_map[16]; int xy2ra_map[16]; int rbc2axi_map[32]; int xy2rbc_config; int map_type; #define GDI_LINEAR_FRAME_MAP 0 }; 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 (*seq_end_work)(struct work_struct *work); void (*release)(struct coda_ctx *ctx); }; struct coda_ctx { struct coda_dev *dev; struct mutex buffer_mutex; struct list_head list; struct work_struct pic_run_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; struct coda_params params; struct v4l2_ctrl_handler ctrls; struct v4l2_fh fh; int gopcounter; int runcounter; 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_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; u32 frame_types[CODA_MAX_FRAMEBUFFERS]; struct coda_buffer_meta frame_metas[CODA_MAX_FRAMEBUFFERS]; u32 frame_errors[CODA_MAX_FRAMEBUFFERS]; struct list_head buffer_meta_list; struct coda_aux_buf workbuf; int num_internal_frames; int idx; int reg_idx; struct coda_iram_info iram_info; struct gdi_tiled_map tiled_map; u32 bit_stream_param; u32 frm_dis_flg; u32 frame_mem_ctrl; int display_idx; struct dentry *debugfs_entry; bool use_bit; }; extern int coda_debug; 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_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, bool streaming); 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); } void coda_bit_stream_end_flag(struct coda_ctx *ctx); int coda_h264_padding(int size, char *p); bool coda_jpeg_check_buffer(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; irqreturn_t coda_irq_handler(int irq, void *data); #endif /* __CODA_H__ */