cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

saa7164-vbi.c (19716B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Driver for the NXP SAA7164 PCIe bridge
      4 *
      5 *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
      6 */
      7
      8#include "saa7164.h"
      9
     10/* Take the encoder configuration from the port struct and
     11 * flush it to the hardware.
     12 */
     13static void saa7164_vbi_configure(struct saa7164_port *port)
     14{
     15	struct saa7164_dev *dev = port->dev;
     16	dprintk(DBGLVL_VBI, "%s()\n", __func__);
     17
     18	port->vbi_params.width = port->enc_port->width;
     19	port->vbi_params.height = port->enc_port->height;
     20	port->vbi_params.is_50hz =
     21		(port->enc_port->encodernorm.id & V4L2_STD_625_50) != 0;
     22
     23	/* Set up the DIF (enable it) for analog mode by default */
     24	saa7164_api_initialize_dif(port);
     25	dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
     26}
     27
     28static int saa7164_vbi_buffers_dealloc(struct saa7164_port *port)
     29{
     30	struct list_head *c, *n, *p, *q, *l, *v;
     31	struct saa7164_dev *dev = port->dev;
     32	struct saa7164_buffer *buf;
     33	struct saa7164_user_buffer *ubuf;
     34
     35	/* Remove any allocated buffers */
     36	mutex_lock(&port->dmaqueue_lock);
     37
     38	dprintk(DBGLVL_VBI, "%s(port=%d) dmaqueue\n", __func__, port->nr);
     39	list_for_each_safe(c, n, &port->dmaqueue.list) {
     40		buf = list_entry(c, struct saa7164_buffer, list);
     41		list_del(c);
     42		saa7164_buffer_dealloc(buf);
     43	}
     44
     45	dprintk(DBGLVL_VBI, "%s(port=%d) used\n", __func__, port->nr);
     46	list_for_each_safe(p, q, &port->list_buf_used.list) {
     47		ubuf = list_entry(p, struct saa7164_user_buffer, list);
     48		list_del(p);
     49		saa7164_buffer_dealloc_user(ubuf);
     50	}
     51
     52	dprintk(DBGLVL_VBI, "%s(port=%d) free\n", __func__, port->nr);
     53	list_for_each_safe(l, v, &port->list_buf_free.list) {
     54		ubuf = list_entry(l, struct saa7164_user_buffer, list);
     55		list_del(l);
     56		saa7164_buffer_dealloc_user(ubuf);
     57	}
     58
     59	mutex_unlock(&port->dmaqueue_lock);
     60	dprintk(DBGLVL_VBI, "%s(port=%d) done\n", __func__, port->nr);
     61
     62	return 0;
     63}
     64
     65/* Dynamic buffer switch at vbi start time */
     66static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
     67{
     68	struct saa7164_dev *dev = port->dev;
     69	struct saa7164_buffer *buf;
     70	struct saa7164_user_buffer *ubuf;
     71	struct tmHWStreamParameters *params = &port->hw_streamingparams;
     72	int result = -ENODEV, i;
     73	int len = 0;
     74
     75	dprintk(DBGLVL_VBI, "%s()\n", __func__);
     76
     77	/* TODO: NTSC SPECIFIC */
     78	/* Init and establish defaults */
     79	params->samplesperline = 1440;
     80	params->numberoflines = 12;
     81	params->numberoflines = 18;
     82	params->pitch = 1600;
     83	params->pitch = 1440;
     84	params->numpagetables = 2 +
     85		((params->numberoflines * params->pitch) / PAGE_SIZE);
     86	params->bitspersample = 8;
     87	params->linethreshold = 0;
     88	params->pagetablelistvirt = NULL;
     89	params->pagetablelistphys = NULL;
     90	params->numpagetableentries = port->hwcfg.buffercount;
     91
     92	/* Allocate the PCI resources, buffers (hard) */
     93	for (i = 0; i < port->hwcfg.buffercount; i++) {
     94		buf = saa7164_buffer_alloc(port,
     95			params->numberoflines *
     96			params->pitch);
     97
     98		if (!buf) {
     99			printk(KERN_ERR "%s() failed (errno = %d), unable to allocate buffer\n",
    100				__func__, result);
    101			result = -ENOMEM;
    102			goto failed;
    103		} else {
    104
    105			mutex_lock(&port->dmaqueue_lock);
    106			list_add_tail(&buf->list, &port->dmaqueue.list);
    107			mutex_unlock(&port->dmaqueue_lock);
    108
    109		}
    110	}
    111
    112	/* Allocate some kernel buffers for copying
    113	 * to userpsace.
    114	 */
    115	len = params->numberoflines * params->pitch;
    116
    117	if (vbi_buffers < 16)
    118		vbi_buffers = 16;
    119	if (vbi_buffers > 512)
    120		vbi_buffers = 512;
    121
    122	for (i = 0; i < vbi_buffers; i++) {
    123
    124		ubuf = saa7164_buffer_alloc_user(dev, len);
    125		if (ubuf) {
    126			mutex_lock(&port->dmaqueue_lock);
    127			list_add_tail(&ubuf->list, &port->list_buf_free.list);
    128			mutex_unlock(&port->dmaqueue_lock);
    129		}
    130
    131	}
    132
    133	result = 0;
    134
    135failed:
    136	return result;
    137}
    138
    139
    140static int saa7164_vbi_initialize(struct saa7164_port *port)
    141{
    142	saa7164_vbi_configure(port);
    143	return 0;
    144}
    145
    146/* -- V4L2 --------------------------------------------------------- */
    147static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
    148{
    149	struct saa7164_vbi_fh *fh = file->private_data;
    150
    151	return saa7164_s_std(fh->port->enc_port, id);
    152}
    153
    154static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
    155{
    156	struct saa7164_encoder_fh *fh = file->private_data;
    157
    158	return saa7164_g_std(fh->port->enc_port, id);
    159}
    160
    161static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
    162{
    163	struct saa7164_vbi_fh *fh = file->private_data;
    164
    165	return saa7164_g_input(fh->port->enc_port, i);
    166}
    167
    168static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
    169{
    170	struct saa7164_vbi_fh *fh = file->private_data;
    171
    172	return saa7164_s_input(fh->port->enc_port, i);
    173}
    174
    175static int vidioc_g_frequency(struct file *file, void *priv,
    176	struct v4l2_frequency *f)
    177{
    178	struct saa7164_vbi_fh *fh = file->private_data;
    179
    180	return saa7164_g_frequency(fh->port->enc_port, f);
    181}
    182
    183static int vidioc_s_frequency(struct file *file, void *priv,
    184	const struct v4l2_frequency *f)
    185{
    186	struct saa7164_vbi_fh *fh = file->private_data;
    187	int ret = saa7164_s_frequency(fh->port->enc_port, f);
    188
    189	if (ret == 0)
    190		saa7164_vbi_initialize(fh->port);
    191	return ret;
    192}
    193
    194static int vidioc_querycap(struct file *file, void  *priv,
    195	struct v4l2_capability *cap)
    196{
    197	struct saa7164_vbi_fh *fh = file->private_data;
    198	struct saa7164_port *port = fh->port;
    199	struct saa7164_dev *dev = port->dev;
    200
    201	strscpy(cap->driver, dev->name, sizeof(cap->driver));
    202	strscpy(cap->card, saa7164_boards[dev->board].name,
    203		sizeof(cap->card));
    204	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
    205			    V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE |
    206			    V4L2_CAP_DEVICE_CAPS;
    207	return 0;
    208}
    209
    210static int saa7164_vbi_stop_port(struct saa7164_port *port)
    211{
    212	struct saa7164_dev *dev = port->dev;
    213	int ret;
    214
    215	ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
    216	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
    217		printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
    218			__func__, ret);
    219		ret = -EIO;
    220	} else {
    221		dprintk(DBGLVL_VBI, "%s()    Stopped\n", __func__);
    222		ret = 0;
    223	}
    224
    225	return ret;
    226}
    227
    228static int saa7164_vbi_acquire_port(struct saa7164_port *port)
    229{
    230	struct saa7164_dev *dev = port->dev;
    231	int ret;
    232
    233	ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
    234	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
    235		printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
    236			__func__, ret);
    237		ret = -EIO;
    238	} else {
    239		dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
    240		ret = 0;
    241	}
    242
    243	return ret;
    244}
    245
    246static int saa7164_vbi_pause_port(struct saa7164_port *port)
    247{
    248	struct saa7164_dev *dev = port->dev;
    249	int ret;
    250
    251	ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
    252	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
    253		printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
    254			__func__, ret);
    255		ret = -EIO;
    256	} else {
    257		dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
    258		ret = 0;
    259	}
    260
    261	return ret;
    262}
    263
    264/* Firmware is very windows centric, meaning you have to transition
    265 * the part through AVStream / KS Windows stages, forwards or backwards.
    266 * States are: stopped, acquired (h/w), paused, started.
    267 * We have to leave here will all of the soft buffers on the free list,
    268 * else the cfg_post() func won't have soft buffers to correctly configure.
    269 */
    270static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
    271{
    272	struct saa7164_dev *dev = port->dev;
    273	struct saa7164_buffer *buf;
    274	struct saa7164_user_buffer *ubuf;
    275	struct list_head *c, *n;
    276	int ret;
    277
    278	dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
    279
    280	ret = saa7164_vbi_pause_port(port);
    281	ret = saa7164_vbi_acquire_port(port);
    282	ret = saa7164_vbi_stop_port(port);
    283
    284	dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
    285		port->nr);
    286
    287	/* Reset the state of any allocated buffer resources */
    288	mutex_lock(&port->dmaqueue_lock);
    289
    290	/* Reset the hard and soft buffer state */
    291	list_for_each_safe(c, n, &port->dmaqueue.list) {
    292		buf = list_entry(c, struct saa7164_buffer, list);
    293		buf->flags = SAA7164_BUFFER_FREE;
    294		buf->pos = 0;
    295	}
    296
    297	list_for_each_safe(c, n, &port->list_buf_used.list) {
    298		ubuf = list_entry(c, struct saa7164_user_buffer, list);
    299		ubuf->pos = 0;
    300		list_move_tail(&ubuf->list, &port->list_buf_free.list);
    301	}
    302
    303	mutex_unlock(&port->dmaqueue_lock);
    304
    305	/* Free any allocated resources */
    306	saa7164_vbi_buffers_dealloc(port);
    307
    308	dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
    309
    310	return ret;
    311}
    312
    313static int saa7164_vbi_start_streaming(struct saa7164_port *port)
    314{
    315	struct saa7164_dev *dev = port->dev;
    316	int result, ret = 0;
    317
    318	dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
    319
    320	port->done_first_interrupt = 0;
    321
    322	/* allocate all of the PCIe DMA buffer resources on the fly,
    323	 * allowing switching between TS and PS payloads without
    324	 * requiring a complete driver reload.
    325	 */
    326	saa7164_vbi_buffers_alloc(port);
    327
    328	/* Configure the encoder with any cache values */
    329#if 0
    330	saa7164_api_set_encoder(port);
    331	saa7164_api_get_encoder(port);
    332#endif
    333
    334	/* Place the empty buffers on the hardware */
    335	saa7164_buffer_cfg_port(port);
    336
    337	/* Negotiate format */
    338	if (saa7164_api_set_vbi_format(port) != SAA_OK) {
    339		printk(KERN_ERR "%s() No supported VBI format\n", __func__);
    340		ret = -EIO;
    341		goto out;
    342	}
    343
    344	/* Acquire the hardware */
    345	result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
    346	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    347		printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
    348			__func__, result);
    349
    350		ret = -EIO;
    351		goto out;
    352	} else
    353		dprintk(DBGLVL_VBI, "%s()   Acquired\n", __func__);
    354
    355	/* Pause the hardware */
    356	result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
    357	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    358		printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
    359				__func__, result);
    360
    361		/* Stop the hardware, regardless */
    362		result = saa7164_vbi_stop_port(port);
    363		if (result != SAA_OK) {
    364			printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
    365			       __func__, result);
    366		}
    367
    368		ret = -EIO;
    369		goto out;
    370	} else
    371		dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
    372
    373	/* Start the hardware */
    374	result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
    375	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    376		printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
    377				__func__, result);
    378
    379		/* Stop the hardware, regardless */
    380		result = saa7164_vbi_acquire_port(port);
    381		result = saa7164_vbi_stop_port(port);
    382		if (result != SAA_OK) {
    383			printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
    384			       __func__, result);
    385		}
    386
    387		ret = -EIO;
    388	} else
    389		dprintk(DBGLVL_VBI, "%s()   Running\n", __func__);
    390
    391out:
    392	return ret;
    393}
    394
    395static int saa7164_vbi_fmt(struct file *file, void *priv,
    396			   struct v4l2_format *f)
    397{
    398	/* ntsc */
    399	f->fmt.vbi.samples_per_line = 1440;
    400	f->fmt.vbi.sampling_rate = 27000000;
    401	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
    402	f->fmt.vbi.offset = 0;
    403	f->fmt.vbi.flags = 0;
    404	f->fmt.vbi.start[0] = 10;
    405	f->fmt.vbi.count[0] = 18;
    406	f->fmt.vbi.start[1] = 263 + 10 + 1;
    407	f->fmt.vbi.count[1] = 18;
    408	memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
    409	return 0;
    410}
    411
    412static int fops_open(struct file *file)
    413{
    414	struct saa7164_dev *dev;
    415	struct saa7164_port *port;
    416	struct saa7164_vbi_fh *fh;
    417
    418	port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
    419	if (!port)
    420		return -ENODEV;
    421
    422	dev = port->dev;
    423
    424	dprintk(DBGLVL_VBI, "%s()\n", __func__);
    425
    426	/* allocate + initialize per filehandle data */
    427	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
    428	if (NULL == fh)
    429		return -ENOMEM;
    430
    431	fh->port = port;
    432	v4l2_fh_init(&fh->fh, video_devdata(file));
    433	v4l2_fh_add(&fh->fh);
    434	file->private_data = fh;
    435
    436	return 0;
    437}
    438
    439static int fops_release(struct file *file)
    440{
    441	struct saa7164_vbi_fh *fh = file->private_data;
    442	struct saa7164_port *port = fh->port;
    443	struct saa7164_dev *dev = port->dev;
    444
    445	dprintk(DBGLVL_VBI, "%s()\n", __func__);
    446
    447	/* Shut device down on last close */
    448	if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
    449		if (atomic_dec_return(&port->v4l_reader_count) == 0) {
    450			/* stop vbi capture then cancel buffers */
    451			saa7164_vbi_stop_streaming(port);
    452		}
    453	}
    454
    455	v4l2_fh_del(&fh->fh);
    456	v4l2_fh_exit(&fh->fh);
    457	kfree(fh);
    458
    459	return 0;
    460}
    461
    462static struct
    463saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
    464{
    465	struct saa7164_user_buffer *ubuf = NULL;
    466	struct saa7164_dev *dev = port->dev;
    467	u32 crc;
    468
    469	mutex_lock(&port->dmaqueue_lock);
    470	if (!list_empty(&port->list_buf_used.list)) {
    471		ubuf = list_first_entry(&port->list_buf_used.list,
    472			struct saa7164_user_buffer, list);
    473
    474		if (crc_checking) {
    475			crc = crc32(0, ubuf->data, ubuf->actual_size);
    476			if (crc != ubuf->crc) {
    477				printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
    478					__func__,
    479					ubuf, ubuf->crc, crc);
    480			}
    481		}
    482
    483	}
    484	mutex_unlock(&port->dmaqueue_lock);
    485
    486	dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
    487
    488	return ubuf;
    489}
    490
    491static ssize_t fops_read(struct file *file, char __user *buffer,
    492	size_t count, loff_t *pos)
    493{
    494	struct saa7164_vbi_fh *fh = file->private_data;
    495	struct saa7164_port *port = fh->port;
    496	struct saa7164_user_buffer *ubuf = NULL;
    497	struct saa7164_dev *dev = port->dev;
    498	int ret = 0;
    499	int rem, cnt;
    500	u8 *p;
    501
    502	port->last_read_msecs_diff = port->last_read_msecs;
    503	port->last_read_msecs = jiffies_to_msecs(jiffies);
    504	port->last_read_msecs_diff = port->last_read_msecs -
    505		port->last_read_msecs_diff;
    506
    507	saa7164_histogram_update(&port->read_interval,
    508		port->last_read_msecs_diff);
    509
    510	if (*pos) {
    511		printk(KERN_ERR "%s() ESPIPE\n", __func__);
    512		return -ESPIPE;
    513	}
    514
    515	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
    516		if (atomic_inc_return(&port->v4l_reader_count) == 1) {
    517
    518			if (saa7164_vbi_initialize(port) < 0) {
    519				printk(KERN_ERR "%s() EINVAL\n", __func__);
    520				return -EINVAL;
    521			}
    522
    523			saa7164_vbi_start_streaming(port);
    524			msleep(200);
    525		}
    526	}
    527
    528	/* blocking wait for buffer */
    529	if ((file->f_flags & O_NONBLOCK) == 0) {
    530		if (wait_event_interruptible(port->wait_read,
    531			saa7164_vbi_next_buf(port))) {
    532				printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
    533				return -ERESTARTSYS;
    534		}
    535	}
    536
    537	/* Pull the first buffer from the used list */
    538	ubuf = saa7164_vbi_next_buf(port);
    539
    540	while ((count > 0) && ubuf) {
    541
    542		/* set remaining bytes to copy */
    543		rem = ubuf->actual_size - ubuf->pos;
    544		cnt = rem > count ? count : rem;
    545
    546		p = ubuf->data + ubuf->pos;
    547
    548		dprintk(DBGLVL_VBI,
    549			"%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
    550			__func__, (int)count, cnt, rem, ubuf, ubuf->pos);
    551
    552		if (copy_to_user(buffer, p, cnt)) {
    553			printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
    554			if (!ret) {
    555				printk(KERN_ERR "%s() EFAULT\n", __func__);
    556				ret = -EFAULT;
    557			}
    558			goto err;
    559		}
    560
    561		ubuf->pos += cnt;
    562		count -= cnt;
    563		buffer += cnt;
    564		ret += cnt;
    565
    566		if (ubuf->pos > ubuf->actual_size)
    567			printk(KERN_ERR "read() pos > actual, huh?\n");
    568
    569		if (ubuf->pos == ubuf->actual_size) {
    570
    571			/* finished with current buffer, take next buffer */
    572
    573			/* Requeue the buffer on the free list */
    574			ubuf->pos = 0;
    575
    576			mutex_lock(&port->dmaqueue_lock);
    577			list_move_tail(&ubuf->list, &port->list_buf_free.list);
    578			mutex_unlock(&port->dmaqueue_lock);
    579
    580			/* Dequeue next */
    581			if ((file->f_flags & O_NONBLOCK) == 0) {
    582				if (wait_event_interruptible(port->wait_read,
    583					saa7164_vbi_next_buf(port))) {
    584						break;
    585				}
    586			}
    587			ubuf = saa7164_vbi_next_buf(port);
    588		}
    589	}
    590err:
    591	if (!ret && !ubuf) {
    592		printk(KERN_ERR "%s() EAGAIN\n", __func__);
    593		ret = -EAGAIN;
    594	}
    595
    596	return ret;
    597}
    598
    599static __poll_t fops_poll(struct file *file, poll_table *wait)
    600{
    601	struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
    602	struct saa7164_port *port = fh->port;
    603	__poll_t mask = 0;
    604
    605	port->last_poll_msecs_diff = port->last_poll_msecs;
    606	port->last_poll_msecs = jiffies_to_msecs(jiffies);
    607	port->last_poll_msecs_diff = port->last_poll_msecs -
    608		port->last_poll_msecs_diff;
    609
    610	saa7164_histogram_update(&port->poll_interval,
    611		port->last_poll_msecs_diff);
    612
    613	if (!video_is_registered(port->v4l_device))
    614		return EPOLLERR;
    615
    616	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
    617		if (atomic_inc_return(&port->v4l_reader_count) == 1) {
    618			if (saa7164_vbi_initialize(port) < 0)
    619				return EPOLLERR;
    620			saa7164_vbi_start_streaming(port);
    621			msleep(200);
    622		}
    623	}
    624
    625	/* blocking wait for buffer */
    626	if ((file->f_flags & O_NONBLOCK) == 0) {
    627		if (wait_event_interruptible(port->wait_read,
    628			saa7164_vbi_next_buf(port))) {
    629				return EPOLLERR;
    630		}
    631	}
    632
    633	/* Pull the first buffer from the used list */
    634	if (!list_empty(&port->list_buf_used.list))
    635		mask |= EPOLLIN | EPOLLRDNORM;
    636
    637	return mask;
    638}
    639static const struct v4l2_file_operations vbi_fops = {
    640	.owner		= THIS_MODULE,
    641	.open		= fops_open,
    642	.release	= fops_release,
    643	.read		= fops_read,
    644	.poll		= fops_poll,
    645	.unlocked_ioctl	= video_ioctl2,
    646};
    647
    648static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
    649	.vidioc_s_std		 = vidioc_s_std,
    650	.vidioc_g_std		 = vidioc_g_std,
    651	.vidioc_enum_input	 = saa7164_enum_input,
    652	.vidioc_g_input		 = vidioc_g_input,
    653	.vidioc_s_input		 = vidioc_s_input,
    654	.vidioc_g_tuner		 = saa7164_g_tuner,
    655	.vidioc_s_tuner		 = saa7164_s_tuner,
    656	.vidioc_g_frequency	 = vidioc_g_frequency,
    657	.vidioc_s_frequency	 = vidioc_s_frequency,
    658	.vidioc_querycap	 = vidioc_querycap,
    659	.vidioc_g_fmt_vbi_cap	 = saa7164_vbi_fmt,
    660	.vidioc_try_fmt_vbi_cap	 = saa7164_vbi_fmt,
    661	.vidioc_s_fmt_vbi_cap	 = saa7164_vbi_fmt,
    662};
    663
    664static struct video_device saa7164_vbi_template = {
    665	.name          = "saa7164",
    666	.fops          = &vbi_fops,
    667	.ioctl_ops     = &vbi_ioctl_ops,
    668	.minor         = -1,
    669	.tvnorms       = SAA7164_NORMS,
    670	.device_caps   = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE |
    671			 V4L2_CAP_TUNER,
    672};
    673
    674static struct video_device *saa7164_vbi_alloc(
    675	struct saa7164_port *port,
    676	struct pci_dev *pci,
    677	struct video_device *template,
    678	char *type)
    679{
    680	struct video_device *vfd;
    681	struct saa7164_dev *dev = port->dev;
    682
    683	dprintk(DBGLVL_VBI, "%s()\n", __func__);
    684
    685	vfd = video_device_alloc();
    686	if (NULL == vfd)
    687		return NULL;
    688
    689	*vfd = *template;
    690	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
    691		type, saa7164_boards[dev->board].name);
    692
    693	vfd->v4l2_dev  = &dev->v4l2_dev;
    694	vfd->release = video_device_release;
    695	return vfd;
    696}
    697
    698int saa7164_vbi_register(struct saa7164_port *port)
    699{
    700	struct saa7164_dev *dev = port->dev;
    701	int result = -ENODEV;
    702
    703	dprintk(DBGLVL_VBI, "%s()\n", __func__);
    704
    705	BUG_ON(port->type != SAA7164_MPEG_VBI);
    706
    707	/* Sanity check that the PCI configuration space is active */
    708	if (port->hwcfg.BARLocation == 0) {
    709		printk(KERN_ERR "%s() failed (errno = %d), NO PCI configuration\n",
    710			__func__, result);
    711		result = -ENOMEM;
    712		goto failed;
    713	}
    714
    715	/* Establish VBI defaults here */
    716
    717	/* Allocate and register the video device node */
    718	port->v4l_device = saa7164_vbi_alloc(port,
    719		dev->pci, &saa7164_vbi_template, "vbi");
    720
    721	if (!port->v4l_device) {
    722		printk(KERN_INFO "%s: can't allocate vbi device\n",
    723			dev->name);
    724		result = -ENOMEM;
    725		goto failed;
    726	}
    727
    728	port->enc_port = &dev->ports[port->nr - 2];
    729	video_set_drvdata(port->v4l_device, port);
    730	result = video_register_device(port->v4l_device,
    731		VFL_TYPE_VBI, -1);
    732	if (result < 0) {
    733		printk(KERN_INFO "%s: can't register vbi device\n",
    734			dev->name);
    735		/* TODO: We're going to leak here if we don't dealloc
    736		 The buffers above. The unreg function can't deal wit it.
    737		*/
    738		goto failed;
    739	}
    740
    741	printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
    742		dev->name, port->v4l_device->num);
    743
    744	/* Configure the hardware defaults */
    745
    746	result = 0;
    747failed:
    748	return result;
    749}
    750
    751void saa7164_vbi_unregister(struct saa7164_port *port)
    752{
    753	struct saa7164_dev *dev = port->dev;
    754
    755	dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
    756
    757	BUG_ON(port->type != SAA7164_MPEG_VBI);
    758
    759	if (port->v4l_device) {
    760		if (port->v4l_device->minor != -1)
    761			video_unregister_device(port->v4l_device);
    762		else
    763			video_device_release(port->v4l_device);
    764
    765		port->v4l_device = NULL;
    766	}
    767
    768}