18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TW5864 driver - common header file 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2016 Bluecherry, LLC <maintainers@bluecherrydvr.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/pci.h> 98c2ecf20Sopenharmony_ci#include <linux/videodev2.h> 108c2ecf20Sopenharmony_ci#include <linux/notifier.h> 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/mutex.h> 138c2ecf20Sopenharmony_ci#include <linux/io.h> 148c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <media/v4l2-common.h> 178c2ecf20Sopenharmony_ci#include <media/v4l2-ioctl.h> 188c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 198c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 208c2ecf20Sopenharmony_ci#include <media/videobuf2-dma-sg.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "tw5864-reg.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define PCI_DEVICE_ID_TECHWELL_5864 0x5864 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define TW5864_NORMS V4L2_STD_ALL 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */ 298c2ecf20Sopenharmony_ci/* card configuration */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define TW5864_INPUTS 4 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* The TW5864 uses 192 (16x12) detection cells in full screen for motion 348c2ecf20Sopenharmony_ci * detection. Each detection cell is composed of 44 pixels and 20 lines for 358c2ecf20Sopenharmony_ci * NTSC and 24 lines for PAL. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci#define MD_CELLS_HOR 16 388c2ecf20Sopenharmony_ci#define MD_CELLS_VERT 12 398c2ecf20Sopenharmony_ci#define MD_CELLS (MD_CELLS_HOR * MD_CELLS_VERT) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define H264_VLC_BUF_SIZE 0x80000 428c2ecf20Sopenharmony_ci#define H264_MV_BUF_SIZE 0x2000 /* device writes 5396 bytes */ 438c2ecf20Sopenharmony_ci#define QP_VALUE 28 448c2ecf20Sopenharmony_ci#define MAX_GOP_SIZE 255 458c2ecf20Sopenharmony_ci#define GOP_SIZE MAX_GOP_SIZE 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cienum resolution { 488c2ecf20Sopenharmony_ci D1 = 1, 498c2ecf20Sopenharmony_ci HD1 = 2, /* half d1 - 360x(240|288) */ 508c2ecf20Sopenharmony_ci CIF = 3, 518c2ecf20Sopenharmony_ci QCIF = 4, 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */ 558c2ecf20Sopenharmony_ci/* device / file handle status */ 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistruct tw5864_dev; /* forward delclaration */ 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* buffer for one video/vbi/ts frame */ 608c2ecf20Sopenharmony_cistruct tw5864_buf { 618c2ecf20Sopenharmony_ci struct vb2_v4l2_buffer vb; 628c2ecf20Sopenharmony_ci struct list_head list; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci unsigned int size; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct tw5864_dma_buf { 688c2ecf20Sopenharmony_ci void *addr; 698c2ecf20Sopenharmony_ci dma_addr_t dma_addr; 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cienum tw5864_vid_std { 738c2ecf20Sopenharmony_ci STD_NTSC = 0, /* NTSC (M) */ 748c2ecf20Sopenharmony_ci STD_PAL = 1, /* PAL (B, D, G, H, I) */ 758c2ecf20Sopenharmony_ci STD_SECAM = 2, /* SECAM */ 768c2ecf20Sopenharmony_ci STD_NTSC443 = 3, /* NTSC4.43 */ 778c2ecf20Sopenharmony_ci STD_PAL_M = 4, /* PAL (M) */ 788c2ecf20Sopenharmony_ci STD_PAL_CN = 5, /* PAL (CN) */ 798c2ecf20Sopenharmony_ci STD_PAL_60 = 6, /* PAL 60 */ 808c2ecf20Sopenharmony_ci STD_INVALID = 7, 818c2ecf20Sopenharmony_ci STD_AUTO = 7, 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistruct tw5864_input { 858c2ecf20Sopenharmony_ci int nr; /* input number */ 868c2ecf20Sopenharmony_ci struct tw5864_dev *root; 878c2ecf20Sopenharmony_ci struct mutex lock; /* used for vidq and vdev */ 888c2ecf20Sopenharmony_ci spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */ 898c2ecf20Sopenharmony_ci struct video_device vdev; 908c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler hdl; 918c2ecf20Sopenharmony_ci struct vb2_queue vidq; 928c2ecf20Sopenharmony_ci struct list_head active; 938c2ecf20Sopenharmony_ci enum resolution resolution; 948c2ecf20Sopenharmony_ci unsigned int width, height; 958c2ecf20Sopenharmony_ci unsigned int frame_seqno; 968c2ecf20Sopenharmony_ci unsigned int frame_gop_seqno; 978c2ecf20Sopenharmony_ci unsigned int h264_idr_pic_id; 988c2ecf20Sopenharmony_ci int enabled; 998c2ecf20Sopenharmony_ci enum tw5864_vid_std std; 1008c2ecf20Sopenharmony_ci v4l2_std_id v4l2_std; 1018c2ecf20Sopenharmony_ci int tail_nb_bits; 1028c2ecf20Sopenharmony_ci u8 tail; 1038c2ecf20Sopenharmony_ci u8 *buf_cur_ptr; 1048c2ecf20Sopenharmony_ci int buf_cur_space_left; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci u32 reg_interlacing; 1078c2ecf20Sopenharmony_ci u32 reg_vlc; 1088c2ecf20Sopenharmony_ci u32 reg_dsp_codec; 1098c2ecf20Sopenharmony_ci u32 reg_dsp; 1108c2ecf20Sopenharmony_ci u32 reg_emu; 1118c2ecf20Sopenharmony_ci u32 reg_dsp_qp; 1128c2ecf20Sopenharmony_ci u32 reg_dsp_ref_mvp_lambda; 1138c2ecf20Sopenharmony_ci u32 reg_dsp_i4x4_weight; 1148c2ecf20Sopenharmony_ci u32 buf_id; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci struct tw5864_buf *vb; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci struct v4l2_ctrl *md_threshold_grid_ctrl; 1198c2ecf20Sopenharmony_ci u16 md_threshold_grid_values[12 * 16]; 1208c2ecf20Sopenharmony_ci int qp; 1218c2ecf20Sopenharmony_ci int gop; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* 1248c2ecf20Sopenharmony_ci * In (1/MAX_FPS) units. 1258c2ecf20Sopenharmony_ci * For max FPS (default), set to 1. 1268c2ecf20Sopenharmony_ci * For 1 FPS, set to e.g. 32. 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ci int frame_interval; 1298c2ecf20Sopenharmony_ci unsigned long new_frame_deadline; 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistruct tw5864_h264_frame { 1338c2ecf20Sopenharmony_ci struct tw5864_dma_buf vlc; 1348c2ecf20Sopenharmony_ci struct tw5864_dma_buf mv; 1358c2ecf20Sopenharmony_ci int vlc_len; 1368c2ecf20Sopenharmony_ci u32 checksum; 1378c2ecf20Sopenharmony_ci struct tw5864_input *input; 1388c2ecf20Sopenharmony_ci u64 timestamp; 1398c2ecf20Sopenharmony_ci unsigned int seqno; 1408c2ecf20Sopenharmony_ci unsigned int gop_seqno; 1418c2ecf20Sopenharmony_ci}; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/* global device status */ 1448c2ecf20Sopenharmony_cistruct tw5864_dev { 1458c2ecf20Sopenharmony_ci spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */ 1468c2ecf20Sopenharmony_ci struct v4l2_device v4l2_dev; 1478c2ecf20Sopenharmony_ci struct tw5864_input inputs[TW5864_INPUTS]; 1488c2ecf20Sopenharmony_ci#define H264_BUF_CNT 4 1498c2ecf20Sopenharmony_ci struct tw5864_h264_frame h264_buf[H264_BUF_CNT]; 1508c2ecf20Sopenharmony_ci int h264_buf_r_index; 1518c2ecf20Sopenharmony_ci int h264_buf_w_index; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci struct tasklet_struct tasklet; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci int encoder_busy; 1568c2ecf20Sopenharmony_ci /* Input number to check next for ready raw picture (in RR fashion) */ 1578c2ecf20Sopenharmony_ci int next_input; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* pci i/o */ 1608c2ecf20Sopenharmony_ci char name[64]; 1618c2ecf20Sopenharmony_ci struct pci_dev *pci; 1628c2ecf20Sopenharmony_ci void __iomem *mmio; 1638c2ecf20Sopenharmony_ci u32 irqmask; 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci#define tw_readl(reg) readl(dev->mmio + reg) 1678c2ecf20Sopenharmony_ci#define tw_mask_readl(reg, mask) \ 1688c2ecf20Sopenharmony_ci (tw_readl(reg) & (mask)) 1698c2ecf20Sopenharmony_ci#define tw_mask_shift_readl(reg, mask, shift) \ 1708c2ecf20Sopenharmony_ci (tw_mask_readl((reg), ((mask) << (shift))) >> (shift)) 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#define tw_writel(reg, value) writel((value), dev->mmio + reg) 1738c2ecf20Sopenharmony_ci#define tw_mask_writel(reg, mask, value) \ 1748c2ecf20Sopenharmony_ci tw_writel(reg, (tw_readl(reg) & ~(mask)) | ((value) & (mask))) 1758c2ecf20Sopenharmony_ci#define tw_mask_shift_writel(reg, mask, shift, value) \ 1768c2ecf20Sopenharmony_ci tw_mask_writel((reg), ((mask) << (shift)), ((value) << (shift))) 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#define tw_setl(reg, bit) tw_writel((reg), tw_readl(reg) | (bit)) 1798c2ecf20Sopenharmony_ci#define tw_clearl(reg, bit) tw_writel((reg), tw_readl(reg) & ~(bit)) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ciu8 tw5864_indir_readb(struct tw5864_dev *dev, u16 addr); 1828c2ecf20Sopenharmony_ci#define tw_indir_readb(addr) tw5864_indir_readb(dev, addr) 1838c2ecf20Sopenharmony_civoid tw5864_indir_writeb(struct tw5864_dev *dev, u16 addr, u8 data); 1848c2ecf20Sopenharmony_ci#define tw_indir_writeb(addr, data) tw5864_indir_writeb(dev, addr, data) 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_civoid tw5864_irqmask_apply(struct tw5864_dev *dev); 1878c2ecf20Sopenharmony_ciint tw5864_video_init(struct tw5864_dev *dev, int *video_nr); 1888c2ecf20Sopenharmony_civoid tw5864_video_fini(struct tw5864_dev *dev); 1898c2ecf20Sopenharmony_civoid tw5864_prepare_frame_headers(struct tw5864_input *input); 1908c2ecf20Sopenharmony_civoid tw5864_h264_put_stream_header(u8 **buf, size_t *space_left, int qp, 1918c2ecf20Sopenharmony_ci int width, int height); 1928c2ecf20Sopenharmony_civoid tw5864_h264_put_slice_header(u8 **buf, size_t *space_left, 1938c2ecf20Sopenharmony_ci unsigned int idr_pic_id, 1948c2ecf20Sopenharmony_ci unsigned int frame_gop_seqno, 1958c2ecf20Sopenharmony_ci int *tail_nb_bits, u8 *tail); 1968c2ecf20Sopenharmony_civoid tw5864_request_encoded_frame(struct tw5864_input *input); 197