162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci bttv - Bt848 frame grabber driver 562306a36Sopenharmony_ci vbi interface 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci (c) 2002 Gerd Knorr <kraxel@bytesex.org> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at> 1062306a36Sopenharmony_ci Sponsored by OPQ Systems AB 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci*/ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/errno.h> 1862306a36Sopenharmony_ci#include <linux/fs.h> 1962306a36Sopenharmony_ci#include <linux/kernel.h> 2062306a36Sopenharmony_ci#include <linux/interrupt.h> 2162306a36Sopenharmony_ci#include <linux/kdev_t.h> 2262306a36Sopenharmony_ci#include <media/v4l2-ioctl.h> 2362306a36Sopenharmony_ci#include <asm/io.h> 2462306a36Sopenharmony_ci#include "bttvp.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* Offset from line sync pulse leading edge (0H) to start of VBI capture, 2762306a36Sopenharmony_ci in fCLKx2 pixels. According to the datasheet, VBI capture starts 2862306a36Sopenharmony_ci VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET 2962306a36Sopenharmony_ci is 64 fCLKx1 pixels wide. VBI_HDELAY is set to 0, so this should be 3062306a36Sopenharmony_ci (64 + 0) * 2 = 128 fCLKx2 pixels. But it's not! The datasheet is 3162306a36Sopenharmony_ci Just Plain Wrong. The real value appears to be different for 3262306a36Sopenharmony_ci different revisions of the bt8x8 chips, and to be affected by the 3362306a36Sopenharmony_ci horizontal scaling factor. Experimentally, the value is measured 3462306a36Sopenharmony_ci to be about 244. */ 3562306a36Sopenharmony_ci#define VBI_OFFSET 244 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic unsigned int vbibufs = 4; 3862306a36Sopenharmony_cistatic unsigned int vbi_debug; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cimodule_param(vbibufs, int, 0444); 4162306a36Sopenharmony_cimodule_param(vbi_debug, int, 0644); 4262306a36Sopenharmony_ciMODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4"); 4362306a36Sopenharmony_ciMODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)"); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#ifdef dprintk 4662306a36Sopenharmony_ci# undef dprintk 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci#define dprintk(fmt, ...) \ 4962306a36Sopenharmony_cido { \ 5062306a36Sopenharmony_ci if (vbi_debug) \ 5162306a36Sopenharmony_ci pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__); \ 5262306a36Sopenharmony_ci} while (0) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define IMAGE_SIZE(fmt) \ 5562306a36Sopenharmony_ci (((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* ----------------------------------------------------------------------- */ 5862306a36Sopenharmony_ci/* vbi risc code + mm */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic int queue_setup_vbi(struct vb2_queue *q, unsigned int *num_buffers, 6162306a36Sopenharmony_ci unsigned int *num_planes, unsigned int sizes[], 6262306a36Sopenharmony_ci struct device *alloc_devs[]) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct bttv *btv = vb2_get_drv_priv(q); 6562306a36Sopenharmony_ci unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (*num_planes) 6862306a36Sopenharmony_ci return sizes[0] < size ? -EINVAL : 0; 6962306a36Sopenharmony_ci *num_planes = 1; 7062306a36Sopenharmony_ci sizes[0] = size; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return 0; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic void buf_queue_vbi(struct vb2_buffer *vb) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 7862306a36Sopenharmony_ci struct vb2_queue *vq = vb->vb2_queue; 7962306a36Sopenharmony_ci struct bttv *btv = vb2_get_drv_priv(vq); 8062306a36Sopenharmony_ci struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf); 8162306a36Sopenharmony_ci unsigned long flags; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci spin_lock_irqsave(&btv->s_lock, flags); 8462306a36Sopenharmony_ci if (list_empty(&btv->vcapture)) { 8562306a36Sopenharmony_ci btv->loop_irq = BT848_RISC_VBI; 8662306a36Sopenharmony_ci if (vb2_is_streaming(&btv->capq)) 8762306a36Sopenharmony_ci btv->loop_irq |= BT848_RISC_VIDEO; 8862306a36Sopenharmony_ci bttv_set_dma(btv, BT848_CAP_CTL_CAPTURE_VBI_ODD | 8962306a36Sopenharmony_ci BT848_CAP_CTL_CAPTURE_VBI_EVEN); 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci list_add_tail(&buf->list, &btv->vcapture); 9262306a36Sopenharmony_ci spin_unlock_irqrestore(&btv->s_lock, flags); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int buf_prepare_vbi(struct vb2_buffer *vb) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci int ret = 0; 9862306a36Sopenharmony_ci struct vb2_queue *vq = vb->vb2_queue; 9962306a36Sopenharmony_ci struct bttv *btv = vb2_get_drv_priv(vq); 10062306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 10162306a36Sopenharmony_ci struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf); 10262306a36Sopenharmony_ci unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (vb2_plane_size(vb, 0) < size) 10562306a36Sopenharmony_ci return -EINVAL; 10662306a36Sopenharmony_ci vb2_set_plane_payload(vb, 0, size); 10762306a36Sopenharmony_ci buf->vbuf.field = V4L2_FIELD_NONE; 10862306a36Sopenharmony_ci ret = bttv_buffer_risc_vbi(btv, buf); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return ret; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic void buf_cleanup_vbi(struct vb2_buffer *vb) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 11662306a36Sopenharmony_ci struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf); 11762306a36Sopenharmony_ci struct vb2_queue *vq = vb->vb2_queue; 11862306a36Sopenharmony_ci struct bttv *btv = vb2_get_drv_priv(vq); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci btcx_riscmem_free(btv->c.pci, &buf->top); 12162306a36Sopenharmony_ci btcx_riscmem_free(btv->c.pci, &buf->bottom); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic int start_streaming_vbi(struct vb2_queue *q, unsigned int count) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci int seqnr = 0; 12762306a36Sopenharmony_ci struct bttv_buffer *buf; 12862306a36Sopenharmony_ci struct bttv *btv = vb2_get_drv_priv(q); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci btv->framedrop = 0; 13162306a36Sopenharmony_ci if (!check_alloc_btres_lock(btv, RESOURCE_VBI)) { 13262306a36Sopenharmony_ci if (btv->field_count) 13362306a36Sopenharmony_ci seqnr++; 13462306a36Sopenharmony_ci while (!list_empty(&btv->vcapture)) { 13562306a36Sopenharmony_ci buf = list_entry(btv->vcapture.next, 13662306a36Sopenharmony_ci struct bttv_buffer, list); 13762306a36Sopenharmony_ci list_del(&buf->list); 13862306a36Sopenharmony_ci buf->vbuf.sequence = (btv->field_count >> 1) + seqnr++; 13962306a36Sopenharmony_ci vb2_buffer_done(&buf->vbuf.vb2_buf, 14062306a36Sopenharmony_ci VB2_BUF_STATE_QUEUED); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci return -EBUSY; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci if (!vb2_is_streaming(&btv->capq)) { 14562306a36Sopenharmony_ci init_irqreg(btv); 14662306a36Sopenharmony_ci btv->field_count = 0; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci return 0; 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic void stop_streaming_vbi(struct vb2_queue *q) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci struct bttv *btv = vb2_get_drv_priv(q); 15462306a36Sopenharmony_ci unsigned long flags; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci vb2_wait_for_all_buffers(q); 15762306a36Sopenharmony_ci spin_lock_irqsave(&btv->s_lock, flags); 15862306a36Sopenharmony_ci free_btres_lock(btv, RESOURCE_VBI); 15962306a36Sopenharmony_ci if (!vb2_is_streaming(&btv->capq)) { 16062306a36Sopenharmony_ci /* stop field counter */ 16162306a36Sopenharmony_ci btand(~BT848_INT_VSYNC, BT848_INT_MASK); 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci spin_unlock_irqrestore(&btv->s_lock, flags); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciconst struct vb2_ops bttv_vbi_qops = { 16762306a36Sopenharmony_ci .queue_setup = queue_setup_vbi, 16862306a36Sopenharmony_ci .buf_queue = buf_queue_vbi, 16962306a36Sopenharmony_ci .buf_prepare = buf_prepare_vbi, 17062306a36Sopenharmony_ci .buf_cleanup = buf_cleanup_vbi, 17162306a36Sopenharmony_ci .start_streaming = start_streaming_vbi, 17262306a36Sopenharmony_ci .stop_streaming = stop_streaming_vbi, 17362306a36Sopenharmony_ci .wait_prepare = vb2_ops_wait_prepare, 17462306a36Sopenharmony_ci .wait_finish = vb2_ops_wait_finish, 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/* ----------------------------------------------------------------------- */ 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm, 18062306a36Sopenharmony_ci __s32 crop_start) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci __s32 min_start, max_start, max_end, f2_offset; 18362306a36Sopenharmony_ci unsigned int i; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* For compatibility with earlier driver versions we must pretend 18662306a36Sopenharmony_ci the VBI and video capture window may overlap. In reality RISC 18762306a36Sopenharmony_ci magic aborts VBI capturing at the first line of video capturing, 18862306a36Sopenharmony_ci leaving the rest of the buffer unchanged, usually all zero. 18962306a36Sopenharmony_ci VBI capturing must always start before video capturing. >> 1 19062306a36Sopenharmony_ci because cropping counts field lines times two. */ 19162306a36Sopenharmony_ci min_start = tvnorm->vbistart[0]; 19262306a36Sopenharmony_ci max_start = (crop_start >> 1) - 1; 19362306a36Sopenharmony_ci max_end = (tvnorm->cropcap.bounds.top 19462306a36Sopenharmony_ci + tvnorm->cropcap.bounds.height) >> 1; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (min_start > max_start) 19762306a36Sopenharmony_ci return -EBUSY; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci WARN_ON(max_start >= max_end); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci f->sampling_rate = tvnorm->Fsc; 20262306a36Sopenharmony_ci f->samples_per_line = VBI_BPL; 20362306a36Sopenharmony_ci f->sample_format = V4L2_PIX_FMT_GREY; 20462306a36Sopenharmony_ci f->offset = VBI_OFFSET; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0]; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci for (i = 0; i < 2; ++i) { 20962306a36Sopenharmony_ci if (0 == f->count[i]) { 21062306a36Sopenharmony_ci /* No data from this field. We leave f->start[i] 21162306a36Sopenharmony_ci alone because VIDIOCSVBIFMT is w/o and EINVALs 21262306a36Sopenharmony_ci when a driver does not support exactly the 21362306a36Sopenharmony_ci requested parameters. */ 21462306a36Sopenharmony_ci } else { 21562306a36Sopenharmony_ci s64 start, count; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci start = clamp(f->start[i], min_start, max_start); 21862306a36Sopenharmony_ci /* s64 to prevent overflow. */ 21962306a36Sopenharmony_ci count = (s64) f->start[i] + f->count[i] - start; 22062306a36Sopenharmony_ci f->start[i] = start; 22162306a36Sopenharmony_ci f->count[i] = clamp(count, (s64) 1, 22262306a36Sopenharmony_ci max_end - start); 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci min_start += f2_offset; 22662306a36Sopenharmony_ci max_start += f2_offset; 22762306a36Sopenharmony_ci max_end += f2_offset; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (0 == (f->count[0] | f->count[1])) { 23162306a36Sopenharmony_ci /* As in earlier driver versions. */ 23262306a36Sopenharmony_ci f->start[0] = tvnorm->vbistart[0]; 23362306a36Sopenharmony_ci f->start[1] = tvnorm->vbistart[1]; 23462306a36Sopenharmony_ci f->count[0] = 1; 23562306a36Sopenharmony_ci f->count[1] = 1; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci f->flags = 0; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci f->reserved[0] = 0; 24162306a36Sopenharmony_ci f->reserved[1] = 0; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return 0; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ciint bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct bttv *btv = video_drvdata(file); 24962306a36Sopenharmony_ci const struct bttv_tvnorm *tvnorm; 25062306a36Sopenharmony_ci __s32 crop_start; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci mutex_lock(&btv->lock); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci tvnorm = &bttv_tvnorms[btv->tvnorm]; 25562306a36Sopenharmony_ci crop_start = btv->crop_start; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci mutex_unlock(&btv->lock); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return try_fmt(&frt->fmt.vbi, tvnorm, crop_start); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ciint bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci struct bttv *btv = video_drvdata(file); 26662306a36Sopenharmony_ci const struct bttv_tvnorm *tvnorm; 26762306a36Sopenharmony_ci __s32 start1, end; 26862306a36Sopenharmony_ci int rc; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci mutex_lock(&btv->lock); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci rc = -EBUSY; 27362306a36Sopenharmony_ci if (btv->resources & RESOURCE_VBI) 27462306a36Sopenharmony_ci goto fail; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci tvnorm = &bttv_tvnorms[btv->tvnorm]; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start); 27962306a36Sopenharmony_ci if (0 != rc) 28062306a36Sopenharmony_ci goto fail; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] + 28362306a36Sopenharmony_ci tvnorm->vbistart[0]; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* First possible line of video capturing. Should be 28662306a36Sopenharmony_ci max(f->start[0] + f->count[0], start1 + f->count[1]) * 2 28762306a36Sopenharmony_ci when capturing both fields. But for compatibility we must 28862306a36Sopenharmony_ci pretend the VBI and video capture window may overlap, 28962306a36Sopenharmony_ci so end = start + 1, the lowest possible value, times two 29062306a36Sopenharmony_ci because vbi_fmt.end counts field lines times two. */ 29162306a36Sopenharmony_ci end = max(frt->fmt.vbi.start[0], start1) * 2 + 2; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci btv->vbi_fmt.fmt = frt->fmt.vbi; 29462306a36Sopenharmony_ci btv->vbi_fmt.tvnorm = tvnorm; 29562306a36Sopenharmony_ci btv->vbi_fmt.end = end; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci rc = 0; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci fail: 30062306a36Sopenharmony_ci mutex_unlock(&btv->lock); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return rc; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ciint bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci const struct bttv_tvnorm *tvnorm; 30962306a36Sopenharmony_ci struct bttv *btv = video_drvdata(file); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci frt->fmt.vbi = btv->vbi_fmt.fmt; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci tvnorm = &bttv_tvnorms[btv->tvnorm]; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (tvnorm != btv->vbi_fmt.tvnorm) { 31662306a36Sopenharmony_ci __s32 max_end; 31762306a36Sopenharmony_ci unsigned int i; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* As in vbi_buffer_prepare() this imitates the 32062306a36Sopenharmony_ci behaviour of earlier driver versions after video 32162306a36Sopenharmony_ci standard changes, with default parameters anyway. */ 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci max_end = (tvnorm->cropcap.bounds.top 32462306a36Sopenharmony_ci + tvnorm->cropcap.bounds.height) >> 1; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci frt->fmt.vbi.sampling_rate = tvnorm->Fsc; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci for (i = 0; i < 2; ++i) { 32962306a36Sopenharmony_ci __s32 new_start; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci new_start = frt->fmt.vbi.start[i] + tvnorm->vbistart[i] 33262306a36Sopenharmony_ci - btv->vbi_fmt.tvnorm->vbistart[i]; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci frt->fmt.vbi.start[i] = min(new_start, max_end - 1); 33562306a36Sopenharmony_ci frt->fmt.vbi.count[i] = 33662306a36Sopenharmony_ci min((__s32) frt->fmt.vbi.count[i], 33762306a36Sopenharmony_ci max_end - frt->fmt.vbi.start[i]); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci max_end += tvnorm->vbistart[1] 34062306a36Sopenharmony_ci - tvnorm->vbistart[0]; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci return 0; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_civoid bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci const struct bttv_tvnorm *tvnorm; 34962306a36Sopenharmony_ci unsigned int real_samples_per_line; 35062306a36Sopenharmony_ci unsigned int real_count; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci tvnorm = &bttv_tvnorms[norm]; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci f->fmt.sampling_rate = tvnorm->Fsc; 35562306a36Sopenharmony_ci f->fmt.samples_per_line = VBI_BPL; 35662306a36Sopenharmony_ci f->fmt.sample_format = V4L2_PIX_FMT_GREY; 35762306a36Sopenharmony_ci f->fmt.offset = VBI_OFFSET; 35862306a36Sopenharmony_ci f->fmt.start[0] = tvnorm->vbistart[0]; 35962306a36Sopenharmony_ci f->fmt.start[1] = tvnorm->vbistart[1]; 36062306a36Sopenharmony_ci f->fmt.count[0] = VBI_DEFLINES; 36162306a36Sopenharmony_ci f->fmt.count[1] = VBI_DEFLINES; 36262306a36Sopenharmony_ci f->fmt.flags = 0; 36362306a36Sopenharmony_ci f->fmt.reserved[0] = 0; 36462306a36Sopenharmony_ci f->fmt.reserved[1] = 0; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* For compatibility the buffer size must be 2 * VBI_DEFLINES * 36762306a36Sopenharmony_ci VBI_BPL regardless of the current video standard. */ 36862306a36Sopenharmony_ci real_samples_per_line = 1024 + tvnorm->vbipack * 4; 36962306a36Sopenharmony_ci real_count = ((tvnorm->cropcap.defrect.top >> 1) 37062306a36Sopenharmony_ci - tvnorm->vbistart[0]); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci WARN_ON(real_samples_per_line > VBI_BPL); 37362306a36Sopenharmony_ci WARN_ON(real_count > VBI_DEFLINES); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci f->tvnorm = tvnorm; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* See bttv_vbi_fmt_set(). */ 37862306a36Sopenharmony_ci f->end = tvnorm->vbistart[0] * 2 + 2; 37962306a36Sopenharmony_ci} 380