162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * TW5864 driver - common header file 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2016 Bluecherry, LLC <maintainers@bluecherrydvr.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/pci.h> 962306a36Sopenharmony_ci#include <linux/videodev2.h> 1062306a36Sopenharmony_ci#include <linux/notifier.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/mutex.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <media/v4l2-common.h> 1762306a36Sopenharmony_ci#include <media/v4l2-ioctl.h> 1862306a36Sopenharmony_ci#include <media/v4l2-ctrls.h> 1962306a36Sopenharmony_ci#include <media/v4l2-device.h> 2062306a36Sopenharmony_ci#include <media/videobuf2-dma-sg.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "tw5864-reg.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define PCI_DEVICE_ID_TECHWELL_5864 0x5864 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define TW5864_NORMS V4L2_STD_ALL 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 2962306a36Sopenharmony_ci/* card configuration */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define TW5864_INPUTS 4 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* The TW5864 uses 192 (16x12) detection cells in full screen for motion 3462306a36Sopenharmony_ci * detection. Each detection cell is composed of 44 pixels and 20 lines for 3562306a36Sopenharmony_ci * NTSC and 24 lines for PAL. 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci#define MD_CELLS_HOR 16 3862306a36Sopenharmony_ci#define MD_CELLS_VERT 12 3962306a36Sopenharmony_ci#define MD_CELLS (MD_CELLS_HOR * MD_CELLS_VERT) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define H264_VLC_BUF_SIZE 0x80000 4262306a36Sopenharmony_ci#define H264_MV_BUF_SIZE 0x2000 /* device writes 5396 bytes */ 4362306a36Sopenharmony_ci#define QP_VALUE 28 4462306a36Sopenharmony_ci#define MAX_GOP_SIZE 255 4562306a36Sopenharmony_ci#define GOP_SIZE MAX_GOP_SIZE 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cienum resolution { 4862306a36Sopenharmony_ci D1 = 1, 4962306a36Sopenharmony_ci HD1 = 2, /* half d1 - 360x(240|288) */ 5062306a36Sopenharmony_ci CIF = 3, 5162306a36Sopenharmony_ci QCIF = 4, 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 5562306a36Sopenharmony_ci/* device / file handle status */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistruct tw5864_dev; /* forward delclaration */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* buffer for one video/vbi/ts frame */ 6062306a36Sopenharmony_cistruct tw5864_buf { 6162306a36Sopenharmony_ci struct vb2_v4l2_buffer vb; 6262306a36Sopenharmony_ci struct list_head list; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci unsigned int size; 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistruct tw5864_dma_buf { 6862306a36Sopenharmony_ci void *addr; 6962306a36Sopenharmony_ci dma_addr_t dma_addr; 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cienum tw5864_vid_std { 7362306a36Sopenharmony_ci STD_NTSC = 0, /* NTSC (M) */ 7462306a36Sopenharmony_ci STD_PAL = 1, /* PAL (B, D, G, H, I) */ 7562306a36Sopenharmony_ci STD_SECAM = 2, /* SECAM */ 7662306a36Sopenharmony_ci STD_NTSC443 = 3, /* NTSC4.43 */ 7762306a36Sopenharmony_ci STD_PAL_M = 4, /* PAL (M) */ 7862306a36Sopenharmony_ci STD_PAL_CN = 5, /* PAL (CN) */ 7962306a36Sopenharmony_ci STD_PAL_60 = 6, /* PAL 60 */ 8062306a36Sopenharmony_ci STD_INVALID = 7, 8162306a36Sopenharmony_ci STD_AUTO = 7, 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistruct tw5864_input { 8562306a36Sopenharmony_ci int nr; /* input number */ 8662306a36Sopenharmony_ci struct tw5864_dev *root; 8762306a36Sopenharmony_ci struct mutex lock; /* used for vidq and vdev */ 8862306a36Sopenharmony_ci spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */ 8962306a36Sopenharmony_ci struct video_device vdev; 9062306a36Sopenharmony_ci struct v4l2_ctrl_handler hdl; 9162306a36Sopenharmony_ci struct vb2_queue vidq; 9262306a36Sopenharmony_ci struct list_head active; 9362306a36Sopenharmony_ci enum resolution resolution; 9462306a36Sopenharmony_ci unsigned int width, height; 9562306a36Sopenharmony_ci unsigned int frame_seqno; 9662306a36Sopenharmony_ci unsigned int frame_gop_seqno; 9762306a36Sopenharmony_ci unsigned int h264_idr_pic_id; 9862306a36Sopenharmony_ci int enabled; 9962306a36Sopenharmony_ci enum tw5864_vid_std std; 10062306a36Sopenharmony_ci v4l2_std_id v4l2_std; 10162306a36Sopenharmony_ci int tail_nb_bits; 10262306a36Sopenharmony_ci u8 tail; 10362306a36Sopenharmony_ci u8 *buf_cur_ptr; 10462306a36Sopenharmony_ci int buf_cur_space_left; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci u32 reg_interlacing; 10762306a36Sopenharmony_ci u32 reg_vlc; 10862306a36Sopenharmony_ci u32 reg_dsp_codec; 10962306a36Sopenharmony_ci u32 reg_dsp; 11062306a36Sopenharmony_ci u32 reg_emu; 11162306a36Sopenharmony_ci u32 reg_dsp_qp; 11262306a36Sopenharmony_ci u32 reg_dsp_ref_mvp_lambda; 11362306a36Sopenharmony_ci u32 reg_dsp_i4x4_weight; 11462306a36Sopenharmony_ci u32 buf_id; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci struct tw5864_buf *vb; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci struct v4l2_ctrl *md_threshold_grid_ctrl; 11962306a36Sopenharmony_ci u16 md_threshold_grid_values[12 * 16]; 12062306a36Sopenharmony_ci int qp; 12162306a36Sopenharmony_ci int gop; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* 12462306a36Sopenharmony_ci * In (1/MAX_FPS) units. 12562306a36Sopenharmony_ci * For max FPS (default), set to 1. 12662306a36Sopenharmony_ci * For 1 FPS, set to e.g. 32. 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ci int frame_interval; 12962306a36Sopenharmony_ci unsigned long new_frame_deadline; 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistruct tw5864_h264_frame { 13362306a36Sopenharmony_ci struct tw5864_dma_buf vlc; 13462306a36Sopenharmony_ci struct tw5864_dma_buf mv; 13562306a36Sopenharmony_ci int vlc_len; 13662306a36Sopenharmony_ci u32 checksum; 13762306a36Sopenharmony_ci struct tw5864_input *input; 13862306a36Sopenharmony_ci u64 timestamp; 13962306a36Sopenharmony_ci unsigned int seqno; 14062306a36Sopenharmony_ci unsigned int gop_seqno; 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* global device status */ 14462306a36Sopenharmony_cistruct tw5864_dev { 14562306a36Sopenharmony_ci spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */ 14662306a36Sopenharmony_ci struct v4l2_device v4l2_dev; 14762306a36Sopenharmony_ci struct tw5864_input inputs[TW5864_INPUTS]; 14862306a36Sopenharmony_ci#define H264_BUF_CNT 4 14962306a36Sopenharmony_ci struct tw5864_h264_frame h264_buf[H264_BUF_CNT]; 15062306a36Sopenharmony_ci int h264_buf_r_index; 15162306a36Sopenharmony_ci int h264_buf_w_index; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci struct tasklet_struct tasklet; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci int encoder_busy; 15662306a36Sopenharmony_ci /* Input number to check next for ready raw picture (in RR fashion) */ 15762306a36Sopenharmony_ci int next_input; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* pci i/o */ 16062306a36Sopenharmony_ci char name[64]; 16162306a36Sopenharmony_ci struct pci_dev *pci; 16262306a36Sopenharmony_ci void __iomem *mmio; 16362306a36Sopenharmony_ci u32 irqmask; 16462306a36Sopenharmony_ci}; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci#define tw_readl(reg) readl(dev->mmio + reg) 16762306a36Sopenharmony_ci#define tw_mask_readl(reg, mask) \ 16862306a36Sopenharmony_ci (tw_readl(reg) & (mask)) 16962306a36Sopenharmony_ci#define tw_mask_shift_readl(reg, mask, shift) \ 17062306a36Sopenharmony_ci (tw_mask_readl((reg), ((mask) << (shift))) >> (shift)) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define tw_writel(reg, value) writel((value), dev->mmio + reg) 17362306a36Sopenharmony_ci#define tw_mask_writel(reg, mask, value) \ 17462306a36Sopenharmony_ci tw_writel(reg, (tw_readl(reg) & ~(mask)) | ((value) & (mask))) 17562306a36Sopenharmony_ci#define tw_mask_shift_writel(reg, mask, shift, value) \ 17662306a36Sopenharmony_ci tw_mask_writel((reg), ((mask) << (shift)), ((value) << (shift))) 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#define tw_setl(reg, bit) tw_writel((reg), tw_readl(reg) | (bit)) 17962306a36Sopenharmony_ci#define tw_clearl(reg, bit) tw_writel((reg), tw_readl(reg) & ~(bit)) 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciu8 tw5864_indir_readb(struct tw5864_dev *dev, u16 addr); 18262306a36Sopenharmony_ci#define tw_indir_readb(addr) tw5864_indir_readb(dev, addr) 18362306a36Sopenharmony_civoid tw5864_indir_writeb(struct tw5864_dev *dev, u16 addr, u8 data); 18462306a36Sopenharmony_ci#define tw_indir_writeb(addr, data) tw5864_indir_writeb(dev, addr, data) 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_civoid tw5864_irqmask_apply(struct tw5864_dev *dev); 18762306a36Sopenharmony_ciint tw5864_video_init(struct tw5864_dev *dev, int *video_nr); 18862306a36Sopenharmony_civoid tw5864_video_fini(struct tw5864_dev *dev); 18962306a36Sopenharmony_civoid tw5864_prepare_frame_headers(struct tw5864_input *input); 19062306a36Sopenharmony_civoid tw5864_h264_put_stream_header(u8 **buf, size_t *space_left, int qp, 19162306a36Sopenharmony_ci int width, int height); 19262306a36Sopenharmony_civoid tw5864_h264_put_slice_header(u8 **buf, size_t *space_left, 19362306a36Sopenharmony_ci unsigned int idr_pic_id, 19462306a36Sopenharmony_ci unsigned int frame_gop_seqno, 19562306a36Sopenharmony_ci int *tail_nb_bits, u8 *tail); 19662306a36Sopenharmony_civoid tw5864_request_encoded_frame(struct tw5864_input *input); 197