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