162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * tw68 driver common header file 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Much of this code is derived from the cx88 and sa7134 drivers, which 662306a36Sopenharmony_ci * were in turn derived from the bt87x driver. The original work was by 762306a36Sopenharmony_ci * Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab, 862306a36Sopenharmony_ci * Hans Verkuil, Andy Walls and many others. Their work is gratefully 962306a36Sopenharmony_ci * acknowledged. Full credit goes to them - any problems within this code 1062306a36Sopenharmony_ci * are mine. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Copyright (C) 2009 William M. Brack 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Refactored and updated to the latest v4l core frameworks: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl> 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/pci.h> 2062306a36Sopenharmony_ci#include <linux/videodev2.h> 2162306a36Sopenharmony_ci#include <linux/notifier.h> 2262306a36Sopenharmony_ci#include <linux/delay.h> 2362306a36Sopenharmony_ci#include <linux/mutex.h> 2462306a36Sopenharmony_ci#include <linux/io.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <media/v4l2-common.h> 2762306a36Sopenharmony_ci#include <media/v4l2-ioctl.h> 2862306a36Sopenharmony_ci#include <media/v4l2-ctrls.h> 2962306a36Sopenharmony_ci#include <media/v4l2-device.h> 3062306a36Sopenharmony_ci#include <media/videobuf2-v4l2.h> 3162306a36Sopenharmony_ci#include <media/videobuf2-dma-sg.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "tw68-reg.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define UNSET (-1U) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define TW68_NORMS ( \ 3862306a36Sopenharmony_ci V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM | \ 3962306a36Sopenharmony_ci V4L2_STD_PAL_M | V4L2_STD_PAL_Nc | V4L2_STD_PAL_60) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define TW68_VID_INTS (TW68_FFERR | TW68_PABORT | TW68_DMAPERR | \ 4262306a36Sopenharmony_ci TW68_FFOF | TW68_DMAPI) 4362306a36Sopenharmony_ci/* TW6800 chips have trouble with these, so we don't set them for that chip */ 4462306a36Sopenharmony_ci#define TW68_VID_INTSX (TW68_FDMIS | TW68_HLOCK | TW68_VLOCK) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define TW68_I2C_INTS (TW68_SBERR | TW68_SBDONE | TW68_SBERR2 | \ 4762306a36Sopenharmony_ci TW68_SBDONE2) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cienum tw68_decoder_type { 5062306a36Sopenharmony_ci TW6800, 5162306a36Sopenharmony_ci TW6801, 5262306a36Sopenharmony_ci TW6804, 5362306a36Sopenharmony_ci TWXXXX, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 5762306a36Sopenharmony_ci/* static data */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct tw68_tvnorm { 6062306a36Sopenharmony_ci char *name; 6162306a36Sopenharmony_ci v4l2_std_id id; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* video decoder */ 6462306a36Sopenharmony_ci u32 sync_control; 6562306a36Sopenharmony_ci u32 luma_control; 6662306a36Sopenharmony_ci u32 chroma_ctrl1; 6762306a36Sopenharmony_ci u32 chroma_gain; 6862306a36Sopenharmony_ci u32 chroma_ctrl2; 6962306a36Sopenharmony_ci u32 vgate_misc; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* video scaler */ 7262306a36Sopenharmony_ci u32 h_delay; 7362306a36Sopenharmony_ci u32 h_delay0; /* for TW6800 */ 7462306a36Sopenharmony_ci u32 h_start; 7562306a36Sopenharmony_ci u32 h_stop; 7662306a36Sopenharmony_ci u32 v_delay; 7762306a36Sopenharmony_ci u32 video_v_start; 7862306a36Sopenharmony_ci u32 video_v_stop; 7962306a36Sopenharmony_ci u32 vbi_v_start_0; 8062306a36Sopenharmony_ci u32 vbi_v_stop_0; 8162306a36Sopenharmony_ci u32 vbi_v_start_1; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Techwell specific */ 8462306a36Sopenharmony_ci u32 format; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct tw68_format { 8862306a36Sopenharmony_ci u32 fourcc; 8962306a36Sopenharmony_ci u32 depth; 9062306a36Sopenharmony_ci u32 twformat; 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 9462306a36Sopenharmony_ci/* card configuration */ 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define TW68_BOARD_NOAUTO UNSET 9762306a36Sopenharmony_ci#define TW68_BOARD_UNKNOWN 0 9862306a36Sopenharmony_ci#define TW68_BOARD_GENERIC_6802 1 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define TW68_MAXBOARDS 16 10162306a36Sopenharmony_ci#define TW68_INPUT_MAX 4 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 10462306a36Sopenharmony_ci/* device / file handle status */ 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistruct tw68_dev; /* forward delclaration */ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* buffer for one video/vbi/ts frame */ 11162306a36Sopenharmony_cistruct tw68_buf { 11262306a36Sopenharmony_ci struct vb2_v4l2_buffer vb; 11362306a36Sopenharmony_ci struct list_head list; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci unsigned int size; 11662306a36Sopenharmony_ci __le32 *cpu; 11762306a36Sopenharmony_ci __le32 *jmp; 11862306a36Sopenharmony_ci dma_addr_t dma; 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistruct tw68_fmt { 12262306a36Sopenharmony_ci char *name; 12362306a36Sopenharmony_ci u32 fourcc; /* v4l2 format id */ 12462306a36Sopenharmony_ci int depth; 12562306a36Sopenharmony_ci int flags; 12662306a36Sopenharmony_ci u32 twformat; 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* global device status */ 13062306a36Sopenharmony_cistruct tw68_dev { 13162306a36Sopenharmony_ci struct mutex lock; 13262306a36Sopenharmony_ci spinlock_t slock; 13362306a36Sopenharmony_ci u16 instance; 13462306a36Sopenharmony_ci struct v4l2_device v4l2_dev; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* various device info */ 13762306a36Sopenharmony_ci enum tw68_decoder_type vdecoder; 13862306a36Sopenharmony_ci struct video_device vdev; 13962306a36Sopenharmony_ci struct v4l2_ctrl_handler hdl; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* pci i/o */ 14262306a36Sopenharmony_ci char *name; 14362306a36Sopenharmony_ci struct pci_dev *pci; 14462306a36Sopenharmony_ci unsigned char pci_rev, pci_lat; 14562306a36Sopenharmony_ci u32 __iomem *lmmio; 14662306a36Sopenharmony_ci u8 __iomem *bmmio; 14762306a36Sopenharmony_ci u32 pci_irqmask; 14862306a36Sopenharmony_ci /* The irq mask to be used will depend upon the chip type */ 14962306a36Sopenharmony_ci u32 board_virqmask; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* video capture */ 15262306a36Sopenharmony_ci const struct tw68_format *fmt; 15362306a36Sopenharmony_ci unsigned width, height; 15462306a36Sopenharmony_ci unsigned seqnr; 15562306a36Sopenharmony_ci unsigned field; 15662306a36Sopenharmony_ci struct vb2_queue vidq; 15762306a36Sopenharmony_ci struct list_head active; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* various v4l controls */ 16062306a36Sopenharmony_ci const struct tw68_tvnorm *tvnorm; /* video */ 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci int input; 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#define tw_readl(reg) readl(dev->lmmio + ((reg) >> 2)) 16862306a36Sopenharmony_ci#define tw_readb(reg) readb(dev->bmmio + (reg)) 16962306a36Sopenharmony_ci#define tw_writel(reg, value) writel((value), dev->lmmio + ((reg) >> 2)) 17062306a36Sopenharmony_ci#define tw_writeb(reg, value) writeb((value), dev->bmmio + (reg)) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define tw_andorl(reg, mask, value) \ 17362306a36Sopenharmony_ci writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ 17462306a36Sopenharmony_ci ((value) & (mask)), dev->lmmio+((reg)>>2)) 17562306a36Sopenharmony_ci#define tw_andorb(reg, mask, value) \ 17662306a36Sopenharmony_ci writeb((readb(dev->bmmio + (reg)) & ~(mask)) |\ 17762306a36Sopenharmony_ci ((value) & (mask)), dev->bmmio+(reg)) 17862306a36Sopenharmony_ci#define tw_setl(reg, bit) tw_andorl((reg), (bit), (bit)) 17962306a36Sopenharmony_ci#define tw_setb(reg, bit) tw_andorb((reg), (bit), (bit)) 18062306a36Sopenharmony_ci#define tw_clearl(reg, bit) \ 18162306a36Sopenharmony_ci writel((readl(dev->lmmio + ((reg) >> 2)) & ~(bit)), \ 18262306a36Sopenharmony_ci dev->lmmio + ((reg) >> 2)) 18362306a36Sopenharmony_ci#define tw_clearb(reg, bit) \ 18462306a36Sopenharmony_ci writeb((readb(dev->bmmio+(reg)) & ~(bit)), \ 18562306a36Sopenharmony_ci dev->bmmio + (reg)) 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci#define tw_wait(us) { udelay(us); } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 19062306a36Sopenharmony_ci/* tw68-video.c */ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_civoid tw68_set_tvnorm_hw(struct tw68_dev *dev); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ciint tw68_video_init1(struct tw68_dev *dev); 19562306a36Sopenharmony_ciint tw68_video_init2(struct tw68_dev *dev, int video_nr); 19662306a36Sopenharmony_civoid tw68_irq_video_done(struct tw68_dev *dev, unsigned long status); 19762306a36Sopenharmony_ciint tw68_video_start_dma(struct tw68_dev *dev, struct tw68_buf *buf); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 20062306a36Sopenharmony_ci/* tw68-risc.c */ 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciint tw68_risc_buffer(struct pci_dev *pci, struct tw68_buf *buf, 20362306a36Sopenharmony_ci struct scatterlist *sglist, unsigned int top_offset, 20462306a36Sopenharmony_ci unsigned int bottom_offset, unsigned int bpl, 20562306a36Sopenharmony_ci unsigned int padding, unsigned int lines); 206