aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-03-26 12:38:38 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-28 16:47:57 -0400
commite507e0e513c41ccfc68d6f619faa212f97c88ddb (patch)
tree29d61558f2a92148b8d869bdec1fc55f0cfb067c /drivers/media/usb
parent736a320bd285b4b90cdc49d1506461518979f240 (diff)
[media] em28xx: add support for em25xx/em276x/em277x/em278x frame data processing
The em25xx/em276x/em277x/em278x frame data format is different to the one used by the em2710/em2750/em28xx chips. With the recent cleanups and reorganization of the frame data processing code it can be easily extended to support these devices. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index b1817231f50c..ef1959bbd23f 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -76,6 +76,16 @@ MODULE_DESCRIPTION(DRIVER_DESC);
76MODULE_LICENSE("GPL"); 76MODULE_LICENSE("GPL");
77MODULE_VERSION(EM28XX_VERSION); 77MODULE_VERSION(EM28XX_VERSION);
78 78
79
80#define EM25XX_FRMDATAHDR_BYTE1 0x02
81#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
82#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
83#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
84#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
85 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
86 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
87
88
79static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U }; 89static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
80static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U }; 90static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
81static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U }; 91static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
@@ -408,6 +418,62 @@ static inline void process_frame_data_em28xx(struct em28xx *dev,
408 em28xx_copy_video(dev, buf, data_pkt, data_len); 418 em28xx_copy_video(dev, buf, data_pkt, data_len);
409} 419}
410 420
421/*
422 * Process data packet according to the em25xx/em276x/7x/8x frame data format
423 */
424static inline void process_frame_data_em25xx(struct em28xx *dev,
425 unsigned char *data_pkt,
426 unsigned int data_len)
427{
428 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
429 struct em28xx_dmaqueue *dmaq = &dev->vidq;
430 bool frame_end = 0;
431
432 /* Check for header */
433 /* NOTE: at least with bulk transfers, only the first packet
434 * has a header and has always set the FRAME_END bit */
435 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
436 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
437 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
438 dev->top_field = !(data_pkt[1] &
439 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
440 frame_end = data_pkt[1] &
441 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
442 data_pkt += 2;
443 data_len -= 2;
444 }
445
446 /* Finish field and prepare next (BULK only) */
447 if (dev->analog_xfer_bulk && frame_end) {
448 buf = finish_field_prepare_next(dev, buf, dmaq);
449 dev->usb_ctl.vid_buf = buf;
450 }
451 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
452 * we COULD already prepare a buffer here to avoid skipping the
453 * first frame.
454 */
455 }
456
457 /* Copy data */
458 if (buf != NULL && data_len > 0)
459 em28xx_copy_video(dev, buf, data_pkt, data_len);
460
461 /* Finish frame (ISOC only) => avoids lag of 1 frame */
462 if (!dev->analog_xfer_bulk && frame_end) {
463 buf = finish_field_prepare_next(dev, buf, dmaq);
464 dev->usb_ctl.vid_buf = buf;
465 }
466
467 /* NOTE: Tested with USB bulk transfers only !
468 * The wording in the datasheet suggests that isoc might work different.
469 * The current code assumes that with isoc transfers each packet has a
470 * header like with the other em28xx devices.
471 */
472 /* NOTE: Support for interlaced mode is pure theory. It has not been
473 * tested and it is unknown if these devices actually support it. */
474 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
475}
476
411/* Processes and copies the URB data content (video and VBI data) */ 477/* Processes and copies the URB data content (video and VBI data) */
412static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) 478static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
413{ 479{
@@ -460,7 +526,13 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
460 continue; 526 continue;
461 } 527 }
462 528
463 process_frame_data_em28xx(dev, usb_data_pkt, usb_data_len); 529 if (dev->is_em25xx)
530 process_frame_data_em25xx(dev,
531 usb_data_pkt, usb_data_len);
532 else
533 process_frame_data_em28xx(dev,
534 usb_data_pkt, usb_data_len);
535
464 } 536 }
465 return 1; 537 return 1;
466} 538}