xref: /openbmc/linux/drivers/media/pci/bt8xx/bttv-vbi.c (revision 1188f7f111c61394ec56beb8e30322305a8220b6)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
268de959fSMauro Carvalho Chehab /*
368de959fSMauro Carvalho Chehab 
468de959fSMauro Carvalho Chehab     bttv - Bt848 frame grabber driver
568de959fSMauro Carvalho Chehab     vbi interface
668de959fSMauro Carvalho Chehab 
768de959fSMauro Carvalho Chehab     (c) 2002 Gerd Knorr <kraxel@bytesex.org>
868de959fSMauro Carvalho Chehab 
968de959fSMauro Carvalho Chehab     Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
1068de959fSMauro Carvalho Chehab     Sponsored by OPQ Systems AB
1168de959fSMauro Carvalho Chehab 
1268de959fSMauro Carvalho Chehab */
1368de959fSMauro Carvalho Chehab 
1468de959fSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1568de959fSMauro Carvalho Chehab 
1668de959fSMauro Carvalho Chehab #include <linux/module.h>
1768de959fSMauro Carvalho Chehab #include <linux/errno.h>
1868de959fSMauro Carvalho Chehab #include <linux/fs.h>
1968de959fSMauro Carvalho Chehab #include <linux/kernel.h>
2068de959fSMauro Carvalho Chehab #include <linux/interrupt.h>
2168de959fSMauro Carvalho Chehab #include <linux/kdev_t.h>
2268de959fSMauro Carvalho Chehab #include <media/v4l2-ioctl.h>
2368de959fSMauro Carvalho Chehab #include <asm/io.h>
2468de959fSMauro Carvalho Chehab #include "bttvp.h"
2568de959fSMauro Carvalho Chehab 
2668de959fSMauro Carvalho Chehab /* Offset from line sync pulse leading edge (0H) to start of VBI capture,
2768de959fSMauro Carvalho Chehab    in fCLKx2 pixels.  According to the datasheet, VBI capture starts
2868de959fSMauro Carvalho Chehab    VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
2968de959fSMauro Carvalho Chehab    is 64 fCLKx1 pixels wide.  VBI_HDELAY is set to 0, so this should be
3068de959fSMauro Carvalho Chehab    (64 + 0) * 2 = 128 fCLKx2 pixels.  But it's not!  The datasheet is
3168de959fSMauro Carvalho Chehab    Just Plain Wrong.  The real value appears to be different for
3268de959fSMauro Carvalho Chehab    different revisions of the bt8x8 chips, and to be affected by the
3368de959fSMauro Carvalho Chehab    horizontal scaling factor.  Experimentally, the value is measured
3468de959fSMauro Carvalho Chehab    to be about 244.  */
3568de959fSMauro Carvalho Chehab #define VBI_OFFSET 244
3668de959fSMauro Carvalho Chehab 
3768de959fSMauro Carvalho Chehab static unsigned int vbibufs = 4;
3868de959fSMauro Carvalho Chehab static unsigned int vbi_debug;
3968de959fSMauro Carvalho Chehab 
4068de959fSMauro Carvalho Chehab module_param(vbibufs,   int, 0444);
4168de959fSMauro Carvalho Chehab module_param(vbi_debug, int, 0644);
4268de959fSMauro Carvalho Chehab MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4");
4368de959fSMauro Carvalho Chehab MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
4468de959fSMauro Carvalho Chehab 
4568de959fSMauro Carvalho Chehab #ifdef dprintk
4668de959fSMauro Carvalho Chehab # undef dprintk
4768de959fSMauro Carvalho Chehab #endif
4868de959fSMauro Carvalho Chehab #define dprintk(fmt, ...)						\
4968de959fSMauro Carvalho Chehab do {									\
5068de959fSMauro Carvalho Chehab 	if (vbi_debug)							\
5168de959fSMauro Carvalho Chehab 		pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__);		\
5268de959fSMauro Carvalho Chehab } while (0)
5368de959fSMauro Carvalho Chehab 
5468de959fSMauro Carvalho Chehab #define IMAGE_SIZE(fmt) \
5568de959fSMauro Carvalho Chehab 	(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
5668de959fSMauro Carvalho Chehab 
5768de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
5868de959fSMauro Carvalho Chehab /* vbi risc code + mm                                                      */
5968de959fSMauro Carvalho Chehab 
queue_setup_vbi(struct vb2_queue * q,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_devs[])60b7ec3212SDeborah Brouwer static int queue_setup_vbi(struct vb2_queue *q, unsigned int *num_buffers,
61b7ec3212SDeborah Brouwer 			   unsigned int *num_planes, unsigned int sizes[],
62b7ec3212SDeborah Brouwer 			   struct device *alloc_devs[])
6368de959fSMauro Carvalho Chehab {
64b7ec3212SDeborah Brouwer 	struct bttv *btv = vb2_get_drv_priv(q);
65b7ec3212SDeborah Brouwer 	unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
6668de959fSMauro Carvalho Chehab 
67b7ec3212SDeborah Brouwer 	if (*num_planes)
68b7ec3212SDeborah Brouwer 		return sizes[0] < size ? -EINVAL : 0;
69b7ec3212SDeborah Brouwer 	*num_planes = 1;
70b7ec3212SDeborah Brouwer 	sizes[0] = size;
7168de959fSMauro Carvalho Chehab 
7268de959fSMauro Carvalho Chehab 	return 0;
7368de959fSMauro Carvalho Chehab }
7468de959fSMauro Carvalho Chehab 
buf_queue_vbi(struct vb2_buffer * vb)75b7ec3212SDeborah Brouwer static void buf_queue_vbi(struct vb2_buffer *vb)
7668de959fSMauro Carvalho Chehab {
77b7ec3212SDeborah Brouwer 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
78b7ec3212SDeborah Brouwer 	struct vb2_queue *vq = vb->vb2_queue;
79b7ec3212SDeborah Brouwer 	struct bttv *btv = vb2_get_drv_priv(vq);
80b7ec3212SDeborah Brouwer 	struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
81b7ec3212SDeborah Brouwer 	unsigned long flags;
8268de959fSMauro Carvalho Chehab 
83b7ec3212SDeborah Brouwer 	spin_lock_irqsave(&btv->s_lock, flags);
84b7ec3212SDeborah Brouwer 	if (list_empty(&btv->vcapture)) {
85b7ec3212SDeborah Brouwer 		btv->loop_irq = BT848_RISC_VBI;
86b7ec3212SDeborah Brouwer 		if (vb2_is_streaming(&btv->capq))
87b7ec3212SDeborah Brouwer 			btv->loop_irq |= BT848_RISC_VIDEO;
88b7ec3212SDeborah Brouwer 		bttv_set_dma(btv, BT848_CAP_CTL_CAPTURE_VBI_ODD |
89b7ec3212SDeborah Brouwer 			     BT848_CAP_CTL_CAPTURE_VBI_EVEN);
90b7ec3212SDeborah Brouwer 	}
91b7ec3212SDeborah Brouwer 	list_add_tail(&buf->list, &btv->vcapture);
92b7ec3212SDeborah Brouwer 	spin_unlock_irqrestore(&btv->s_lock, flags);
93b7ec3212SDeborah Brouwer }
94b7ec3212SDeborah Brouwer 
buf_prepare_vbi(struct vb2_buffer * vb)95b7ec3212SDeborah Brouwer static int buf_prepare_vbi(struct vb2_buffer *vb)
96b7ec3212SDeborah Brouwer {
97b7ec3212SDeborah Brouwer 	int ret = 0;
98b7ec3212SDeborah Brouwer 	struct vb2_queue *vq = vb->vb2_queue;
99b7ec3212SDeborah Brouwer 	struct bttv *btv = vb2_get_drv_priv(vq);
100b7ec3212SDeborah Brouwer 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
101b7ec3212SDeborah Brouwer 	struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
102b7ec3212SDeborah Brouwer 	unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
103b7ec3212SDeborah Brouwer 
104b7ec3212SDeborah Brouwer 	if (vb2_plane_size(vb, 0) < size)
10568de959fSMauro Carvalho Chehab 		return -EINVAL;
106b7ec3212SDeborah Brouwer 	vb2_set_plane_payload(vb, 0, size);
107b7ec3212SDeborah Brouwer 	buf->vbuf.field = V4L2_FIELD_NONE;
108b7ec3212SDeborah Brouwer 	ret = bttv_buffer_risc_vbi(btv, buf);
10968de959fSMauro Carvalho Chehab 
110b7ec3212SDeborah Brouwer 	return ret;
11168de959fSMauro Carvalho Chehab }
11268de959fSMauro Carvalho Chehab 
buf_cleanup_vbi(struct vb2_buffer * vb)113b7ec3212SDeborah Brouwer static void buf_cleanup_vbi(struct vb2_buffer *vb)
11468de959fSMauro Carvalho Chehab {
115b7ec3212SDeborah Brouwer 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
116b7ec3212SDeborah Brouwer 	struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
117b7ec3212SDeborah Brouwer 	struct vb2_queue *vq = vb->vb2_queue;
118b7ec3212SDeborah Brouwer 	struct bttv *btv = vb2_get_drv_priv(vq);
11968de959fSMauro Carvalho Chehab 
120b7ec3212SDeborah Brouwer 	btcx_riscmem_free(btv->c.pci, &buf->top);
121b7ec3212SDeborah Brouwer 	btcx_riscmem_free(btv->c.pci, &buf->bottom);
12268de959fSMauro Carvalho Chehab }
12368de959fSMauro Carvalho Chehab 
start_streaming_vbi(struct vb2_queue * q,unsigned int count)124b7ec3212SDeborah Brouwer static int start_streaming_vbi(struct vb2_queue *q, unsigned int count)
12568de959fSMauro Carvalho Chehab {
126b7ec3212SDeborah Brouwer 	int seqnr = 0;
127b7ec3212SDeborah Brouwer 	struct bttv_buffer *buf;
128b7ec3212SDeborah Brouwer 	struct bttv *btv = vb2_get_drv_priv(q);
12968de959fSMauro Carvalho Chehab 
130b7ec3212SDeborah Brouwer 	btv->framedrop = 0;
131*e8fa30faSHans Verkuil 	if (!check_alloc_btres_lock(btv, RESOURCE_VBI)) {
132b7ec3212SDeborah Brouwer 		if (btv->field_count)
133b7ec3212SDeborah Brouwer 			seqnr++;
134b7ec3212SDeborah Brouwer 		while (!list_empty(&btv->vcapture)) {
135b7ec3212SDeborah Brouwer 			buf = list_entry(btv->vcapture.next,
136b7ec3212SDeborah Brouwer 					 struct bttv_buffer, list);
137b7ec3212SDeborah Brouwer 			list_del(&buf->list);
138b7ec3212SDeborah Brouwer 			buf->vbuf.sequence = (btv->field_count >> 1) + seqnr++;
139b7ec3212SDeborah Brouwer 			vb2_buffer_done(&buf->vbuf.vb2_buf,
140b7ec3212SDeborah Brouwer 					VB2_BUF_STATE_QUEUED);
141b7ec3212SDeborah Brouwer 		}
142*e8fa30faSHans Verkuil 		return -EBUSY;
143b7ec3212SDeborah Brouwer 	}
144b7ec3212SDeborah Brouwer 	if (!vb2_is_streaming(&btv->capq)) {
145b7ec3212SDeborah Brouwer 		init_irqreg(btv);
146b7ec3212SDeborah Brouwer 		btv->field_count = 0;
147b7ec3212SDeborah Brouwer 	}
148*e8fa30faSHans Verkuil 	return 0;
14968de959fSMauro Carvalho Chehab }
15068de959fSMauro Carvalho Chehab 
stop_streaming_vbi(struct vb2_queue * q)151b7ec3212SDeborah Brouwer static void stop_streaming_vbi(struct vb2_queue *q)
152b7ec3212SDeborah Brouwer {
153b7ec3212SDeborah Brouwer 	struct bttv *btv = vb2_get_drv_priv(q);
154b7ec3212SDeborah Brouwer 	unsigned long flags;
155b7ec3212SDeborah Brouwer 
156b7ec3212SDeborah Brouwer 	vb2_wait_for_all_buffers(q);
157b7ec3212SDeborah Brouwer 	spin_lock_irqsave(&btv->s_lock, flags);
158b7ec3212SDeborah Brouwer 	free_btres_lock(btv, RESOURCE_VBI);
159b7ec3212SDeborah Brouwer 	if (!vb2_is_streaming(&btv->capq)) {
160b7ec3212SDeborah Brouwer 		/* stop field counter */
161b7ec3212SDeborah Brouwer 		btand(~BT848_INT_VSYNC, BT848_INT_MASK);
162b7ec3212SDeborah Brouwer 	}
163b7ec3212SDeborah Brouwer 	spin_unlock_irqrestore(&btv->s_lock, flags);
164b7ec3212SDeborah Brouwer }
165b7ec3212SDeborah Brouwer 
166b7ec3212SDeborah Brouwer const struct vb2_ops bttv_vbi_qops = {
167b7ec3212SDeborah Brouwer 	.queue_setup    = queue_setup_vbi,
168b7ec3212SDeborah Brouwer 	.buf_queue      = buf_queue_vbi,
169b7ec3212SDeborah Brouwer 	.buf_prepare    = buf_prepare_vbi,
170b7ec3212SDeborah Brouwer 	.buf_cleanup	= buf_cleanup_vbi,
171b7ec3212SDeborah Brouwer 	.start_streaming = start_streaming_vbi,
172b7ec3212SDeborah Brouwer 	.stop_streaming = stop_streaming_vbi,
173b7ec3212SDeborah Brouwer 	.wait_prepare   = vb2_ops_wait_prepare,
174b7ec3212SDeborah Brouwer 	.wait_finish    = vb2_ops_wait_finish,
17568de959fSMauro Carvalho Chehab };
17668de959fSMauro Carvalho Chehab 
17768de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
17868de959fSMauro Carvalho Chehab 
try_fmt(struct v4l2_vbi_format * f,const struct bttv_tvnorm * tvnorm,__s32 crop_start)17968de959fSMauro Carvalho Chehab static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
18068de959fSMauro Carvalho Chehab 			__s32 crop_start)
18168de959fSMauro Carvalho Chehab {
18268de959fSMauro Carvalho Chehab 	__s32 min_start, max_start, max_end, f2_offset;
18368de959fSMauro Carvalho Chehab 	unsigned int i;
18468de959fSMauro Carvalho Chehab 
18568de959fSMauro Carvalho Chehab 	/* For compatibility with earlier driver versions we must pretend
18668de959fSMauro Carvalho Chehab 	   the VBI and video capture window may overlap. In reality RISC
18768de959fSMauro Carvalho Chehab 	   magic aborts VBI capturing at the first line of video capturing,
18868de959fSMauro Carvalho Chehab 	   leaving the rest of the buffer unchanged, usually all zero.
18968de959fSMauro Carvalho Chehab 	   VBI capturing must always start before video capturing. >> 1
19068de959fSMauro Carvalho Chehab 	   because cropping counts field lines times two. */
19168de959fSMauro Carvalho Chehab 	min_start = tvnorm->vbistart[0];
19268de959fSMauro Carvalho Chehab 	max_start = (crop_start >> 1) - 1;
19368de959fSMauro Carvalho Chehab 	max_end = (tvnorm->cropcap.bounds.top
19468de959fSMauro Carvalho Chehab 		   + tvnorm->cropcap.bounds.height) >> 1;
19568de959fSMauro Carvalho Chehab 
19668de959fSMauro Carvalho Chehab 	if (min_start > max_start)
19768de959fSMauro Carvalho Chehab 		return -EBUSY;
19868de959fSMauro Carvalho Chehab 
199615c5450SDeborah Brouwer 	WARN_ON(max_start >= max_end);
20068de959fSMauro Carvalho Chehab 
20168de959fSMauro Carvalho Chehab 	f->sampling_rate    = tvnorm->Fsc;
20268de959fSMauro Carvalho Chehab 	f->samples_per_line = VBI_BPL;
20368de959fSMauro Carvalho Chehab 	f->sample_format    = V4L2_PIX_FMT_GREY;
20468de959fSMauro Carvalho Chehab 	f->offset           = VBI_OFFSET;
20568de959fSMauro Carvalho Chehab 
20668de959fSMauro Carvalho Chehab 	f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
20768de959fSMauro Carvalho Chehab 
20868de959fSMauro Carvalho Chehab 	for (i = 0; i < 2; ++i) {
20968de959fSMauro Carvalho Chehab 		if (0 == f->count[i]) {
21068de959fSMauro Carvalho Chehab 			/* No data from this field. We leave f->start[i]
21168de959fSMauro Carvalho Chehab 			   alone because VIDIOCSVBIFMT is w/o and EINVALs
21268de959fSMauro Carvalho Chehab 			   when a driver does not support exactly the
21368de959fSMauro Carvalho Chehab 			   requested parameters. */
21468de959fSMauro Carvalho Chehab 		} else {
21568de959fSMauro Carvalho Chehab 			s64 start, count;
21668de959fSMauro Carvalho Chehab 
21768de959fSMauro Carvalho Chehab 			start = clamp(f->start[i], min_start, max_start);
21868de959fSMauro Carvalho Chehab 			/* s64 to prevent overflow. */
21968de959fSMauro Carvalho Chehab 			count = (s64) f->start[i] + f->count[i] - start;
22068de959fSMauro Carvalho Chehab 			f->start[i] = start;
22168de959fSMauro Carvalho Chehab 			f->count[i] = clamp(count, (s64) 1,
22268de959fSMauro Carvalho Chehab 					    max_end - start);
22368de959fSMauro Carvalho Chehab 		}
22468de959fSMauro Carvalho Chehab 
22568de959fSMauro Carvalho Chehab 		min_start += f2_offset;
22668de959fSMauro Carvalho Chehab 		max_start += f2_offset;
22768de959fSMauro Carvalho Chehab 		max_end += f2_offset;
22868de959fSMauro Carvalho Chehab 	}
22968de959fSMauro Carvalho Chehab 
23068de959fSMauro Carvalho Chehab 	if (0 == (f->count[0] | f->count[1])) {
23168de959fSMauro Carvalho Chehab 		/* As in earlier driver versions. */
23268de959fSMauro Carvalho Chehab 		f->start[0] = tvnorm->vbistart[0];
23368de959fSMauro Carvalho Chehab 		f->start[1] = tvnorm->vbistart[1];
23468de959fSMauro Carvalho Chehab 		f->count[0] = 1;
23568de959fSMauro Carvalho Chehab 		f->count[1] = 1;
23668de959fSMauro Carvalho Chehab 	}
23768de959fSMauro Carvalho Chehab 
23868de959fSMauro Carvalho Chehab 	f->flags = 0;
23968de959fSMauro Carvalho Chehab 
24068de959fSMauro Carvalho Chehab 	f->reserved[0] = 0;
24168de959fSMauro Carvalho Chehab 	f->reserved[1] = 0;
24268de959fSMauro Carvalho Chehab 
24368de959fSMauro Carvalho Chehab 	return 0;
24468de959fSMauro Carvalho Chehab }
24568de959fSMauro Carvalho Chehab 
bttv_try_fmt_vbi_cap(struct file * file,void * f,struct v4l2_format * frt)24668de959fSMauro Carvalho Chehab int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
24768de959fSMauro Carvalho Chehab {
248d1846d72SDeborah Brouwer 	struct bttv *btv = video_drvdata(file);
24968de959fSMauro Carvalho Chehab 	const struct bttv_tvnorm *tvnorm;
25068de959fSMauro Carvalho Chehab 	__s32 crop_start;
25168de959fSMauro Carvalho Chehab 
25268de959fSMauro Carvalho Chehab 	mutex_lock(&btv->lock);
25368de959fSMauro Carvalho Chehab 
25468de959fSMauro Carvalho Chehab 	tvnorm = &bttv_tvnorms[btv->tvnorm];
25568de959fSMauro Carvalho Chehab 	crop_start = btv->crop_start;
25668de959fSMauro Carvalho Chehab 
25768de959fSMauro Carvalho Chehab 	mutex_unlock(&btv->lock);
25868de959fSMauro Carvalho Chehab 
25968de959fSMauro Carvalho Chehab 	return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
26068de959fSMauro Carvalho Chehab }
26168de959fSMauro Carvalho Chehab 
26268de959fSMauro Carvalho Chehab 
bttv_s_fmt_vbi_cap(struct file * file,void * f,struct v4l2_format * frt)26368de959fSMauro Carvalho Chehab int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
26468de959fSMauro Carvalho Chehab {
265d1846d72SDeborah Brouwer 	struct bttv *btv = video_drvdata(file);
26668de959fSMauro Carvalho Chehab 	const struct bttv_tvnorm *tvnorm;
26768de959fSMauro Carvalho Chehab 	__s32 start1, end;
26868de959fSMauro Carvalho Chehab 	int rc;
26968de959fSMauro Carvalho Chehab 
27068de959fSMauro Carvalho Chehab 	mutex_lock(&btv->lock);
27168de959fSMauro Carvalho Chehab 
27268de959fSMauro Carvalho Chehab 	rc = -EBUSY;
273b7ec3212SDeborah Brouwer 	if (btv->resources & RESOURCE_VBI)
27468de959fSMauro Carvalho Chehab 		goto fail;
27568de959fSMauro Carvalho Chehab 
27668de959fSMauro Carvalho Chehab 	tvnorm = &bttv_tvnorms[btv->tvnorm];
27768de959fSMauro Carvalho Chehab 
27868de959fSMauro Carvalho Chehab 	rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
27968de959fSMauro Carvalho Chehab 	if (0 != rc)
28068de959fSMauro Carvalho Chehab 		goto fail;
28168de959fSMauro Carvalho Chehab 
28268de959fSMauro Carvalho Chehab 	start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
28368de959fSMauro Carvalho Chehab 		tvnorm->vbistart[0];
28468de959fSMauro Carvalho Chehab 
28568de959fSMauro Carvalho Chehab 	/* First possible line of video capturing. Should be
28668de959fSMauro Carvalho Chehab 	   max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
28768de959fSMauro Carvalho Chehab 	   when capturing both fields. But for compatibility we must
28868de959fSMauro Carvalho Chehab 	   pretend the VBI and video capture window may overlap,
28968de959fSMauro Carvalho Chehab 	   so end = start + 1, the lowest possible value, times two
29068de959fSMauro Carvalho Chehab 	   because vbi_fmt.end counts field lines times two. */
29168de959fSMauro Carvalho Chehab 	end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
29268de959fSMauro Carvalho Chehab 
293faebe84eSDeborah Brouwer 	btv->vbi_fmt.fmt = frt->fmt.vbi;
294faebe84eSDeborah Brouwer 	btv->vbi_fmt.tvnorm = tvnorm;
295faebe84eSDeborah Brouwer 	btv->vbi_fmt.end = end;
29668de959fSMauro Carvalho Chehab 
29768de959fSMauro Carvalho Chehab 	rc = 0;
29868de959fSMauro Carvalho Chehab 
29968de959fSMauro Carvalho Chehab  fail:
30068de959fSMauro Carvalho Chehab 	mutex_unlock(&btv->lock);
30168de959fSMauro Carvalho Chehab 
30268de959fSMauro Carvalho Chehab 	return rc;
30368de959fSMauro Carvalho Chehab }
30468de959fSMauro Carvalho Chehab 
30568de959fSMauro Carvalho Chehab 
bttv_g_fmt_vbi_cap(struct file * file,void * f,struct v4l2_format * frt)30668de959fSMauro Carvalho Chehab int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
30768de959fSMauro Carvalho Chehab {
30868de959fSMauro Carvalho Chehab 	const struct bttv_tvnorm *tvnorm;
309d1846d72SDeborah Brouwer 	struct bttv *btv = video_drvdata(file);
31068de959fSMauro Carvalho Chehab 
311faebe84eSDeborah Brouwer 	frt->fmt.vbi = btv->vbi_fmt.fmt;
31268de959fSMauro Carvalho Chehab 
313d1846d72SDeborah Brouwer 	tvnorm = &bttv_tvnorms[btv->tvnorm];
31468de959fSMauro Carvalho Chehab 
315faebe84eSDeborah Brouwer 	if (tvnorm != btv->vbi_fmt.tvnorm) {
31668de959fSMauro Carvalho Chehab 		__s32 max_end;
31768de959fSMauro Carvalho Chehab 		unsigned int i;
31868de959fSMauro Carvalho Chehab 
31968de959fSMauro Carvalho Chehab 		/* As in vbi_buffer_prepare() this imitates the
32068de959fSMauro Carvalho Chehab 		   behaviour of earlier driver versions after video
32168de959fSMauro Carvalho Chehab 		   standard changes, with default parameters anyway. */
32268de959fSMauro Carvalho Chehab 
32368de959fSMauro Carvalho Chehab 		max_end = (tvnorm->cropcap.bounds.top
32468de959fSMauro Carvalho Chehab 			   + tvnorm->cropcap.bounds.height) >> 1;
32568de959fSMauro Carvalho Chehab 
32668de959fSMauro Carvalho Chehab 		frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
32768de959fSMauro Carvalho Chehab 
32868de959fSMauro Carvalho Chehab 		for (i = 0; i < 2; ++i) {
32968de959fSMauro Carvalho Chehab 			__s32 new_start;
33068de959fSMauro Carvalho Chehab 
331faebe84eSDeborah Brouwer 			new_start = frt->fmt.vbi.start[i] + tvnorm->vbistart[i]
332faebe84eSDeborah Brouwer 				- btv->vbi_fmt.tvnorm->vbistart[i];
33368de959fSMauro Carvalho Chehab 
33468de959fSMauro Carvalho Chehab 			frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
33568de959fSMauro Carvalho Chehab 			frt->fmt.vbi.count[i] =
33668de959fSMauro Carvalho Chehab 				min((__s32) frt->fmt.vbi.count[i],
33768de959fSMauro Carvalho Chehab 					  max_end - frt->fmt.vbi.start[i]);
33868de959fSMauro Carvalho Chehab 
33968de959fSMauro Carvalho Chehab 			max_end += tvnorm->vbistart[1]
34068de959fSMauro Carvalho Chehab 				- tvnorm->vbistart[0];
34168de959fSMauro Carvalho Chehab 		}
34268de959fSMauro Carvalho Chehab 	}
34368de959fSMauro Carvalho Chehab 	return 0;
34468de959fSMauro Carvalho Chehab }
34568de959fSMauro Carvalho Chehab 
bttv_vbi_fmt_reset(struct bttv_vbi_fmt * f,unsigned int norm)34668de959fSMauro Carvalho Chehab void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
34768de959fSMauro Carvalho Chehab {
34868de959fSMauro Carvalho Chehab 	const struct bttv_tvnorm *tvnorm;
34968de959fSMauro Carvalho Chehab 	unsigned int real_samples_per_line;
35068de959fSMauro Carvalho Chehab 	unsigned int real_count;
35168de959fSMauro Carvalho Chehab 
35268de959fSMauro Carvalho Chehab 	tvnorm = &bttv_tvnorms[norm];
35368de959fSMauro Carvalho Chehab 
35468de959fSMauro Carvalho Chehab 	f->fmt.sampling_rate    = tvnorm->Fsc;
35568de959fSMauro Carvalho Chehab 	f->fmt.samples_per_line = VBI_BPL;
35668de959fSMauro Carvalho Chehab 	f->fmt.sample_format    = V4L2_PIX_FMT_GREY;
35768de959fSMauro Carvalho Chehab 	f->fmt.offset           = VBI_OFFSET;
35868de959fSMauro Carvalho Chehab 	f->fmt.start[0]		= tvnorm->vbistart[0];
35968de959fSMauro Carvalho Chehab 	f->fmt.start[1]		= tvnorm->vbistart[1];
36068de959fSMauro Carvalho Chehab 	f->fmt.count[0]		= VBI_DEFLINES;
36168de959fSMauro Carvalho Chehab 	f->fmt.count[1]		= VBI_DEFLINES;
36268de959fSMauro Carvalho Chehab 	f->fmt.flags            = 0;
36368de959fSMauro Carvalho Chehab 	f->fmt.reserved[0]      = 0;
36468de959fSMauro Carvalho Chehab 	f->fmt.reserved[1]      = 0;
36568de959fSMauro Carvalho Chehab 
36668de959fSMauro Carvalho Chehab 	/* For compatibility the buffer size must be 2 * VBI_DEFLINES *
36768de959fSMauro Carvalho Chehab 	   VBI_BPL regardless of the current video standard. */
36868de959fSMauro Carvalho Chehab 	real_samples_per_line   = 1024 + tvnorm->vbipack * 4;
36968de959fSMauro Carvalho Chehab 	real_count              = ((tvnorm->cropcap.defrect.top >> 1)
37068de959fSMauro Carvalho Chehab 				   - tvnorm->vbistart[0]);
37168de959fSMauro Carvalho Chehab 
372615c5450SDeborah Brouwer 	WARN_ON(real_samples_per_line > VBI_BPL);
373615c5450SDeborah Brouwer 	WARN_ON(real_count > VBI_DEFLINES);
37468de959fSMauro Carvalho Chehab 
37568de959fSMauro Carvalho Chehab 	f->tvnorm               = tvnorm;
37668de959fSMauro Carvalho Chehab 
37768de959fSMauro Carvalho Chehab 	/* See bttv_vbi_fmt_set(). */
37868de959fSMauro Carvalho Chehab 	f->end                  = tvnorm->vbistart[0] * 2 + 2;
37968de959fSMauro Carvalho Chehab }
380