1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/module.h>
27#include <linux/errno.h>
28#include <linux/fs.h>
29#include <linux/kernel.h>
30#include <linux/interrupt.h>
31#include <linux/kdev_t.h>
32#include <media/v4l2-ioctl.h>
33#include <asm/io.h>
34#include "bttvp.h"
35
36
37
38
39
40
41
42
43
44
45#define VBI_OFFSET 244
46
47
48
49
50
51
52#define VBI_BPL 2048
53
54
55#define VBI_DEFLINES 16
56
57static unsigned int vbibufs = 4;
58static unsigned int vbi_debug;
59
60module_param(vbibufs, int, 0444);
61module_param(vbi_debug, int, 0644);
62MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4");
63MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
64
65#ifdef dprintk
66# undef dprintk
67#endif
68#define dprintk(fmt, arg...) if (vbi_debug) \
69 printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
70
71#define IMAGE_SIZE(fmt) \
72 (((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
73
74
75
76
77static int vbi_buffer_setup(struct videobuf_queue *q,
78 unsigned int *count, unsigned int *size)
79{
80 struct bttv_fh *fh = q->priv_data;
81 struct bttv *btv = fh->btv;
82
83 if (0 == *count)
84 *count = vbibufs;
85
86 *size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
87
88 dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
89 fh->vbi_fmt.fmt.samples_per_line,
90 fh->vbi_fmt.fmt.start[0],
91 fh->vbi_fmt.fmt.start[1],
92 fh->vbi_fmt.fmt.count[0],
93 fh->vbi_fmt.fmt.count[1]);
94
95 return 0;
96}
97
98static int vbi_buffer_prepare(struct videobuf_queue *q,
99 struct videobuf_buffer *vb,
100 enum v4l2_field field)
101{
102 struct bttv_fh *fh = q->priv_data;
103 struct bttv *btv = fh->btv;
104 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
105 const struct bttv_tvnorm *tvnorm;
106 unsigned int skip_lines0, skip_lines1, min_vdelay;
107 int redo_dma_risc;
108 int rc;
109
110 buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
111 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
112 return -EINVAL;
113
114 tvnorm = fh->vbi_fmt.tvnorm;
115
116
117
118
119
120
121
122
123 skip_lines0 = 0;
124 skip_lines1 = 0;
125
126 if (fh->vbi_fmt.fmt.count[0] > 0)
127 skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
128 - tvnorm->vbistart[0]));
129 if (fh->vbi_fmt.fmt.count[1] > 0)
130 skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
131 - tvnorm->vbistart[1]));
132
133 redo_dma_risc = 0;
134
135 if (buf->vbi_skip[0] != skip_lines0 ||
136 buf->vbi_skip[1] != skip_lines1 ||
137 buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
138 buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
139 buf->vbi_skip[0] = skip_lines0;
140 buf->vbi_skip[1] = skip_lines1;
141 buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
142 buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
143 redo_dma_risc = 1;
144 }
145
146 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
147 redo_dma_risc = 1;
148 if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
149 goto fail;
150 }
151
152 if (redo_dma_risc) {
153 unsigned int bpl, padding, offset;
154 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
155
156 bpl = 2044;
157 padding = VBI_BPL - bpl;
158
159 if (fh->vbi_fmt.fmt.count[0] > 0) {
160 rc = bttv_risc_packed(btv, &buf->top,
161 dma->sglist,
162 0, bpl,
163 padding, skip_lines0,
164 fh->vbi_fmt.fmt.count[0]);
165 if (0 != rc)
166 goto fail;
167 }
168
169 if (fh->vbi_fmt.fmt.count[1] > 0) {
170 offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
171
172 rc = bttv_risc_packed(btv, &buf->bottom,
173 dma->sglist,
174 offset, bpl,
175 padding, skip_lines1,
176 fh->vbi_fmt.fmt.count[1]);
177 if (0 != rc)
178 goto fail;
179 }
180 }
181
182
183
184
185
186 min_vdelay = MIN_VDELAY;
187 if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
188 min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
189
190
191 buf->geo.vdelay = min_vdelay;
192
193 buf->vb.state = VIDEOBUF_PREPARED;
194 buf->vb.field = field;
195 dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
196 vb, &buf->top, &buf->bottom,
197 v4l2_field_names[buf->vb.field]);
198 return 0;
199
200 fail:
201 bttv_dma_free(q,btv,buf);
202 return rc;
203}
204
205static void
206vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
207{
208 struct bttv_fh *fh = q->priv_data;
209 struct bttv *btv = fh->btv;
210 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
211
212 dprintk("queue %p\n",vb);
213 buf->vb.state = VIDEOBUF_QUEUED;
214 list_add_tail(&buf->vb.queue,&btv->vcapture);
215 if (NULL == btv->cvbi) {
216 fh->btv->loop_irq |= 4;
217 bttv_set_dma(btv,0x0c);
218 }
219}
220
221static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
222{
223 struct bttv_fh *fh = q->priv_data;
224 struct bttv *btv = fh->btv;
225 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
226
227 dprintk("free %p\n",vb);
228 bttv_dma_free(q,fh->btv,buf);
229}
230
231struct videobuf_queue_ops bttv_vbi_qops = {
232 .buf_setup = vbi_buffer_setup,
233 .buf_prepare = vbi_buffer_prepare,
234 .buf_queue = vbi_buffer_queue,
235 .buf_release = vbi_buffer_release,
236};
237
238
239
240static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
241 __s32 crop_start)
242{
243 __s32 min_start, max_start, max_end, f2_offset;
244 unsigned int i;
245
246
247
248
249
250
251
252 min_start = tvnorm->vbistart[0];
253 max_start = (crop_start >> 1) - 1;
254 max_end = (tvnorm->cropcap.bounds.top
255 + tvnorm->cropcap.bounds.height) >> 1;
256
257 if (min_start > max_start)
258 return -EBUSY;
259
260 BUG_ON(max_start >= max_end);
261
262 f->sampling_rate = tvnorm->Fsc;
263 f->samples_per_line = VBI_BPL;
264 f->sample_format = V4L2_PIX_FMT_GREY;
265 f->offset = VBI_OFFSET;
266
267 f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
268
269 for (i = 0; i < 2; ++i) {
270 if (0 == f->count[i]) {
271
272
273
274
275 } else {
276 s64 start, count;
277
278 start = clamp(f->start[i], min_start, max_start);
279
280 count = (s64) f->start[i] + f->count[i] - start;
281 f->start[i] = start;
282 f->count[i] = clamp(count, (s64) 1,
283 max_end - start);
284 }
285
286 min_start += f2_offset;
287 max_start += f2_offset;
288 max_end += f2_offset;
289 }
290
291 if (0 == (f->count[0] | f->count[1])) {
292
293 f->start[0] = tvnorm->vbistart[0];
294 f->start[1] = tvnorm->vbistart[1];
295 f->count[0] = 1;
296 f->count[1] = 1;
297 }
298
299 f->flags = 0;
300
301 f->reserved[0] = 0;
302 f->reserved[1] = 0;
303
304 return 0;
305}
306
307int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
308{
309 struct bttv_fh *fh = f;
310 struct bttv *btv = fh->btv;
311 const struct bttv_tvnorm *tvnorm;
312 __s32 crop_start;
313
314 mutex_lock(&btv->lock);
315
316 tvnorm = &bttv_tvnorms[btv->tvnorm];
317 crop_start = btv->crop_start;
318
319 mutex_unlock(&btv->lock);
320
321 return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
322}
323
324
325int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
326{
327 struct bttv_fh *fh = f;
328 struct bttv *btv = fh->btv;
329 const struct bttv_tvnorm *tvnorm;
330 __s32 start1, end;
331 int rc;
332
333 mutex_lock(&btv->lock);
334
335 rc = -EBUSY;
336 if (fh->resources & RESOURCE_VBI)
337 goto fail;
338
339 tvnorm = &bttv_tvnorms[btv->tvnorm];
340
341 rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
342 if (0 != rc)
343 goto fail;
344
345 start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
346 tvnorm->vbistart[0];
347
348
349
350
351
352
353
354 end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
355
356 mutex_lock(&fh->vbi.vb_lock);
357
358 fh->vbi_fmt.fmt = frt->fmt.vbi;
359 fh->vbi_fmt.tvnorm = tvnorm;
360 fh->vbi_fmt.end = end;
361
362 mutex_unlock(&fh->vbi.vb_lock);
363
364 rc = 0;
365
366 fail:
367 mutex_unlock(&btv->lock);
368
369 return rc;
370}
371
372
373int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
374{
375 struct bttv_fh *fh = f;
376 const struct bttv_tvnorm *tvnorm;
377
378 frt->fmt.vbi = fh->vbi_fmt.fmt;
379
380 tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
381
382 if (tvnorm != fh->vbi_fmt.tvnorm) {
383 __s32 max_end;
384 unsigned int i;
385
386
387
388
389
390 max_end = (tvnorm->cropcap.bounds.top
391 + tvnorm->cropcap.bounds.height) >> 1;
392
393 frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
394
395 for (i = 0; i < 2; ++i) {
396 __s32 new_start;
397
398 new_start = frt->fmt.vbi.start[i]
399 + tvnorm->vbistart[i]
400 - fh->vbi_fmt.tvnorm->vbistart[i];
401
402 frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
403 frt->fmt.vbi.count[i] =
404 min((__s32) frt->fmt.vbi.count[i],
405 max_end - frt->fmt.vbi.start[i]);
406
407 max_end += tvnorm->vbistart[1]
408 - tvnorm->vbistart[0];
409 }
410 }
411 return 0;
412}
413
414void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
415{
416 const struct bttv_tvnorm *tvnorm;
417 unsigned int real_samples_per_line;
418 unsigned int real_count;
419
420 tvnorm = &bttv_tvnorms[norm];
421
422 f->fmt.sampling_rate = tvnorm->Fsc;
423 f->fmt.samples_per_line = VBI_BPL;
424 f->fmt.sample_format = V4L2_PIX_FMT_GREY;
425 f->fmt.offset = VBI_OFFSET;
426 f->fmt.start[0] = tvnorm->vbistart[0];
427 f->fmt.start[1] = tvnorm->vbistart[1];
428 f->fmt.count[0] = VBI_DEFLINES;
429 f->fmt.count[1] = VBI_DEFLINES;
430 f->fmt.flags = 0;
431 f->fmt.reserved[0] = 0;
432 f->fmt.reserved[1] = 0;
433
434
435
436 real_samples_per_line = 1024 + tvnorm->vbipack * 4;
437 real_count = ((tvnorm->cropcap.defrect.top >> 1)
438 - tvnorm->vbistart[0]);
439
440 BUG_ON(real_samples_per_line > VBI_BPL);
441 BUG_ON(real_count > VBI_DEFLINES);
442
443 f->tvnorm = tvnorm;
444
445
446 f->end = tvnorm->vbistart[0] * 2 + 2;
447}
448
449
450
451
452
453
454
455