diff options
Diffstat (limited to 'drivers/media/video/cx231xx/cx231xx-vbi.c')
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-vbi.c | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c new file mode 100644 index 000000000000..94180526909c --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c | |||
@@ -0,0 +1,701 @@ | |||
1 | /* | ||
2 | cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on cx88 driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/bitmap.h> | ||
27 | #include <linux/usb.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/version.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/mutex.h> | ||
32 | |||
33 | #include <media/v4l2-common.h> | ||
34 | #include <media/v4l2-ioctl.h> | ||
35 | #include <media/v4l2-chip-ident.h> | ||
36 | #include <media/msp3400.h> | ||
37 | #include <media/tuner.h> | ||
38 | |||
39 | #include "cx231xx.h" | ||
40 | #include "cx231xx-vbi.h" | ||
41 | |||
42 | static inline void print_err_status(struct cx231xx *dev, int packet, int status) | ||
43 | { | ||
44 | char *errmsg = "Unknown"; | ||
45 | |||
46 | switch (status) { | ||
47 | case -ENOENT: | ||
48 | errmsg = "unlinked synchronuously"; | ||
49 | break; | ||
50 | case -ECONNRESET: | ||
51 | errmsg = "unlinked asynchronuously"; | ||
52 | break; | ||
53 | case -ENOSR: | ||
54 | errmsg = "Buffer error (overrun)"; | ||
55 | break; | ||
56 | case -EPIPE: | ||
57 | errmsg = "Stalled (device not responding)"; | ||
58 | break; | ||
59 | case -EOVERFLOW: | ||
60 | errmsg = "Babble (bad cable?)"; | ||
61 | break; | ||
62 | case -EPROTO: | ||
63 | errmsg = "Bit-stuff error (bad cable?)"; | ||
64 | break; | ||
65 | case -EILSEQ: | ||
66 | errmsg = "CRC/Timeout (could be anything)"; | ||
67 | break; | ||
68 | case -ETIME: | ||
69 | errmsg = "Device does not respond"; | ||
70 | break; | ||
71 | } | ||
72 | if (packet < 0) { | ||
73 | cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status, | ||
74 | errmsg); | ||
75 | } else { | ||
76 | cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n", | ||
77 | packet, status, errmsg); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Controls the isoc copy of each urb packet | ||
83 | */ | ||
84 | static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) | ||
85 | { | ||
86 | struct cx231xx_buffer *buf; | ||
87 | struct cx231xx_dmaqueue *dma_q = urb->context; | ||
88 | int rc = 1; | ||
89 | unsigned char *p_buffer; | ||
90 | u32 bytes_parsed = 0, buffer_size = 0; | ||
91 | u8 sav_eav = 0; | ||
92 | |||
93 | if (!dev) | ||
94 | return 0; | ||
95 | |||
96 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | ||
97 | return 0; | ||
98 | |||
99 | if (urb->status < 0) { | ||
100 | print_err_status(dev, -1, urb->status); | ||
101 | if (urb->status == -ENOENT) | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
106 | |||
107 | /* get buffer pointer and length */ | ||
108 | p_buffer = urb->transfer_buffer; | ||
109 | buffer_size = urb->actual_length; | ||
110 | |||
111 | if (buffer_size > 0) { | ||
112 | bytes_parsed = 0; | ||
113 | |||
114 | if (dma_q->is_partial_line) { | ||
115 | /* Handle the case where we were working on a partial | ||
116 | line */ | ||
117 | sav_eav = dma_q->last_sav; | ||
118 | } else { | ||
119 | /* Check for a SAV/EAV overlapping the | ||
120 | buffer boundary */ | ||
121 | |||
122 | sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, | ||
123 | dma_q->partial_buf, | ||
124 | &bytes_parsed); | ||
125 | } | ||
126 | |||
127 | sav_eav &= 0xF0; | ||
128 | /* Get the first line if we have some portion of an SAV/EAV from | ||
129 | the last buffer or a partial line */ | ||
130 | if (sav_eav) { | ||
131 | bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, | ||
132 | sav_eav, /* SAV/EAV */ | ||
133 | p_buffer + bytes_parsed, /* p_buffer */ | ||
134 | buffer_size - bytes_parsed); /* buffer size */ | ||
135 | } | ||
136 | |||
137 | /* Now parse data that is completely in this buffer */ | ||
138 | dma_q->is_partial_line = 0; | ||
139 | |||
140 | while (bytes_parsed < buffer_size) { | ||
141 | u32 bytes_used = 0; | ||
142 | |||
143 | sav_eav = cx231xx_find_next_SAV_EAV( | ||
144 | p_buffer + bytes_parsed, /* p_buffer */ | ||
145 | buffer_size - bytes_parsed, /* buffer size */ | ||
146 | &bytes_used); /* bytes used to get SAV/EAV */ | ||
147 | |||
148 | bytes_parsed += bytes_used; | ||
149 | |||
150 | sav_eav &= 0xF0; | ||
151 | if (sav_eav && (bytes_parsed < buffer_size)) { | ||
152 | bytes_parsed += cx231xx_get_vbi_line(dev, | ||
153 | dma_q, sav_eav, /* SAV/EAV */ | ||
154 | p_buffer+bytes_parsed, /* p_buffer */ | ||
155 | buffer_size-bytes_parsed);/*buf size*/ | ||
156 | } | ||
157 | } | ||
158 | |||
159 | /* Save the last four bytes of the buffer so we can | ||
160 | check the buffer boundary condition next time */ | ||
161 | memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); | ||
162 | bytes_parsed = 0; | ||
163 | } | ||
164 | |||
165 | return rc; | ||
166 | } | ||
167 | |||
168 | /* ------------------------------------------------------------------ | ||
169 | Vbi buf operations | ||
170 | ------------------------------------------------------------------*/ | ||
171 | |||
172 | static int | ||
173 | vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, | ||
174 | unsigned int *size) | ||
175 | { | ||
176 | struct cx231xx_fh *fh = vq->priv_data; | ||
177 | struct cx231xx *dev = fh->dev; | ||
178 | u32 height = 0; | ||
179 | |||
180 | height = ((dev->norm & V4L2_STD_625_50) ? | ||
181 | PAL_VBI_LINES : NTSC_VBI_LINES); | ||
182 | |||
183 | *size = (dev->width * height * 2); | ||
184 | if (0 == *count) | ||
185 | *count = CX231XX_DEF_VBI_BUF; | ||
186 | |||
187 | if (*count < CX231XX_MIN_BUF) | ||
188 | *count = CX231XX_MIN_BUF; | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | /* This is called *without* dev->slock held; please keep it that way */ | ||
194 | static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) | ||
195 | { | ||
196 | struct cx231xx_fh *fh = vq->priv_data; | ||
197 | struct cx231xx *dev = fh->dev; | ||
198 | unsigned long flags = 0; | ||
199 | if (in_interrupt()) | ||
200 | BUG(); | ||
201 | |||
202 | /* We used to wait for the buffer to finish here, but this didn't work | ||
203 | because, as we were keeping the state as VIDEOBUF_QUEUED, | ||
204 | videobuf_queue_cancel marked it as finished for us. | ||
205 | (Also, it could wedge forever if the hardware was misconfigured.) | ||
206 | |||
207 | This should be safe; by the time we get here, the buffer isn't | ||
208 | queued anymore. If we ever start marking the buffers as | ||
209 | VIDEOBUF_ACTIVE, it won't be, though. | ||
210 | */ | ||
211 | spin_lock_irqsave(&dev->vbi_mode.slock, flags); | ||
212 | if (dev->vbi_mode.isoc_ctl.buf == buf) | ||
213 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
214 | spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); | ||
215 | |||
216 | videobuf_vmalloc_free(&buf->vb); | ||
217 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
218 | } | ||
219 | |||
220 | static int | ||
221 | vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | ||
222 | enum v4l2_field field) | ||
223 | { | ||
224 | struct cx231xx_fh *fh = vq->priv_data; | ||
225 | struct cx231xx_buffer *buf = | ||
226 | container_of(vb, struct cx231xx_buffer, vb); | ||
227 | struct cx231xx *dev = fh->dev; | ||
228 | int rc = 0, urb_init = 0; | ||
229 | u32 height = 0; | ||
230 | |||
231 | height = ((dev->norm & V4L2_STD_625_50) ? | ||
232 | PAL_VBI_LINES : NTSC_VBI_LINES); | ||
233 | buf->vb.size = ((dev->width << 1) * height); | ||
234 | |||
235 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
236 | return -EINVAL; | ||
237 | |||
238 | buf->vb.width = dev->width; | ||
239 | buf->vb.height = height; | ||
240 | buf->vb.field = field; | ||
241 | buf->vb.field = V4L2_FIELD_SEQ_TB; | ||
242 | |||
243 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
244 | rc = videobuf_iolock(vq, &buf->vb, NULL); | ||
245 | if (rc < 0) | ||
246 | goto fail; | ||
247 | } | ||
248 | |||
249 | if (!dev->vbi_mode.isoc_ctl.num_bufs) | ||
250 | urb_init = 1; | ||
251 | |||
252 | if (urb_init) { | ||
253 | rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, | ||
254 | CX231XX_NUM_VBI_BUFS, | ||
255 | dev->vbi_mode.alt_max_pkt_size[0], | ||
256 | cx231xx_isoc_vbi_copy); | ||
257 | if (rc < 0) | ||
258 | goto fail; | ||
259 | } | ||
260 | |||
261 | buf->vb.state = VIDEOBUF_PREPARED; | ||
262 | return 0; | ||
263 | |||
264 | fail: | ||
265 | free_buffer(vq, buf); | ||
266 | return rc; | ||
267 | } | ||
268 | |||
269 | static void | ||
270 | vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
271 | { | ||
272 | struct cx231xx_buffer *buf = | ||
273 | container_of(vb, struct cx231xx_buffer, vb); | ||
274 | struct cx231xx_fh *fh = vq->priv_data; | ||
275 | struct cx231xx *dev = fh->dev; | ||
276 | struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; | ||
277 | |||
278 | buf->vb.state = VIDEOBUF_QUEUED; | ||
279 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
280 | |||
281 | } | ||
282 | |||
283 | static void vbi_buffer_release(struct videobuf_queue *vq, | ||
284 | struct videobuf_buffer *vb) | ||
285 | { | ||
286 | struct cx231xx_buffer *buf = | ||
287 | container_of(vb, struct cx231xx_buffer, vb); | ||
288 | |||
289 | |||
290 | free_buffer(vq, buf); | ||
291 | } | ||
292 | |||
293 | struct videobuf_queue_ops cx231xx_vbi_qops = { | ||
294 | .buf_setup = vbi_buffer_setup, | ||
295 | .buf_prepare = vbi_buffer_prepare, | ||
296 | .buf_queue = vbi_buffer_queue, | ||
297 | .buf_release = vbi_buffer_release, | ||
298 | }; | ||
299 | |||
300 | /* ------------------------------------------------------------------ | ||
301 | URB control | ||
302 | ------------------------------------------------------------------*/ | ||
303 | |||
304 | /* | ||
305 | * IRQ callback, called by URB callback | ||
306 | */ | ||
307 | static void cx231xx_irq_vbi_callback(struct urb *urb) | ||
308 | { | ||
309 | struct cx231xx_dmaqueue *dma_q = urb->context; | ||
310 | struct cx231xx_video_mode *vmode = | ||
311 | container_of(dma_q, struct cx231xx_video_mode, vidq); | ||
312 | struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); | ||
313 | int rc; | ||
314 | |||
315 | switch (urb->status) { | ||
316 | case 0: /* success */ | ||
317 | case -ETIMEDOUT: /* NAK */ | ||
318 | break; | ||
319 | case -ECONNRESET: /* kill */ | ||
320 | case -ENOENT: | ||
321 | case -ESHUTDOWN: | ||
322 | return; | ||
323 | default: /* error */ | ||
324 | cx231xx_err(DRIVER_NAME "urb completition error %d.\n", | ||
325 | urb->status); | ||
326 | break; | ||
327 | } | ||
328 | |||
329 | /* Copy data from URB */ | ||
330 | spin_lock(&dev->vbi_mode.slock); | ||
331 | rc = dev->vbi_mode.isoc_ctl.isoc_copy(dev, urb); | ||
332 | spin_unlock(&dev->vbi_mode.slock); | ||
333 | |||
334 | /* Reset status */ | ||
335 | urb->status = 0; | ||
336 | |||
337 | urb->status = usb_submit_urb(urb, GFP_ATOMIC); | ||
338 | if (urb->status) { | ||
339 | cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n", | ||
340 | urb->status); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* | ||
345 | * Stop and Deallocate URBs | ||
346 | */ | ||
347 | void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) | ||
348 | { | ||
349 | struct urb *urb; | ||
350 | int i; | ||
351 | |||
352 | cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); | ||
353 | |||
354 | dev->vbi_mode.isoc_ctl.nfields = -1; | ||
355 | for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { | ||
356 | urb = dev->vbi_mode.isoc_ctl.urb[i]; | ||
357 | if (urb) { | ||
358 | if (!irqs_disabled()) | ||
359 | usb_kill_urb(urb); | ||
360 | else | ||
361 | usb_unlink_urb(urb); | ||
362 | |||
363 | if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { | ||
364 | |||
365 | kfree(dev->vbi_mode.isoc_ctl. | ||
366 | transfer_buffer[i]); | ||
367 | dev->vbi_mode.isoc_ctl.transfer_buffer[i] = | ||
368 | NULL; | ||
369 | } | ||
370 | usb_free_urb(urb); | ||
371 | dev->vbi_mode.isoc_ctl.urb[i] = NULL; | ||
372 | } | ||
373 | dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; | ||
374 | } | ||
375 | |||
376 | kfree(dev->vbi_mode.isoc_ctl.urb); | ||
377 | kfree(dev->vbi_mode.isoc_ctl.transfer_buffer); | ||
378 | |||
379 | dev->vbi_mode.isoc_ctl.urb = NULL; | ||
380 | dev->vbi_mode.isoc_ctl.transfer_buffer = NULL; | ||
381 | dev->vbi_mode.isoc_ctl.num_bufs = 0; | ||
382 | |||
383 | cx231xx_capture_start(dev, 0, Vbi); | ||
384 | } | ||
385 | EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); | ||
386 | |||
387 | /* | ||
388 | * Allocate URBs and start IRQ | ||
389 | */ | ||
390 | int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, | ||
391 | int num_bufs, int max_pkt_size, | ||
392 | int (*isoc_copy) (struct cx231xx *dev, | ||
393 | struct urb *urb)) | ||
394 | { | ||
395 | struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; | ||
396 | int i; | ||
397 | int sb_size, pipe; | ||
398 | struct urb *urb; | ||
399 | int rc; | ||
400 | |||
401 | cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n"); | ||
402 | |||
403 | /* De-allocates all pending stuff */ | ||
404 | cx231xx_uninit_vbi_isoc(dev); | ||
405 | |||
406 | /* clear if any halt */ | ||
407 | usb_clear_halt(dev->udev, | ||
408 | usb_rcvbulkpipe(dev->udev, | ||
409 | dev->vbi_mode.end_point_addr)); | ||
410 | |||
411 | dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy; | ||
412 | dev->vbi_mode.isoc_ctl.num_bufs = num_bufs; | ||
413 | dma_q->pos = 0; | ||
414 | dma_q->is_partial_line = 0; | ||
415 | dma_q->last_sav = 0; | ||
416 | dma_q->current_field = -1; | ||
417 | dma_q->bytes_left_in_line = dev->width << 1; | ||
418 | dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ? | ||
419 | PAL_VBI_LINES : NTSC_VBI_LINES); | ||
420 | dma_q->lines_completed = 0; | ||
421 | for (i = 0; i < 8; i++) | ||
422 | dma_q->partial_buf[i] = 0; | ||
423 | |||
424 | dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *) * num_bufs, | ||
425 | GFP_KERNEL); | ||
426 | if (!dev->vbi_mode.isoc_ctl.urb) { | ||
427 | cx231xx_errdev("cannot alloc memory for usb buffers\n"); | ||
428 | return -ENOMEM; | ||
429 | } | ||
430 | |||
431 | dev->vbi_mode.isoc_ctl.transfer_buffer = | ||
432 | kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); | ||
433 | if (!dev->vbi_mode.isoc_ctl.transfer_buffer) { | ||
434 | cx231xx_errdev("cannot allocate memory for usbtransfer\n"); | ||
435 | kfree(dev->vbi_mode.isoc_ctl.urb); | ||
436 | return -ENOMEM; | ||
437 | } | ||
438 | |||
439 | dev->vbi_mode.isoc_ctl.max_pkt_size = max_pkt_size; | ||
440 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
441 | |||
442 | sb_size = max_packets * dev->vbi_mode.isoc_ctl.max_pkt_size; | ||
443 | |||
444 | /* allocate urbs and transfer buffers */ | ||
445 | for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { | ||
446 | |||
447 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
448 | if (!urb) { | ||
449 | cx231xx_err(DRIVER_NAME | ||
450 | ": cannot alloc isoc_ctl.urb %i\n", i); | ||
451 | cx231xx_uninit_vbi_isoc(dev); | ||
452 | return -ENOMEM; | ||
453 | } | ||
454 | dev->vbi_mode.isoc_ctl.urb[i] = urb; | ||
455 | urb->transfer_flags = 0; | ||
456 | |||
457 | dev->vbi_mode.isoc_ctl.transfer_buffer[i] = | ||
458 | kzalloc(sb_size, GFP_KERNEL); | ||
459 | if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { | ||
460 | cx231xx_err(DRIVER_NAME | ||
461 | ": unable to allocate %i bytes for transfer" | ||
462 | " buffer %i%s\n", sb_size, i, | ||
463 | in_interrupt() ? " while in int" : ""); | ||
464 | cx231xx_uninit_vbi_isoc(dev); | ||
465 | return -ENOMEM; | ||
466 | } | ||
467 | |||
468 | pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr); | ||
469 | usb_fill_bulk_urb(urb, dev->udev, pipe, | ||
470 | dev->vbi_mode.isoc_ctl.transfer_buffer[i], | ||
471 | sb_size, cx231xx_irq_vbi_callback, dma_q); | ||
472 | } | ||
473 | |||
474 | init_waitqueue_head(&dma_q->wq); | ||
475 | |||
476 | /* submit urbs and enables IRQ */ | ||
477 | for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { | ||
478 | rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC); | ||
479 | if (rc) { | ||
480 | cx231xx_err(DRIVER_NAME | ||
481 | ": submit of urb %i failed (error=%i)\n", i, | ||
482 | rc); | ||
483 | cx231xx_uninit_vbi_isoc(dev); | ||
484 | return rc; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | cx231xx_capture_start(dev, 1, Vbi); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); | ||
493 | |||
494 | u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
495 | u8 sav_eav, u8 *p_buffer, u32 buffer_size) | ||
496 | { | ||
497 | u32 bytes_copied = 0; | ||
498 | int current_field = -1; | ||
499 | |||
500 | switch (sav_eav) { | ||
501 | |||
502 | case SAV_VBI_FIELD1: | ||
503 | current_field = 1; | ||
504 | break; | ||
505 | |||
506 | case SAV_VBI_FIELD2: | ||
507 | current_field = 2; | ||
508 | break; | ||
509 | default: | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | if (current_field < 0) | ||
514 | return bytes_copied; | ||
515 | |||
516 | dma_q->last_sav = sav_eav; | ||
517 | |||
518 | bytes_copied = | ||
519 | cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size, | ||
520 | current_field); | ||
521 | |||
522 | return bytes_copied; | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * Announces that a buffer were filled and request the next | ||
527 | */ | ||
528 | static inline void vbi_buffer_filled(struct cx231xx *dev, | ||
529 | struct cx231xx_dmaqueue *dma_q, | ||
530 | struct cx231xx_buffer *buf) | ||
531 | { | ||
532 | /* Advice that buffer was filled */ | ||
533 | /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */ | ||
534 | |||
535 | buf->vb.state = VIDEOBUF_DONE; | ||
536 | buf->vb.field_count++; | ||
537 | do_gettimeofday(&buf->vb.ts); | ||
538 | |||
539 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
540 | |||
541 | list_del(&buf->vb.queue); | ||
542 | wake_up(&buf->vb.done); | ||
543 | } | ||
544 | |||
545 | u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
546 | u8 *p_line, u32 length, int field_number) | ||
547 | { | ||
548 | u32 bytes_to_copy; | ||
549 | struct cx231xx_buffer *buf; | ||
550 | u32 _line_size = dev->width * 2; | ||
551 | |||
552 | if (dma_q->current_field != field_number) | ||
553 | cx231xx_reset_vbi_buffer(dev, dma_q); | ||
554 | |||
555 | /* get the buffer pointer */ | ||
556 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
557 | |||
558 | /* Remember the field number for next time */ | ||
559 | dma_q->current_field = field_number; | ||
560 | |||
561 | bytes_to_copy = dma_q->bytes_left_in_line; | ||
562 | if (bytes_to_copy > length) | ||
563 | bytes_to_copy = length; | ||
564 | |||
565 | if (dma_q->lines_completed >= dma_q->lines_per_field) { | ||
566 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
567 | dma_q->is_partial_line = | ||
568 | (dma_q->bytes_left_in_line == 0) ? 0 : 1; | ||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | dma_q->is_partial_line = 1; | ||
573 | |||
574 | /* If we don't have a buffer, just return the number of bytes we would | ||
575 | have copied if we had a buffer. */ | ||
576 | if (!buf) { | ||
577 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
578 | dma_q->is_partial_line = | ||
579 | (dma_q->bytes_left_in_line == 0) ? 0 : 1; | ||
580 | return bytes_to_copy; | ||
581 | } | ||
582 | |||
583 | /* copy the data to video buffer */ | ||
584 | cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy); | ||
585 | |||
586 | dma_q->pos += bytes_to_copy; | ||
587 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
588 | |||
589 | if (dma_q->bytes_left_in_line == 0) { | ||
590 | |||
591 | dma_q->bytes_left_in_line = _line_size; | ||
592 | dma_q->lines_completed++; | ||
593 | dma_q->is_partial_line = 0; | ||
594 | |||
595 | if (cx231xx_is_vbi_buffer_done(dev, dma_q) && buf) { | ||
596 | |||
597 | vbi_buffer_filled(dev, dma_q, buf); | ||
598 | |||
599 | dma_q->pos = 0; | ||
600 | buf = NULL; | ||
601 | dma_q->lines_completed = 0; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | return bytes_to_copy; | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * video-buf generic routine to get the next available buffer | ||
610 | */ | ||
611 | static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, | ||
612 | struct cx231xx_buffer **buf) | ||
613 | { | ||
614 | struct cx231xx_video_mode *vmode = | ||
615 | container_of(dma_q, struct cx231xx_video_mode, vidq); | ||
616 | struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); | ||
617 | char *outp; | ||
618 | |||
619 | if (list_empty(&dma_q->active)) { | ||
620 | cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); | ||
621 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
622 | *buf = NULL; | ||
623 | return; | ||
624 | } | ||
625 | |||
626 | /* Get the next buffer */ | ||
627 | *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); | ||
628 | |||
629 | /* Cleans up buffer - Usefull for testing for frame/URB loss */ | ||
630 | outp = videobuf_to_vmalloc(&(*buf)->vb); | ||
631 | memset(outp, 0, (*buf)->vb.size); | ||
632 | |||
633 | dev->vbi_mode.isoc_ctl.buf = *buf; | ||
634 | |||
635 | return; | ||
636 | } | ||
637 | |||
638 | void cx231xx_reset_vbi_buffer(struct cx231xx *dev, | ||
639 | struct cx231xx_dmaqueue *dma_q) | ||
640 | { | ||
641 | struct cx231xx_buffer *buf; | ||
642 | |||
643 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
644 | |||
645 | if (buf == NULL) { | ||
646 | /* first try to get the buffer */ | ||
647 | get_next_vbi_buf(dma_q, &buf); | ||
648 | |||
649 | dma_q->pos = 0; | ||
650 | dma_q->current_field = -1; | ||
651 | } | ||
652 | |||
653 | dma_q->bytes_left_in_line = dev->width << 1; | ||
654 | dma_q->lines_completed = 0; | ||
655 | } | ||
656 | |||
657 | int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
658 | u8 *p_buffer, u32 bytes_to_copy) | ||
659 | { | ||
660 | u8 *p_out_buffer = NULL; | ||
661 | u32 current_line_bytes_copied = 0; | ||
662 | struct cx231xx_buffer *buf; | ||
663 | u32 _line_size = dev->width << 1; | ||
664 | void *startwrite; | ||
665 | int offset, lencopy; | ||
666 | |||
667 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
668 | |||
669 | if (buf == NULL) | ||
670 | return -EINVAL; | ||
671 | |||
672 | p_out_buffer = videobuf_to_vmalloc(&buf->vb); | ||
673 | |||
674 | if (dma_q->bytes_left_in_line != _line_size) { | ||
675 | current_line_bytes_copied = | ||
676 | _line_size - dma_q->bytes_left_in_line; | ||
677 | } | ||
678 | |||
679 | offset = (dma_q->lines_completed * _line_size) + | ||
680 | current_line_bytes_copied; | ||
681 | |||
682 | /* prepare destination address */ | ||
683 | startwrite = p_out_buffer + offset; | ||
684 | |||
685 | lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? | ||
686 | bytes_to_copy : dma_q->bytes_left_in_line; | ||
687 | |||
688 | memcpy(startwrite, p_buffer, lencopy); | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev, | ||
694 | struct cx231xx_dmaqueue *dma_q) | ||
695 | { | ||
696 | u32 height = 0; | ||
697 | |||
698 | height = ((dev->norm & V4L2_STD_625_50) ? | ||
699 | PAL_VBI_LINES : NTSC_VBI_LINES); | ||
700 | return (dma_q->lines_completed == height) ? 1 : 0; | ||
701 | } | ||