Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 164069
b: refs/heads/master
c: da52a55
h: refs/heads/master
i:
  164067: a17bfec
v: v3
  • Loading branch information
Devin Heitmueller authored and Mauro Carvalho Chehab committed Sep 19, 2009
1 parent 9e43998 commit d4aee0f
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 206313db83641022c5ee213ac5f619973a9b427b
refs/heads/master: da52a55cff643b8e0b346b9894adf5b93946040d
44 changes: 39 additions & 5 deletions trunk/drivers/media/video/em28xx/em28xx-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ static int alt = EM28XX_PINOUT;
module_param(alt, int, 0644);
MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");

static unsigned int disable_vbi;
module_param(disable_vbi, int, 0644);
MODULE_PARM_DESC(disable_vbi, "disable vbi support");

/* FIXME */
#define em28xx_isocdbg(fmt, arg...) do {\
if (core_debug) \
Expand Down Expand Up @@ -648,9 +652,24 @@ int em28xx_capture_start(struct em28xx *dev, int start)
return rc;
}

int em28xx_vbi_supported(struct em28xx *dev)
{
/* Modprobe option to manually disable */
if (disable_vbi == 1)
return 0;

if (dev->chip_id == CHIP_ID_EM2860 ||
dev->chip_id == CHIP_ID_EM2883)
return 1;

/* Version of em28xx that does not support VBI */
return 0;
}

int em28xx_set_outfmt(struct em28xx *dev)
{
int ret;
u8 vinctrl;

ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
dev->format->reg | 0x20, 0xff);
Expand All @@ -661,7 +680,16 @@ int em28xx_set_outfmt(struct em28xx *dev)
if (ret < 0)
return ret;

return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
vinctrl = dev->vinctl;
if (em28xx_vbi_supported(dev) == 1) {
vinctrl |= EM28XX_VINCTRL_VBI_RAW;
em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4);
em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c);
}

return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
}

static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
Expand Down Expand Up @@ -732,7 +760,14 @@ int em28xx_resolution_set(struct em28xx *dev)


em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);

/* If we don't set the start position to 4 in VBI mode, we end up
with line 21 being YUYV encoded instead of being in 8-bit
greyscale */
if (em28xx_vbi_supported(dev) == 1)
em28xx_capture_area_set(dev, 0, 4, width >> 2, height >> 2);
else
em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);

return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
}
Expand Down Expand Up @@ -844,8 +879,7 @@ EXPORT_SYMBOL_GPL(em28xx_set_mode);
*/
static void em28xx_irq_callback(struct urb *urb)
{
struct em28xx_dmaqueue *dma_q = urb->context;
struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
struct em28xx *dev = urb->context;
int rc, i;

switch (urb->status) {
Expand Down Expand Up @@ -994,7 +1028,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,

usb_fill_int_urb(urb, dev->udev, pipe,
dev->isoc_ctl.transfer_buffer[i], sb_size,
em28xx_irq_callback, dma_q, 1);
em28xx_irq_callback, dev, 1);

urb->number_of_packets = max_packets;
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/media/video/em28xx/em28xx-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@
#define EM28XX_R31_HSCALEHIGH 0x31
#define EM28XX_R32_VSCALELOW 0x32
#define EM28XX_R33_VSCALEHIGH 0x33
#define EM28XX_R34_VBI_START_H 0x34
#define EM28XX_R35_VBI_START_V 0x35
#define EM28XX_R36_VBI_WIDTH 0x36
#define EM28XX_R37_VBI_HEIGHT 0x37

#define EM28XX_R40_AC97LSB 0x40
#define EM28XX_R41_AC97MSB 0x41
Expand Down
127 changes: 123 additions & 4 deletions trunk/drivers/media/video/em28xx/em28xx-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
{
struct em28xx_buffer *buf;
struct em28xx_dmaqueue *dma_q = urb->context;
struct em28xx_dmaqueue *dma_q = &dev->vidq;
unsigned char *outp = NULL;
int i, len = 0, rc = 1;
unsigned char *p;
Expand Down Expand Up @@ -410,6 +410,118 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
return rc;
}

/* Version of isoc handler that takes into account a mixture of video and
VBI data */
static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
{
struct em28xx_buffer *buf, *vbi_buf;
struct em28xx_dmaqueue *dma_q = &dev->vidq;
unsigned char *outp = NULL;
unsigned char *vbioutp = NULL;
int i, len = 0, rc = 1;
unsigned char *p;
int vbi_size;

if (!dev)
return 0;

if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
return 0;

if (urb->status < 0) {
print_err_status(dev, -1, urb->status);
if (urb->status == -ENOENT)
return 0;
}

buf = dev->isoc_ctl.buf;
if (buf != NULL)
outp = videobuf_to_vmalloc(&buf->vb);
for (i = 0; i < urb->number_of_packets; i++) {
int status = urb->iso_frame_desc[i].status;

if (status < 0) {
print_err_status(dev, i, status);
if (urb->iso_frame_desc[i].status != -EPROTO)
continue;
}

len = urb->iso_frame_desc[i].actual_length - 4;

if (urb->iso_frame_desc[i].actual_length <= 0) {
/* em28xx_isocdbg("packet %d is empty",i); - spammy */
continue;
}
if (urb->iso_frame_desc[i].actual_length >
dev->max_pkt_size) {
em28xx_isocdbg("packet bigger than packet size");
continue;
}

p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;

/* capture type 0 = vbi start
capture type 1 = video start
capture type 2 = video in progress */
if (p[0] == 0x33 && p[1] == 0x95) {
dev->capture_type = 0;
dev->vbi_read = 0;
em28xx_isocdbg("VBI START HEADER!!!\n");
dev->cur_field = p[2];
}

/* FIXME: get rid of hard-coded value */
vbi_size = 720 * 0x0c;

if (dev->capture_type == 0) {
if (dev->vbi_read >= vbi_size) {
/* We've already read all the VBI data, so
treat the rest as video */
printk("djh c should never happen\n");
} else if ((dev->vbi_read + len) < vbi_size) {
/* This entire frame is VBI data */
dev->vbi_read += len;
} else {
/* Some of this frame is VBI data and some is
video data */
int vbi_data_len = vbi_size - dev->vbi_read;
dev->vbi_read += vbi_data_len;
dev->capture_type = 1;
p += vbi_data_len;
len -= vbi_data_len;
}
}

if (dev->capture_type == 1) {
dev->capture_type = 2;
em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
len, (p[2] & 1) ? "odd" : "even");

if (dev->progressive || !(dev->cur_field & 1)) {
if (buf != NULL)
buffer_filled(dev, dma_q, buf);
get_next_buf(dma_q, &buf);
if (buf == NULL)
outp = NULL;
else
outp = videobuf_to_vmalloc(&buf->vb);
}
if (buf != NULL) {
if (dev->cur_field & 1)
buf->top_field = 0;
else
buf->top_field = 1;
}

dma_q->pos = 0;
}
if (buf != NULL && dev->capture_type == 2)
em28xx_copy_video(dev, dma_q, buf, p, outp, len);
}
return rc;
}


/* ------------------------------------------------------------------
Videobuf operations
------------------------------------------------------------------*/
Expand Down Expand Up @@ -494,9 +606,16 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
urb_init = 1;

if (urb_init) {
rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
EM28XX_NUM_BUFS, dev->max_pkt_size,
em28xx_isoc_copy);
if (em28xx_vbi_supported(dev) == 1)
rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
EM28XX_NUM_BUFS,
dev->max_pkt_size,
em28xx_isoc_copy_vbi);
else
rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
EM28XX_NUM_BUFS,
dev->max_pkt_size,
em28xx_isoc_copy);
if (rc < 0)
goto fail;
}
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/media/video/em28xx/em28xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,12 @@ struct em28xx {
enum em28xx_dev_state state;
enum em28xx_io_method io;

/* vbi related state tracking */
int capture_type;
int vbi_read;
unsigned char cur_field;


struct work_struct request_module_wk;

/* locks */
Expand Down Expand Up @@ -639,6 +645,7 @@ int em28xx_audio_setup(struct em28xx *dev);

int em28xx_colorlevels_set_default(struct em28xx *dev);
int em28xx_capture_start(struct em28xx *dev, int start);
int em28xx_vbi_supported(struct em28xx *dev);
int em28xx_set_outfmt(struct em28xx *dev);
int em28xx_resolution_set(struct em28xx *dev);
int em28xx_set_alternate(struct em28xx *dev);
Expand Down

0 comments on commit d4aee0f

Please sign in to comment.