diff options
Diffstat (limited to 'drivers/media/video')
218 files changed, 9200 insertions, 20620 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index ac16e815e27..eb875af05e7 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -7,11 +7,6 @@ config VIDEO_V4L2 depends on VIDEO_DEV && VIDEO_V4L2_COMMON default VIDEO_DEV && VIDEO_V4L2_COMMON -config VIDEO_V4L1 - tristate - depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1 - default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1 - config VIDEOBUF_GEN tristate @@ -96,7 +91,7 @@ config VIDEO_HELPER_CHIPS_AUTO config VIDEO_IR_I2C tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO - depends on I2C && VIDEO_IR + depends on I2C && RC_CORE default y ---help--- Most boards have an IR chip directly connected via GPIO. However, @@ -112,7 +107,7 @@ config VIDEO_IR_I2C # menu "Encoders/decoders and other helper chips" - depends on !VIDEO_HELPER_CHIPS_AUTO + visible if !VIDEO_HELPER_CHIPS_AUTO comment "Audio decoders" @@ -666,6 +661,16 @@ config VIDEO_HEXIUM_GEMINI To compile this driver as a module, choose M here: the module will be called hexium_gemini. +config VIDEO_TIMBERDALE + tristate "Support for timberdale Video In/LogiWIN" + depends on VIDEO_V4L2 && I2C + select DMA_ENGINE + select TIMB_DMA + select VIDEO_ADV7180 + select VIDEOBUF_DMA_CONTIG + ---help--- + Add support for the Video In peripherial of the timberdale FPGA. + source "drivers/media/video/cx88/Kconfig" source "drivers/media/video/cx23885/Kconfig" @@ -789,6 +794,12 @@ config SOC_CAMERA_PLATFORM help This is a generic SoC camera platform driver, useful for testing +config SOC_CAMERA_OV2640 + tristate "ov2640 camera support" + depends on SOC_CAMERA && I2C + help + This is a ov2640 camera driver + config SOC_CAMERA_OV6650 tristate "ov6650 sensor support" depends on SOC_CAMERA && I2C @@ -905,21 +916,8 @@ source "drivers/media/video/cx231xx/Kconfig" source "drivers/media/video/usbvision/Kconfig" -source "drivers/media/video/usbvideo/Kconfig" - source "drivers/media/video/et61x251/Kconfig" -config USB_SE401 - tristate "USB SE401 Camera support" - depends on VIDEO_V4L1 - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. See <file:Documentation/video4linux/se401.txt> - for more information and for a list of supported cameras. - - To compile this driver as a module, choose M here: the - module will be called se401. - source "drivers/media/video/sn9c102/Kconfig" source "drivers/media/video/pwc/Kconfig" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index af79d476a4c..81e38cb0b84 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -22,10 +22,6 @@ endif obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o -ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) - obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o -endif - # All i2c modules must come first: obj-$(CONFIG_VIDEO_TUNER) += tuner.o @@ -79,6 +75,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o +obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o @@ -106,6 +103,7 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o +obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o @@ -124,8 +122,6 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o -obj-$(CONFIG_USB_DABUSB) += dabusb.o -obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_ZR364XX) += zr364xx.o obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o @@ -136,10 +132,6 @@ obj-$(CONFIG_USB_GSPCA) += gspca/ obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ -obj-$(CONFIG_USB_IBMCAM) += usbvideo/ -obj-$(CONFIG_USB_KONICAWC) += usbvideo/ -obj-$(CONFIG_USB_VICAM) += usbvideo/ -obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ obj-$(CONFIG_USB_S2255) += s2255drv.o obj-$(CONFIG_VIDEO_IVTV) += ivtv/ diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 31e7a123d19..f989f2820d8 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar) static const struct v4l2_file_operations ar_fops = { .owner = THIS_MODULE, .read = ar_read, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops ar_ioctl_ops = { diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 0453816d4ec..01be89fa5c7 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -212,7 +212,7 @@ void au0828_card_setup(struct au0828_dev *dev) be abstracted out if we ever need to support a different demod) */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "au8522", 0x8e >> 1, NULL); + "au8522", 0x8e >> 1, NULL); if (sd == NULL) printk(KERN_ERR "analog subdev registration failed\n"); } @@ -221,7 +221,7 @@ void au0828_card_setup(struct au0828_dev *dev) if (dev->board.tuner_type != TUNER_ABSENT) { /* Load the tuner module, which does the attach */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tuner", dev->board.tuner_addr, NULL); + "tuner", dev->board.tuner_addr, NULL); if (sd == NULL) printk(KERN_ERR "tuner subdev registration fail\n"); diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 162fd5f9d44..e41e4ad5cc4 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -122,6 +122,7 @@ static void au0828_irq_callback(struct urb *urb) { struct au0828_dmaqueue *dma_q = urb->context; struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + unsigned long flags = 0; int rc, i; switch (urb->status) { @@ -139,9 +140,9 @@ static void au0828_irq_callback(struct urb *urb) } /* Copy data from URB */ - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); rc = dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock(&dev->slock); + spin_unlock_irqrestore(&dev->slock, flags); /* Reset urb buffers */ for (i = 0; i < urb->number_of_packets; i++) { @@ -576,7 +577,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) p += 4; au0828_isocdbg("Video frame %s\n", (fbyte & 0x40) ? "odd" : "even"); - if (!(fbyte & 0x40)) { + if (fbyte & 0x40) { /* VBI */ if (vbi_buf != NULL) vbi_buffer_filled(dev, @@ -597,6 +598,15 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) outp = NULL; else outp = videobuf_to_vmalloc(&buf->vb); + + /* As long as isoc traffic is arriving, keep + resetting the timer */ + if (dev->vid_timeout_running) + mod_timer(&dev->vid_timeout, + jiffies + (HZ / 10)); + if (dev->vbi_timeout_running) + mod_timer(&dev->vbi_timeout, + jiffies + (HZ / 10)); } if (buf != NULL) { @@ -907,6 +917,57 @@ static int get_ressource(struct au0828_fh *fh) } } +/* This function ensures that video frames continue to be delivered even if + the ITU-656 input isn't receiving any data (thereby preventing applications + such as tvtime from hanging) */ +void au0828_vid_buffer_timeout(unsigned long data) +{ + struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dmaqueue *dma_q = &dev->vidq; + struct au0828_buffer *buf; + unsigned char *vid_data; + unsigned long flags = 0; + + spin_lock_irqsave(&dev->slock, flags); + + buf = dev->isoc_ctl.buf; + if (buf != NULL) { + vid_data = videobuf_to_vmalloc(&buf->vb); + memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ + buffer_filled(dev, dma_q, buf); + } + get_next_buf(dma_q, &buf); + + if (dev->vid_timeout_running == 1) + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); + + spin_unlock_irqrestore(&dev->slock, flags); +} + +void au0828_vbi_buffer_timeout(unsigned long data) +{ + struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dmaqueue *dma_q = &dev->vbiq; + struct au0828_buffer *buf; + unsigned char *vbi_data; + unsigned long flags = 0; + + spin_lock_irqsave(&dev->slock, flags); + + buf = dev->isoc_ctl.vbi_buf; + if (buf != NULL) { + vbi_data = videobuf_to_vmalloc(&buf->vb); + memset(vbi_data, 0x00, buf->vb.size); + vbi_buffer_filled(dev, dma_q, buf); + } + vbi_get_next_buf(dma_q, &buf); + + if (dev->vbi_timeout_running == 1) + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + spin_unlock_irqrestore(&dev->slock, flags); +} + + static int au0828_v4l2_open(struct file *filp) { int ret = 0; @@ -976,7 +1037,6 @@ static int au0828_v4l2_open(struct file *filp) V4L2_FIELD_SEQ_TB, sizeof(struct au0828_buffer), fh, NULL); - return ret; } @@ -987,11 +1047,19 @@ static int au0828_v4l2_close(struct file *filp) struct au0828_dev *dev = fh->dev; if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + /* Cancel timeout thread in case they didn't call streamoff */ + dev->vid_timeout_running = 0; + del_timer_sync(&dev->vid_timeout); + videobuf_stop(&fh->vb_vidq); res_free(fh, AU0828_RESOURCE_VIDEO); } if (res_check(fh, AU0828_RESOURCE_VBI)) { + /* Cancel timeout thread in case they didn't call streamoff */ + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); + videobuf_stop(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } @@ -1048,6 +1116,13 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, if (!res_get(fh, AU0828_RESOURCE_VBI)) return -EBUSY; + if (dev->vbi_timeout_running == 0) { + /* Handle case where caller tries to read without + calling streamon first */ + dev->vbi_timeout_running = 1; + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + } + return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); } @@ -1577,10 +1652,15 @@ static int vidioc_streamon(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); } - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { rc = videobuf_streamon(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + dev->vid_timeout_running = 1; + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { rc = videobuf_streamon(&fh->vb_vbiq); + dev->vbi_timeout_running = 1; + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + } return rc; } @@ -1607,6 +1687,9 @@ static int vidioc_streamoff(struct file *file, void *priv, fh, type, fh->resources, dev->resources); if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev->vid_timeout_running = 0; + del_timer_sync(&dev->vid_timeout); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); rc = au0828_stream_interrupt(dev); if (rc != 0) @@ -1621,6 +1704,9 @@ static int vidioc_streamoff(struct file *file, void *priv, videobuf_streamoff(&fh->vb_vidq); res_free(fh, AU0828_RESOURCE_VIDEO); } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); + videobuf_streamoff(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } @@ -1723,15 +1809,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct au0828_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - static struct v4l2_file_operations au0828_v4l_fops = { .owner = THIS_MODULE, .open = au0828_v4l2_open, @@ -1775,9 +1852,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_register = vidioc_s_register, #endif .vidioc_g_chip_ident = vidioc_g_chip_ident, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static const struct video_device au0828_video_template = { @@ -1840,6 +1914,14 @@ int au0828_analog_register(struct au0828_dev *dev, INIT_LIST_HEAD(&dev->vbiq.active); INIT_LIST_HEAD(&dev->vbiq.queued); + dev->vid_timeout.function = au0828_vid_buffer_timeout; + dev->vid_timeout.data = (unsigned long) dev; + init_timer(&dev->vid_timeout); + + dev->vbi_timeout.function = au0828_vbi_buffer_timeout; + dev->vbi_timeout.data = (unsigned long) dev; + init_timer(&dev->vbi_timeout); + dev->width = NTSC_STD_W; dev->height = NTSC_STD_H; dev->field_size = dev->width * dev->height; diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 9905bc4f5f5..9cde3532182 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -53,7 +53,7 @@ /* Defination for AU0828 USB transfer */ #define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ -#define AU0828_ISO_PACKETS_PER_URB 10 +#define AU0828_ISO_PACKETS_PER_URB 128 #define AU0828_MIN_BUF 4 #define AU0828_DEF_BUF 8 @@ -204,6 +204,10 @@ struct au0828_dev { unsigned int resources; /* resources in use */ struct video_device *vdev; struct video_device *vbi_dev; + struct timer_list vid_timeout; + int vid_timeout_running; + struct timer_list vbi_timeout; + int vbi_timeout_running; int width; int height; int vbi_width; diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 1a4a89fdf76..7da5c2e1fc1 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -1,10 +1,10 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG - depends on VIDEO_IR + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 87d8b006ef7..49efcf660ba 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -3529,7 +3529,7 @@ void __devinit bttv_init_card2(struct bttv *btv) struct v4l2_subdev *sd; sd = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "saa6588", 0, addrs); + &btv->c.i2c_adap, "saa6588", 0, addrs); btv->has_saa6588 = (sd != NULL); } @@ -3554,7 +3554,7 @@ void __devinit bttv_init_card2(struct bttv *btv) }; btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "msp3400", 0, addrs); + &btv->c.i2c_adap, "msp3400", 0, addrs); if (btv->sd_msp34xx) return; goto no_audio; @@ -3568,7 +3568,7 @@ void __devinit bttv_init_card2(struct bttv *btv) }; if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tda7432", 0, addrs)) + &btv->c.i2c_adap, "tda7432", 0, addrs)) return; goto no_audio; } @@ -3576,7 +3576,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case 3: { /* The user specified that we should probe for tvaudio */ btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tvaudio", 0, tvaudio_addrs()); + &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs()); if (btv->sd_tvaudio) return; goto no_audio; @@ -3596,11 +3596,11 @@ void __devinit bttv_init_card2(struct bttv *btv) found is really something else (e.g. a tea6300). */ if (!bttv_tvcards[btv->c.type].no_msp34xx) { btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "msp3400", + &btv->c.i2c_adap, "msp3400", 0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1)); } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "msp3400", + &btv->c.i2c_adap, "msp3400", 0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1)); } @@ -3616,13 +3616,13 @@ void __devinit bttv_init_card2(struct bttv *btv) }; if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tda7432", 0, addrs)) + &btv->c.i2c_adap, "tda7432", 0, addrs)) return; } /* Now see if we can find one of the tvaudio devices. */ btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tvaudio", 0, tvaudio_addrs()); + &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs()); if (btv->sd_tvaudio) return; @@ -3646,13 +3646,13 @@ void __devinit bttv_init_tuner(struct bttv *btv) /* Load tuner module before issuing tuner config call! */ if (bttv_tvcards[btv->c.type].has_radio) v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tuner", + &btv->c.i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tuner", + &btv->c.i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); v4l2_i2c_new_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, NULL, "tuner", + &btv->c.i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 53285aa6e72..91399c94cd1 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -55,7 +55,7 @@ #include <asm/io.h> #include <asm/byteorder.h> -#include <media/rds.h> +#include <media/saa6588.h> unsigned int bttv_num; /* number of Bt848s in use */ @@ -860,7 +860,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit) xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM; /* is it free? */ - mutex_lock(&btv->lock); if (btv->resources & xbits) { /* no, someone else uses it */ goto fail; @@ -890,11 +889,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit) /* it's free, grab it */ fh->resources |= bit; btv->resources |= bit; - mutex_unlock(&btv->lock); return 1; fail: - mutex_unlock(&btv->lock); return 0; } @@ -946,7 +943,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits) /* trying to free ressources not allocated by us ... */ printk("bttv: BUG! (btres)\n"); } - mutex_lock(&btv->lock); fh->resources &= ~bits; btv->resources &= ~bits; @@ -957,8 +953,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits) if (0 == (bits & VBI_RESOURCES)) disclaim_vbi_lines(btv); - - mutex_unlock(&btv->lock); } /* ----------------------------------------------------------------------- */ @@ -1719,28 +1713,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, /* Make sure tvnorm and vbi_end remain consistent until we're done. */ - mutex_lock(&btv->lock); norm = btv->tvnorm; /* In this mode capturing always starts at defrect.top (default VDELAY), ignoring cropping parameters. */ if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) { - mutex_unlock(&btv->lock); return -EINVAL; } - mutex_unlock(&btv->lock); - c.rect = bttv_tvnorms[norm].cropcap.defrect; } else { - mutex_lock(&btv->lock); - norm = btv->tvnorm; c = btv->crop[!!fh->do_crop]; - mutex_unlock(&btv->lock); - if (width < c.min_scaled_width || width > c.max_scaled_width || height < c.min_scaled_height) @@ -1864,7 +1850,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id) unsigned int i; int err; - mutex_lock(&btv->lock); err = v4l2_prio_check(&btv->prio, fh->prio); if (err) goto err; @@ -1880,7 +1865,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id) set_tvnorm(btv, i); err: - mutex_unlock(&btv->lock); return err; } @@ -1904,7 +1888,6 @@ static int bttv_enum_input(struct file *file, void *priv, struct bttv *btv = fh->btv; int rc = 0; - mutex_lock(&btv->lock); if (i->index >= bttv_tvcards[btv->c.type].video_inputs) { rc = -EINVAL; goto err; @@ -1934,7 +1917,6 @@ static int bttv_enum_input(struct file *file, void *priv, i->std = BTTV_NORMS; err: - mutex_unlock(&btv->lock); return rc; } @@ -1944,9 +1926,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i) struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); *i = btv->input; - mutex_unlock(&btv->lock); return 0; } @@ -1958,7 +1938,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i) int err; - mutex_lock(&btv->lock); err = v4l2_prio_check(&btv->prio, fh->prio); if (unlikely(err)) goto err; @@ -1971,7 +1950,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i) set_input(btv, i, btv->tvnorm); err: - mutex_unlock(&btv->lock); return 0; } @@ -1985,7 +1963,6 @@ static int bttv_s_tuner(struct file *file, void *priv, if (unlikely(0 != t->index)) return -EINVAL; - mutex_lock(&btv->lock); if (unlikely(btv->tuner_type == TUNER_ABSENT)) { err = -EINVAL; goto err; @@ -2001,7 +1978,6 @@ static int bttv_s_tuner(struct file *file, void *priv, btv->audio_mode_gpio(btv, t, 1); err: - mutex_unlock(&btv->lock); return 0; } @@ -2012,10 +1988,8 @@ static int bttv_g_frequency(struct file *file, void *priv, struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = btv->freq; - mutex_unlock(&btv->lock); return 0; } @@ -2030,7 +2004,6 @@ static int bttv_s_frequency(struct file *file, void *priv, if (unlikely(f->tuner != 0)) return -EINVAL; - mutex_lock(&btv->lock); err = v4l2_prio_check(&btv->prio, fh->prio); if (unlikely(err)) goto err; @@ -2045,7 +2018,6 @@ static int bttv_s_frequency(struct file *file, void *priv, if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv, btv->freq); err: - mutex_unlock(&btv->lock); return 0; } @@ -2178,7 +2150,6 @@ limit_scaled_size_lock (struct bttv_fh * fh, /* Make sure tvnorm, vbi_end and the current cropping parameters remain consistent until we're done. */ - mutex_lock(&btv->lock); b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; @@ -2256,7 +2227,6 @@ limit_scaled_size_lock (struct bttv_fh * fh, rc = 0; /* success */ fail: - mutex_unlock(&btv->lock); return rc; } @@ -2288,9 +2258,7 @@ verify_window_lock (struct bttv_fh * fh, if (V4L2_FIELD_ANY == field) { __s32 height2; - mutex_lock(&fh->btv->lock); height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1; - mutex_unlock(&fh->btv->lock); field = (win->w.height > height2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; @@ -2366,7 +2334,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv, } } - mutex_lock(&fh->cap.vb_lock); /* clip against screen */ if (NULL != btv->fbuf.base) n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height, @@ -2397,13 +2364,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv, fh->ov.field = win->field; fh->ov.setup_ok = 1; - /* - * FIXME: btv is protected by btv->lock mutex, while btv->init - * is protected by fh->cap.vb_lock. This seems to open the - * possibility for some race situations. Maybe the better would - * be to unify those locks or to use another way to store the - * init values that will be consumed by videobuf callbacks - */ btv->init.ov.w.width = win->w.width; btv->init.ov.w.height = win->w.height; btv->init.ov.field = win->field; @@ -2418,7 +2378,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv, bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); } - mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -2532,9 +2491,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, if (V4L2_FIELD_ANY == field) { __s32 height2; - mutex_lock(&btv->lock); height2 = btv->crop[!!fh->do_crop].rect.height >> 1; - mutex_unlock(&btv->lock); field = (f->fmt.pix.height > height2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; @@ -2620,7 +2577,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); /* update our state informations */ - mutex_lock(&fh->cap.vb_lock); fh->fmt = fmt; fh->cap.field = f->fmt.pix.field; fh->cap.last = V4L2_FIELD_NONE; @@ -2629,7 +2585,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, btv->init.fmt = fmt; btv->init.width = f->fmt.pix.width; btv->init.height = f->fmt.pix.height; - mutex_unlock(&fh->cap.vb_lock); return 0; } @@ -2648,34 +2603,6 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv, return setup_window_lock(fh, btv, &f->fmt.win, 1); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - int retval; - unsigned int i; - struct bttv_fh *fh = priv; - - mutex_lock(&fh->cap.vb_lock); - retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, - V4L2_MEMORY_MMAP); - if (retval < 0) { - mutex_unlock(&fh->cap.vb_lock); - return retval; - } - - gbuffers = retval; - memset(mbuf, 0, sizeof(*mbuf)); - mbuf->frames = gbuffers; - mbuf->size = gbuffers * gbufsize; - - for (i = 0; i < gbuffers; i++) - mbuf->offsets[i] = i * gbufsize; - - mutex_unlock(&fh->cap.vb_lock); - return 0; -} -#endif - static int bttv_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -2781,10 +2708,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) int retval = 0; if (on) { - mutex_lock(&fh->cap.vb_lock); /* verify args */ if (unlikely(!btv->fbuf.base)) { - mutex_unlock(&fh->cap.vb_lock); return -EINVAL; } if (unlikely(!fh->ov.setup_ok)) { @@ -2793,13 +2718,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) } if (retval) return retval; - mutex_unlock(&fh->cap.vb_lock); } if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY)) return -EBUSY; - mutex_lock(&fh->cap.vb_lock); if (on) { fh->ov.tvnorm = btv->tvnorm; new = videobuf_sg_alloc(sizeof(*new)); @@ -2811,7 +2734,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) /* switch over */ retval = bttv_switch_overlay(btv, fh, new); - mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -2850,7 +2772,6 @@ static int bttv_s_fbuf(struct file *file, void *f, } /* ok, accept it */ - mutex_lock(&fh->cap.vb_lock); btv->fbuf.base = fb->base; btv->fbuf.fmt.width = fb->fmt.width; btv->fbuf.fmt.height = fb->fmt.height; @@ -2882,7 +2803,6 @@ static int bttv_s_fbuf(struct file *file, void *f, retval = bttv_switch_overlay(btv, fh, new); } } - mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -2961,7 +2881,6 @@ static int bttv_queryctrl(struct file *file, void *priv, c->id >= V4L2_CID_PRIVATE_LASTP1)) return -EINVAL; - mutex_lock(&btv->lock); if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME)) *c = no_ctl; else { @@ -2969,7 +2888,6 @@ static int bttv_queryctrl(struct file *file, void *priv, *c = (NULL != ctrl) ? *ctrl : no_ctl; } - mutex_unlock(&btv->lock); return 0; } @@ -2980,10 +2898,8 @@ static int bttv_g_parm(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id, &parm->parm.capture.timeperframe); - mutex_unlock(&btv->lock); return 0; } @@ -2999,7 +2915,6 @@ static int bttv_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - mutex_lock(&btv->lock); t->rxsubchans = V4L2_TUNER_SUB_MONO; bttv_call_all(btv, tuner, g_tuner, t); strcpy(t->name, "Television"); @@ -3011,7 +2926,6 @@ static int bttv_g_tuner(struct file *file, void *priv, if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 0); - mutex_unlock(&btv->lock); return 0; } @@ -3020,9 +2934,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p) struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); *p = v4l2_prio_max(&btv->prio); - mutex_unlock(&btv->lock); return 0; } @@ -3034,9 +2946,7 @@ static int bttv_s_priority(struct file *file, void *f, struct bttv *btv = fh->btv; int rc; - mutex_lock(&btv->lock); rc = v4l2_prio_change(&btv->prio, &fh->prio, prio); - mutex_unlock(&btv->lock); return rc; } @@ -3051,9 +2961,7 @@ static int bttv_cropcap(struct file *file, void *priv, cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) return -EINVAL; - mutex_lock(&btv->lock); *cap = bttv_tvnorms[btv->tvnorm].cropcap; - mutex_unlock(&btv->lock); return 0; } @@ -3071,9 +2979,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop) inconsistent with fh->width or fh->height and apps do not expect a change here. */ - mutex_lock(&btv->lock); crop->c = btv->crop[!!fh->do_crop].rect; - mutex_unlock(&btv->lock); return 0; } @@ -3097,17 +3003,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) /* Make sure tvnorm, vbi_end and the current cropping parameters remain consistent until we're done. Note read() may change vbi_end in check_alloc_btres_lock(). */ - mutex_lock(&btv->lock); retval = v4l2_prio_check(&btv->prio, fh->prio); if (0 != retval) { - mutex_unlock(&btv->lock); return retval; } retval = -EBUSY; if (locked_btres(fh->btv, VIDEO_RESOURCES)) { - mutex_unlock(&btv->lock); return retval; } @@ -3119,7 +3022,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) b_top = max(b->top, btv->vbi_end); if (b_top + 32 >= b_bottom) { - mutex_unlock(&btv->lock); return retval; } @@ -3142,12 +3044,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) btv->crop[1] = c; - mutex_unlock(&btv->lock); - fh->do_crop = 1; - mutex_lock(&fh->cap.vb_lock); - if (fh->width < c.min_scaled_width) { fh->width = c.min_scaled_width; btv->init.width = c.min_scaled_width; @@ -3164,8 +3062,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) btv->init.height = c.max_scaled_height; } - mutex_unlock(&fh->cap.vb_lock); - return 0; } @@ -3233,7 +3129,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) return videobuf_poll_stream(file, &fh->vbi, wait); } - mutex_lock(&fh->cap.vb_lock); if (check_btres(fh,RESOURCE_VIDEO_STREAM)) { /* streaming capture */ if (list_empty(&fh->cap.stream)) @@ -3268,7 +3163,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) else rc = 0; err: - mutex_unlock(&fh->cap.vb_lock); return rc; } @@ -3299,23 +3193,11 @@ static int bttv_open(struct file *file) return -ENOMEM; file->private_data = fh; - /* - * btv is protected by btv->lock mutex, while btv->init and other - * streaming vars are protected by fh->cap.vb_lock. We need to take - * care of both locks to avoid troubles. However, vb_lock is used also - * inside videobuf, without calling buf->lock. So, it is a very bad - * idea to hold both locks at the same time. - * Let's first copy btv->init at fh, holding cap.vb_lock, and then work - * with the rest of init, holding btv->lock. - */ - mutex_lock(&fh->cap.vb_lock); *fh = btv->init; - mutex_unlock(&fh->cap.vb_lock); fh->type = type; fh->ov.setup_ok = 0; - mutex_lock(&btv->lock); v4l2_prio_open(&btv->prio, &fh->prio); videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, @@ -3323,13 +3205,13 @@ static int bttv_open(struct file *file) V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct bttv_buffer), - fh, NULL); + fh, &btv->lock); videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops, &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer), - fh, NULL); + fh, &btv->lock); set_tvnorm(btv,btv->tvnorm); set_input(btv, btv->input, btv->tvnorm); @@ -3352,7 +3234,6 @@ static int bttv_open(struct file *file) bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); bttv_field_count(btv); - mutex_unlock(&btv->lock); return 0; } @@ -3361,7 +3242,6 @@ static int bttv_release(struct file *file) struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); /* turn off overlay */ if (check_btres(fh, RESOURCE_OVERLAY)) bttv_switch_overlay(btv,fh,NULL); @@ -3387,14 +3267,8 @@ static int bttv_release(struct file *file) /* free stuff */ - /* - * videobuf uses cap.vb_lock - we should avoid holding btv->lock, - * otherwise we may have dead lock conditions - */ - mutex_unlock(&btv->lock); videobuf_mmap_free(&fh->cap); videobuf_mmap_free(&fh->vbi); - mutex_lock(&btv->lock); v4l2_prio_close(&btv->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -3404,7 +3278,6 @@ static int bttv_release(struct file *file) if (!btv->users) audio_mute(btv, 1); - mutex_unlock(&btv->lock); return 0; } @@ -3462,9 +3335,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { .vidioc_streamoff = bttv_streamoff, .vidioc_g_tuner = bttv_g_tuner, .vidioc_s_tuner = bttv_s_tuner, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_crop = bttv_g_crop, .vidioc_s_crop = bttv_s_crop, .vidioc_g_fbuf = bttv_g_fbuf, @@ -3508,11 +3378,8 @@ static int radio_open(struct file *file) if (unlikely(!fh)) return -ENOMEM; file->private_data = fh; - mutex_lock(&fh->cap.vb_lock); *fh = btv->init; - mutex_unlock(&fh->cap.vb_lock); - mutex_lock(&btv->lock); v4l2_prio_open(&btv->prio, &fh->prio); btv->radio_user++; @@ -3520,7 +3387,6 @@ static int radio_open(struct file *file) bttv_call_all(btv, tuner, s_radio); audio_input(btv,TVAUDIO_INPUT_RADIO); - mutex_unlock(&btv->lock); return 0; } @@ -3528,17 +3394,15 @@ static int radio_release(struct file *file) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - struct rds_command cmd; + struct saa6588_command cmd; - mutex_lock(&btv->lock); v4l2_prio_close(&btv->prio, fh->prio); file->private_data = NULL; kfree(fh); btv->radio_user--; - bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); - mutex_unlock(&btv->lock); + bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd); return 0; } @@ -3567,7 +3431,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; if (0 != t->index) return -EINVAL; - mutex_lock(&btv->lock); strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; @@ -3576,8 +3439,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 0); - mutex_unlock(&btv->lock); - return 0; } @@ -3668,13 +3529,13 @@ static ssize_t radio_read(struct file *file, char __user *data, { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - struct rds_command cmd; + struct saa6588_command cmd; cmd.block_count = count/3; cmd.buffer = data; cmd.instance = file; cmd.result = -ENODEV; - bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd); + bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd); return cmd.result; } @@ -3683,11 +3544,11 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - struct rds_command cmd; + struct saa6588_command cmd; cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd); + bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd); return cmd.result; } @@ -3698,7 +3559,7 @@ static const struct v4l2_file_operations radio_fops = .open = radio_open, .read = radio_read, .release = radio_release, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .poll = radio_poll, }; @@ -4158,9 +4019,6 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) btv=(struct bttv *)dev_id; - if (btv->custom_irq) - handled = btv->custom_irq(btv); - count=0; while (1) { /* get/clear interrupt status bits */ @@ -4196,7 +4054,6 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) btv->field_count++; if ((astat & BT848_INT_GPINT) && btv->remote) { - wake_up(&btv->gpioq); bttv_input_irq(btv); } @@ -4401,7 +4258,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, mutex_init(&btv->lock); spin_lock_init(&btv->s_lock); spin_lock_init(&btv->gpio_lock); - init_waitqueue_head(&btv->gpioq); init_waitqueue_head(&btv->i2c_queue); INIT_LIST_HEAD(&btv->c.subs); INIT_LIST_HEAD(&btv->capture); @@ -4592,7 +4448,6 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) /* tell gpio modules we are leaving ... */ btv->shutdown=1; - wake_up(&btv->gpioq); bttv_input_fini(btv); bttv_sub_del_devices(&btv->c); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 1989f002898..e8b64bca9db 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -31,15 +31,9 @@ static int ir_debug; module_param(ir_debug, int, 0644); -static int repeat_delay = 500; -module_param(repeat_delay, int, 0644); -static int repeat_period = 33; -module_param(repeat_period, int, 0644); static int ir_rc5_remote_gap = 885; module_param(ir_rc5_remote_gap, int, 0644); -static int ir_rc5_key_timeout = 200; -module_param(ir_rc5_key_timeout, int, 0644); #undef dprintk #define dprintk(arg...) do { \ @@ -55,7 +49,7 @@ module_param(ir_rc5_key_timeout, int, 0644); static void ir_handle_key(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; u32 gpio,data; /* read gpio value */ @@ -74,23 +68,22 @@ static void ir_handle_key(struct bttv *btv) (gpio & ir->mask_keydown) ? " down" : "", (gpio & ir->mask_keyup) ? " up" : ""); - if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || - (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data); + if ((ir->mask_keydown && (gpio & ir->mask_keydown)) || + (ir->mask_keyup && !(gpio & ir->mask_keyup))) { + rc_keydown_notimeout(ir->dev, data, 0); } else { /* HACK: Probably, ir->mask_keydown is missing for this board */ if (btv->c.type == BTTV_BOARD_WINFAST2000) - ir_input_keydown(ir->dev, &ir->ir, data); + rc_keydown_notimeout(ir->dev, data, 0); - ir_input_nokey(ir->dev,&ir->ir); + rc_keyup(ir->dev); } - } static void ir_enltv_handle_key(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; u32 gpio, data, keyup; /* read gpio value */ @@ -107,9 +100,9 @@ static void ir_enltv_handle_key(struct bttv *btv) gpio, data, (gpio & ir->mask_keyup) ? " up" : "up/down"); - ir_input_keydown(ir->dev, &ir->ir, data); + rc_keydown_notimeout(ir->dev, data, 0); if (keyup) - ir_input_nokey(ir->dev, &ir->ir); + rc_keyup(ir->dev); } else { if ((ir->last_gpio & 1 << 31) == keyup) return; @@ -119,26 +112,30 @@ static void ir_enltv_handle_key(struct bttv *btv) (gpio & ir->mask_keyup) ? " up" : "down"); if (keyup) - ir_input_nokey(ir->dev, &ir->ir); + rc_keyup(ir->dev); else - ir_input_keydown(ir->dev, &ir->ir, data); + rc_keydown_notimeout(ir->dev, data, 0); } ir->last_gpio = data | keyup; } +static int bttv_rc5_irq(struct bttv *btv); + void bttv_input_irq(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; - if (!ir->polling) + if (ir->rc5_gpio) + bttv_rc5_irq(btv); + else if (!ir->polling) ir_handle_key(btv); } static void bttv_input_timer(unsigned long data) { struct bttv *btv = (struct bttv*)data; - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; if (btv->c.type == BTTV_BOARD_ENLTV_FM_2) ir_enltv_handle_key(btv); @@ -147,11 +144,109 @@ static void bttv_input_timer(unsigned long data) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } -/* ---------------------------------------------------------------*/ +/* + * FIXME: Nebula digi uses the legacy way to decode RC5, instead of relying + * on the rc-core way. As we need to be sure that both IRQ transitions are + * properly triggered, Better to touch it only with this hardware for + * testing. + */ + +#define RC5_START(x) (((x) >> 12) & 3) +#define RC5_TOGGLE(x) (((x) >> 11) & 1) +#define RC5_ADDR(x) (((x) >> 6) & 31) +#define RC5_INSTR(x) ((x) & 63) + +/* decode raw bit pattern to RC5 code */ +static u32 bttv_rc5_decode(unsigned int code) +{ + unsigned int org_code = code; + unsigned int pair; + unsigned int rc5 = 0; + int i; + + for (i = 0; i < 14; ++i) { + pair = code & 0x3; + code >>= 2; + + rc5 <<= 1; + switch (pair) { + case 0: + case 2: + break; + case 1: + rc5 |= 1; + break; + case 3: + dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n", + org_code); + return 0; + } + } + dprintk(KERN_INFO DEVNAME ":" + "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " + "instr=%x\n", rc5, org_code, RC5_START(rc5), + RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); + return rc5; +} + +static void bttv_rc5_timer_end(unsigned long data) +{ + struct bttv_ir *ir = (struct bttv_ir *)data; + struct timeval tv; + unsigned long current_jiffies; + u32 gap; + u32 rc5 = 0; + + /* get time */ + current_jiffies = jiffies; + do_gettimeofday(&tv); + + /* avoid overflow with gap >1s */ + if (tv.tv_sec - ir->base_time.tv_sec > 1) { + gap = 200000; + } else { + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + } + + /* signal we're ready to start a new code */ + ir->active = false; + + /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ + if (gap < 28000) { + dprintk(KERN_INFO DEVNAME ": spurious timer_end\n"); + return; + } + + if (ir->last_bit < 20) { + /* ignore spurious codes (caused by light/other remotes) */ + dprintk(KERN_INFO DEVNAME ": short code: %x\n", ir->code); + } else { + ir->code = (ir->code << ir->shift_by) | 1; + rc5 = bttv_rc5_decode(ir->code); + + /* two start bits? */ + if (RC5_START(rc5) != ir->start) { + printk(KERN_INFO DEVNAME ":" + " rc5 start bits invalid: %u\n", RC5_START(rc5)); + + /* right address? */ + } else if (RC5_ADDR(rc5) == ir->addr) { + u32 toggle = RC5_TOGGLE(rc5); + u32 instr = RC5_INSTR(rc5); + + /* Good code */ + rc_keydown(ir->dev, instr, toggle); + dprintk(KERN_INFO DEVNAME ":" + " instruction %x, toggle %x\n", + instr, toggle); + } + } +} static int bttv_rc5_irq(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; struct timeval tv; u32 gpio; u32 gap; @@ -160,10 +255,6 @@ static int bttv_rc5_irq(struct bttv *btv) /* read gpio port */ gpio = bttv_gpio_read(&btv->c); - /* remote IRQ? */ - if (!(gpio & 0x20)) - return 0; - /* get time of bit */ current_jiffies = jiffies; do_gettimeofday(&tv); @@ -176,6 +267,13 @@ static int bttv_rc5_irq(struct bttv *btv) tv.tv_usec - ir->base_time.tv_usec; } + dprintk(KERN_INFO DEVNAME ": RC5 IRQ: gap %d us for %s\n", + gap, (gpio & 0x20) ? "mark" : "space"); + + /* remote IRQ? */ + if (!(gpio & 0x20)) + return 0; + /* active code => add bit */ if (ir->active) { /* only if in the code (otherwise spurious IRQ or timer @@ -187,13 +285,12 @@ static int bttv_rc5_irq(struct bttv *btv) } /* starting new code */ } else { - ir->active = 1; + ir->active = true; ir->code = 0; ir->base_time = tv; ir->last_bit = 0; - mod_timer(&ir->timer_end, - current_jiffies + msecs_to_jiffies(30)); + mod_timer(&ir->timer, current_jiffies + msecs_to_jiffies(30)); } /* toggle GPIO pin 4 to reset the irq */ @@ -204,7 +301,7 @@ static int bttv_rc5_irq(struct bttv *btv) /* ---------------------------------------------------------------------- */ -static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) +static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) { if (ir->polling) { setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv); @@ -212,17 +309,10 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) add_timer(&ir->timer); } else if (ir->rc5_gpio) { /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = ir_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; - - init_timer(&ir->timer_keyup); - ir->timer_keyup.function = ir_rc5_timer_keyup; - ir->timer_keyup.data = (unsigned long)ir; + setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir); ir->shift_by = 1; ir->start = 3; ir->addr = 0x0; - ir->rc5_key_timeout = ir_rc5_key_timeout; ir->rc5_remote_gap = ir_rc5_remote_gap; } } @@ -235,7 +325,7 @@ static void bttv_ir_stop(struct bttv *btv) if (btv->remote->rc5_gpio) { u32 gpio; - del_timer_sync(&btv->remote->timer_end); + del_timer_sync(&btv->remote->timer); gpio = bttv_gpio_read(&btv->c); bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); @@ -261,6 +351,18 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 0; dprintk(KERN_INFO DEVNAME ": key %02x\n", b); + /* + * NOTE: + * lirc_i2c maps the pv951 code as: + * addr = 0x61D6 + * cmd = bit_reverse (b) + * So, it seems that this device uses NEC extended + * I decided to not fix the table, due to two reasons: + * 1) Without the actual device, this is only a guess; + * 2) As the addr is not reported via I2C, nor can be changed, + * the device is bound to the vendor-provided RC. + */ + *ir_key = b; *ir_raw = b; return 1; @@ -287,16 +389,15 @@ void __devinit init_bttv_i2c_ir(struct bttv *btv) btv->init_data.name = "PV951"; btv->init_data.get_key = get_key_pv951; btv->init_data.ir_codes = RC_MAP_PV951; - btv->init_data.type = IR_TYPE_OTHER; info.addr = 0x4b; break; default: /* * The external IR receiver is at i2c address 0x34 (0x35 for - * reads). Future Hauppauge cards will have an internal - * receiver at 0x30 (0x31 for reads). In theory, both can be - * fitted, and Hauppauge suggest an external overrides an - * internal. + * reads). Future Hauppauge cards will have an internal + * receiver at 0x30 (0x31 for reads). In theory, both can be + * fitted, and Hauppauge suggest an external overrides an + * internal. * That's why we probe 0x1a (~0x34) first. CB */ @@ -321,18 +422,17 @@ int __devexit fini_bttv_i2c(struct bttv *btv) int bttv_input_init(struct bttv *btv) { - struct card_ir *ir; + struct bttv_ir *ir; char *ir_codes = NULL; - struct input_dev *input_dev; - u64 ir_type = IR_TYPE_OTHER; + struct rc_dev *rc; int err = -ENOMEM; if (!btv->has_remote) return -ENODEV; ir = kzalloc(sizeof(*ir),GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) + rc = rc_allocate_device(); + if (!ir || !rc) goto err_out_free; /* detect & configure */ @@ -395,8 +495,7 @@ int bttv_input_init(struct bttv *btv) break; case BTTV_BOARD_NEBULA_DIGITV: ir_codes = RC_MAP_NEBULA; - btv->custom_irq = bttv_rc5_irq; - ir->rc5_gpio = 1; + ir->rc5_gpio = true; break; case BTTV_BOARD_MACHTV_MAGICTV: ir_codes = RC_MAP_APAC_VIEWCOMP; @@ -438,48 +537,43 @@ int bttv_input_init(struct bttv *btv) } /* init input device */ - ir->dev = input_dev; + ir->dev = rc; snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", btv->c.type); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(btv->c.pci)); - err = ir_input_init(input_dev, &ir->ir, ir_type); - if (err < 0) - goto err_out_free; - - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_PCI; + rc->input_id.version = 1; if (btv->c.pci->subsystem_vendor) { - input_dev->id.vendor = btv->c.pci->subsystem_vendor; - input_dev->id.product = btv->c.pci->subsystem_device; + rc->input_id.vendor = btv->c.pci->subsystem_vendor; + rc->input_id.product = btv->c.pci->subsystem_device; } else { - input_dev->id.vendor = btv->c.pci->vendor; - input_dev->id.product = btv->c.pci->device; + rc->input_id.vendor = btv->c.pci->vendor; + rc->input_id.product = btv->c.pci->device; } - input_dev->dev.parent = &btv->c.pci->dev; + rc->dev.parent = &btv->c.pci->dev; + rc->map_name = ir_codes; + rc->driver_name = MODULE_NAME; btv->remote = ir; bttv_ir_start(btv, ir); /* all done */ - err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_stop; - /* the remote isn't as bouncy as a keyboard */ - ir->dev->rep[REP_DELAY] = repeat_delay; - ir->dev->rep[REP_PERIOD] = repeat_period; - return 0; err_out_stop: bttv_ir_stop(btv); btv->remote = NULL; err_out_free: + rc_free_device(rc); kfree(ir); return err; } @@ -490,7 +584,7 @@ void bttv_input_fini(struct bttv *btv) return; bttv_ir_stop(btv); - ir_input_unregister(btv->remote->dev); + rc_unregister_device(btv->remote->dev); kfree(btv->remote); btv->remote = NULL; } diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 6fd2a8ebda1..fd62bf15d77 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -17,7 +17,6 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/ir-common.h> #include <media/i2c-addr.h> #include <media/tuner.h> diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index d1e26a448ed..9b776faf074 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -41,7 +41,7 @@ #include <linux/device.h> #include <media/videobuf-dma-sg.h> #include <media/tveeprom.h> -#include <media/ir-common.h> +#include <media/rc-core.h> #include <media/ir-kbd-i2c.h> #include "bt848.h" @@ -120,6 +120,33 @@ struct bttv_format { int hshift,vshift; /* for planar modes */ }; +struct bttv_ir { + struct rc_dev *dev; + struct timer_list timer; + + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + int shift_by; + int start; // What should RC5_START() be + int addr; // What RC5_ADDR() should be. + int rc5_remote_gap; + + /* RC5 gpio */ + bool rc5_gpio; /* Is RC5 legacy GPIO enabled? */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + bool active; /* building raw code */ +}; + + /* ---------------------------------------------------------- */ struct bttv_geometry { @@ -305,7 +332,6 @@ struct bttv_pll_info { /* for gpio-connected remote control */ struct bttv_input { struct input_dev *dev; - struct ir_input_state ir; char name[32]; char phys[32]; u32 mask_keycode; @@ -338,12 +364,10 @@ struct bttv { struct bttv_pll_info pll; int triton1; int gpioirq; - int (*custom_irq)(struct bttv *btv); int use_i2c_hw; /* old gpio interface */ - wait_queue_head_t gpioq; int shutdown; void (*volume_gpio)(struct bttv *btv, __u16 volume); @@ -368,7 +392,7 @@ struct bttv { /* infrared remote */ int has_remote; - struct card_ir *remote; + struct bttv_ir *remote; /* I2C remote data */ struct IR_i2c_init_data init_data; diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 935e0c9a967..c1193506131 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, static const struct v4l2_file_operations qcam_fops = { .owner = THIS_MODULE, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .read = qcam_read, }; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 6e4b19698c1..24fc00965a1 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, static const struct v4l2_file_operations qcam_fops = { .owner = THIS_MODULE, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .read = qcam_read, }; diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 7bc36670071..789087cd6a9 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -859,8 +859,6 @@ static int cafe_cam_configure(struct cafe_camera *cam) struct v4l2_mbus_framefmt mbus_fmt; int ret; - if (cam->state != S_IDLE) - return -EINVAL; v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code); ret = sensor_call(cam, core, init, 0); if (ret == 0) @@ -1775,7 +1773,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = { .read = cafe_v4l_read, .poll = cafe_v4l_poll, .mmap = cafe_v4l_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { @@ -2066,8 +2064,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, cam->sensor_addr = 0x42; cam->sensor = v4l2_i2c_new_subdev_cfg(&cam->v4l2_dev, &cam->i2c_adapter, - "ov7670", "ov7670", 0, &sensor_cfg, cam->sensor_addr, - NULL); + "ov7670", 0, &sensor_cfg, cam->sensor_addr, NULL); if (cam->sensor == NULL) { ret = -ENODEV; goto out_smbus; @@ -2197,12 +2194,13 @@ static int cafe_pci_resume(struct pci_dev *pdev) return ret; } cafe_ctlr_init(cam); - cafe_ctlr_power_down(cam); mutex_lock(&cam->s_mutex); if (cam->users > 0) { cafe_ctlr_power_up(cam); __cafe_cam_reset(cam); + } else { + cafe_ctlr_power_down(cam); } mutex_unlock(&cam->s_mutex); diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 46b433bbf2c..7edf80b0d01 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -419,28 +419,6 @@ static int sync(struct camera_data *cam, int frame_nr) /****************************************************************************** * - * ioctl_get_mbuf - * - *****************************************************************************/ -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int ioctl_get_mbuf(void *arg, struct camera_data *cam) -{ - struct video_mbuf *vm; - int i; - vm = arg; - - memset(vm, 0, sizeof(*vm)); - vm->size = cam->frame_size*cam->num_frames; - vm->frames = cam->num_frames; - for (i = 0; i < cam->num_frames; i++) - vm->offsets[i] = cam->frame_size * i; - - return 0; -} -#endif - -/****************************************************************************** - * * ioctl_set_gpio * *****************************************************************************/ @@ -1380,17 +1358,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGMBUF: - { - struct cpia2_fh *fh = file->private_data; - if(fh->prio != V4L2_PRIORITY_RECORD) { - mutex_unlock(&cam->busy_lock); - return -EBUSY; - } - break; - } -#endif default: break; } @@ -1400,11 +1367,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case CPIA2_IOC_SET_GPIO: retval = ioctl_set_gpio(arg, cam); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGMBUF: /* mmap interface */ - retval = ioctl_get_mbuf(arg, cam); - break; -#endif case VIDIOC_QUERYCAP: retval = ioctl_querycap(arg,cam); break; diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index 76c054d1eef..d9d2f6ad6ff 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -1,9 +1,8 @@ config VIDEO_CX18 tristate "Conexant cx23418 MPEG encoder support" depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL - depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT - depends on VIDEO_IR + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c index 8f55692db36..82d195be919 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.c +++ b/drivers/media/video/cx18/cx18-alsa-pcm.c @@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream) static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { - return snd_pcm_lib_ioctl(substream, cmd, arg); + struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); + int ret; + + snd_cx18_lock(cxsc); + ret = snd_pcm_lib_ioctl(substream, cmd, arg); + snd_cx18_unlock(cxsc); + return ret; } diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index fe1090940b0..87177733cf9 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -39,7 +39,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { .tv = { 0x61, 0x60, I2C_CLIENT_END }, }; -/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ +/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ This keeps the PCI ID database up to date. Note that the entries must be added under vendor 0x4444 (Conexant) as subsystem IDs. New vendor IDs should still be added to the vendor ID list. */ @@ -251,6 +251,66 @@ static const struct cx18_card cx18_card_mpc718 = { /* ------------------------------------------------------------------------- */ +/* GoTView PCI */ + +static const struct cx18_card_pci_info cx18_pci_gotview_dvd3[] = { + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_GOTVIEW, 0x3343 }, + { 0, 0, 0 } +}; + +static const struct cx18_card cx18_card_gotview_dvd3 = { + .type = CX18_CARD_GOTVIEW_PCI_DVD3, + .name = "GoTView PCI DVD3 Hybrid", + .comment = "Experimenters needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + .v4l2_capabilities = CX18_CAP_ENCODER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | + CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, + .video_inputs = { + { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, + { CX18_CARD_INPUT_SVIDEO1, 1, + CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, + { CX18_CARD_INPUT_SVIDEO2, 2, + CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, + { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, + }, + .audio_inputs = { + { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, + }, + .tuners = { + /* XC3028 tuner */ + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, + }, + /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, + .ddr = { + /* Hynix HY5DU283222B DDR RAM */ + .chip_config = 0x303, + .refresh = 0x3bd, + .timing1 = 0x36320966, + .timing2 = 0x1f, + .tune_lane = 0, + .initial_emrs = 2, + }, + .gpio_init.initial_value = 0x1, + .gpio_init.direction = 0x3, + + .gpio_audio_input = { .mask = 0x3, + .tuner = 0x1, + .linein = 0x2, + .radio = 0x1 }, + .xceive_pin = 0, + .pci_list = cx18_pci_gotview_dvd3, + .i2c = &cx18_i2c_std, +}; + +/* ------------------------------------------------------------------------- */ + /* Conexant Raptor PAL/SECAM: note that this card is analog only! */ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = { @@ -463,6 +523,7 @@ static const struct cx18_card *cx18_card_list[] = { &cx18_card_toshiba_qosmio_dvbt, &cx18_card_leadtek_pvr2100, &cx18_card_leadtek_dvr3100h, + &cx18_card_gotview_dvd3 }; const struct cx18_card *cx18_get_card(u16 index) @@ -485,7 +546,6 @@ int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input) "Component 1" }; - memset(input, 0, sizeof(*input)); if (index >= cx->nof_inputs) return -EINVAL; input->index = index; diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 67043c7b452..97d7b7e100a 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -108,7 +108,7 @@ static int cx18_try_ctrl(struct file *file, void *fh, struct v4l2_ext_control *vctrl) { struct v4l2_queryctrl qctrl; - const char **menu_items = NULL; + const char * const *menu_items = NULL; int err; qctrl.id = vctrl->id; diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index f6fdcfb1084..133ec2bac18 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -156,6 +156,7 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" "\t\t\t 7 = Leadtek WinFast PVR2100\n" "\t\t\t 8 = Leadtek WinFast DVR3100 H\n" + "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); @@ -339,6 +340,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) tveeprom_hauppauge_analog(&c, tv, eedata); break; case CX18_CARD_YUAN_MPC718: + case CX18_CARD_GOTVIEW_PCI_DVD3: tv->model = 0x718; cx18_eeprom_dump(cx, eedata, sizeof(eedata)); CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n", @@ -929,8 +931,13 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE); if (!cx->enc_mem) { - CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + CX18_ERR("ioremap failed. Can't get a window into CX23418 " + "memory and register space\n"); + CX18_ERR("Each capture card with a CX23418 needs 64 MB of " + "vmalloc address space for the window\n"); + CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + CX18_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 77be58c1096..f6f3e50d4bd 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -84,7 +84,8 @@ #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ #define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ #define CX18_CARD_LEADTEK_DVR3100H 7 /* Leadtek WinFast DVR3100 H */ -#define CX18_CARD_LAST 7 +#define CX18_CARD_GOTVIEW_PCI_DVD3 8 /* GoTView PCI DVD3 Hybrid */ +#define CX18_CARD_LAST 8 #define CX18_ENC_STREAM_TYPE_MPG 0 #define CX18_ENC_STREAM_TYPE_TS 1 @@ -106,6 +107,7 @@ #define CX18_PCI_ID_CONEXANT 0x14f1 #define CX18_PCI_ID_TOSHIBA 0x1179 #define CX18_PCI_ID_LEADTEK 0x107D +#define CX18_PCI_ID_GOTVIEW 0x5854 /* ======================================================================== */ /* ========================== START USER SETTABLE DMA VARIABLES =========== */ @@ -323,7 +325,10 @@ struct cx18_queue { spinlock_t lock; }; +struct cx18_stream; /* forward reference */ + struct cx18_dvb { + struct cx18_stream *stream; struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; struct dmxdev dmxdev; @@ -363,9 +368,10 @@ struct cx18_in_work_order { #define CX18_INVALID_TASK_HANDLE 0xffffffff struct cx18_stream { - /* These first four fields are always set, even if the stream + /* These first five fields are always set, even if the stream is not actually created. */ struct video_device *video_dev; /* NULL when stream not created */ + struct cx18_dvb *dvb; /* DVB / Digital Transport */ struct cx18 *cx; /* for ease of use */ const char *name; /* name of the stream */ int type; /* stream type */ @@ -395,9 +401,6 @@ struct cx18_stream { struct cx18_queue q_idle; /* idle - not in rotation */ struct work_struct out_work_order; - - /* DVB / Digital Transport */ - struct cx18_dvb dvb; }; struct cx18_open_id { diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6d19f040d70..f0381d62518 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -137,7 +137,7 @@ static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) { struct cx18_dvb *dvb = container_of(fe->dvb, struct cx18_dvb, dvb_adapter); - struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); + struct cx18_stream *stream = dvb->stream; const struct firmware *fw = NULL; int ret; int i; @@ -203,6 +203,14 @@ static struct zl10353_config yuan_mpc718_zl10353_demod = { .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ }; +static struct zl10353_config gotview_dvd3_zl10353_demod = { + .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ + .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ + .parallel_ts = 1, /* Not a serial TS */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ +}; + static int dvb_register(struct cx18_stream *stream); /* Kernel DVB framework calls this when the feed needs to start. @@ -247,6 +255,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) case CX18_CARD_LEADTEK_DVR3100H: case CX18_CARD_YUAN_MPC718: + case CX18_CARD_GOTVIEW_PCI_DVD3: default: /* Assumption - Parallel transport - Signalling * undefined or default. @@ -257,22 +266,22 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - mutex_lock(&stream->dvb.feedlock); - if (stream->dvb.feeding++ == 0) { + mutex_lock(&stream->dvb->feedlock); + if (stream->dvb->feeding++ == 0) { CX18_DEBUG_INFO("Starting Transport DMA\n"); mutex_lock(&cx->serialize_lock); set_bit(CX18_F_S_STREAMING, &stream->s_flags); ret = cx18_start_v4l2_encode_stream(stream); if (ret < 0) { CX18_DEBUG_INFO("Failed to start Transport DMA\n"); - stream->dvb.feeding--; - if (stream->dvb.feeding == 0) + stream->dvb->feeding--; + if (stream->dvb->feeding == 0) clear_bit(CX18_F_S_STREAMING, &stream->s_flags); } mutex_unlock(&cx->serialize_lock); } else ret = 0; - mutex_unlock(&stream->dvb.feedlock); + mutex_unlock(&stream->dvb->feedlock); return ret; } @@ -290,15 +299,15 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", feed->pid, feed->index); - mutex_lock(&stream->dvb.feedlock); - if (--stream->dvb.feeding == 0) { + mutex_lock(&stream->dvb->feedlock); + if (--stream->dvb->feeding == 0) { CX18_DEBUG_INFO("Stopping Transport DMA\n"); mutex_lock(&cx->serialize_lock); ret = cx18_stop_v4l2_encode_stream(stream, 0); mutex_unlock(&cx->serialize_lock); } else ret = 0; - mutex_unlock(&stream->dvb.feedlock); + mutex_unlock(&stream->dvb->feedlock); } return ret; @@ -307,7 +316,7 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) int cx18_dvb_register(struct cx18_stream *stream) { struct cx18 *cx = stream->cx; - struct cx18_dvb *dvb = &stream->dvb; + struct cx18_dvb *dvb = stream->dvb; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; @@ -316,6 +325,9 @@ int cx18_dvb_register(struct cx18_stream *stream) if (!dvb) return -EINVAL; + dvb->enabled = 0; + dvb->stream = stream; + ret = dvb_register_adapter(&dvb->dvb_adapter, CX18_DRIVER_NAME, THIS_MODULE, &cx->pci_dev->dev, adapter_nr); @@ -369,7 +381,7 @@ int cx18_dvb_register(struct cx18_stream *stream) CX18_INFO("DVB Frontend registered\n"); CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n", - stream->dvb.dvb_adapter.num, stream->name, + stream->dvb->dvb_adapter.num, stream->name, stream->buffers, stream->buf_size/1024, (stream->buf_size * 100 / 1024) % 100); @@ -396,13 +408,16 @@ err_out: void cx18_dvb_unregister(struct cx18_stream *stream) { struct cx18 *cx = stream->cx; - struct cx18_dvb *dvb = &stream->dvb; + struct cx18_dvb *dvb = stream->dvb; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; CX18_INFO("unregister DVB\n"); + if (dvb == NULL || !dvb->enabled) + return; + dvb_adapter = &dvb->dvb_adapter; dvbdemux = &dvb->demux; dmx = &dvbdemux->dmx; @@ -423,7 +438,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream) */ static int dvb_register(struct cx18_stream *stream) { - struct cx18_dvb *dvb = &stream->dvb; + struct cx18_dvb *dvb = stream->dvb; struct cx18 *cx = stream->cx; int ret = 0; @@ -495,6 +510,29 @@ static int dvb_register(struct cx18_stream *stream) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; + case CX18_CARD_GOTVIEW_PCI_DVD3: + dvb->fe = dvb_attach(zl10353_attach, + &gotview_dvd3_zl10353_demod, + &cx->i2c_adap[1]); + if (dvb->fe != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &cx->i2c_adap[1], + .i2c_addr = 0xc2 >> 1, + .ctrl = NULL, + }; + static struct xc2028_ctrl ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + .type = XC2028_AUTO, + }; + + fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctrl); + } + break; default: /* No Digital Tv Support */ break; diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index a09caf88317..c330fb917b5 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -98,7 +98,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, case CX18_HW_Z8F0811_IR_RX_HAUP: init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; init_data->name = cx->card_name; info.platform_data = init_data; break; @@ -122,15 +122,15 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) if (hw == CX18_HW_TUNER) { /* special tuner group handling */ sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, - adap, NULL, type, 0, cx->card_i2c->radio); + adap, type, 0, cx->card_i2c->radio); if (sd != NULL) sd->grp_id = hw; sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, - adap, NULL, type, 0, cx->card_i2c->demod); + adap, type, 0, cx->card_i2c->demod); if (sd != NULL) sd->grp_id = hw; sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, - adap, NULL, type, 0, cx->card_i2c->tv); + adap, type, 0, cx->card_i2c->tv); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; @@ -144,7 +144,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return -1; /* It's an I2C device other than an analog tuner or IR chip */ - sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, NULL, type, hw_addrs[idx], + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx], NULL); if (sd != NULL) sd->grp_id = hw; diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 956aa190ecc..c545f3beef7 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -136,7 +136,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) { struct cx18_buffer *buf; - if (!s->dvb.enabled || mdl->bytesused == 0) + if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0) return; /* We ignore mdl and buf readpos accounting here - it doesn't matter */ @@ -146,7 +146,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, list); if (buf->bytesused) - dvb_dmx_swfilter(&s->dvb.demux, + dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused); return; } @@ -154,7 +154,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) list_for_each_entry(buf, &mdl->buf_list, list) { if (buf->bytesused == 0) break; - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); + dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused); } } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 9045f1ece0e..94f5d7967c5 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = { .read = cx18_v4l2_read, .open = cx18_v4l2_open, /* FIXME change to video_ioctl2 if serialization lock can be removed */ - .ioctl = cx18_v4l2_ioctl, + .unlocked_ioctl = cx18_v4l2_ioctl, .release = cx18_v4l2_close, .poll = cx18_v4l2_enc_poll, }; @@ -107,6 +107,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->video_dev = video_dev; /* initialize cx18_stream fields */ + s->dvb = NULL; s->cx = cx; s->type = type; s->name = cx18_stream_info[type].name; @@ -140,10 +141,15 @@ static int cx18_prep_dev(struct cx18 *cx, int type) int num_offset = cx18_stream_info[type].num_offset; int num = cx->instance + cx18_first_minor + num_offset; - /* These four fields are always initialized. If video_dev == NULL, then - this stream is not in use. In that case no other fields but these - four can be used. */ + /* + * These five fields are always initialized. + * For analog capture related streams, if video_dev == NULL then the + * stream is not in use. + * For the TS stream, if dvb == NULL then the stream is not in use. + * In those cases no other fields but these four can be used. + */ s->video_dev = NULL; + s->dvb = NULL; s->cx = cx; s->type = type; s->name = cx18_stream_info[type].name; @@ -167,6 +173,21 @@ static int cx18_prep_dev(struct cx18 *cx, int type) cx18_stream_init(cx, type); + /* Allocate the cx18_dvb struct only for the TS on cards with DTV */ + if (type == CX18_ENC_STREAM_TYPE_TS) { + if (cx->card->hw_all & CX18_HW_DVB) { + s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL); + if (s->dvb == NULL) { + CX18_ERR("Couldn't allocate cx18_dvb structure" + " for %s\n", s->name); + return -ENOMEM; + } + } else { + /* Don't need buffers for the TS, if there is no DVB */ + s->buffers = 0; + } + } + if (num_offset == -1) return 0; @@ -222,13 +243,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) const char *name; int num, ret; - /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? - * We need a VFL_TYPE_TS defined. - */ - if (strcmp("TS", s->name) == 0) { - /* just return if no DVB is supported */ - if ((cx->card->hw_all & CX18_HW_DVB) == 0) - return 0; + if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) { ret = cx18_dvb_register(s); if (ret < 0) { CX18_ERR("DVB failed to register\n"); @@ -320,11 +335,13 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) /* Teardown all streams */ for (type = 0; type < CX18_MAX_STREAMS; type++) { - /* No struct video_device, but can have buffers allocated */ + /* The TS has a cx18_dvb structure, not a video_device */ if (type == CX18_ENC_STREAM_TYPE_TS) { - if (cx->streams[type].dvb.enabled) { - cx18_dvb_unregister(&cx->streams[type]); - cx->streams[type].dvb.enabled = false; + if (cx->streams[type].dvb != NULL) { + if (unregister) + cx18_dvb_unregister(&cx->streams[type]); + kfree(cx->streams[type].dvb); + cx->streams[type].dvb = NULL; cx18_stream_free(&cx->streams[type]); } continue; diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 77412bee596..51765eb12d3 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h @@ -33,7 +33,8 @@ void cx18_stream_rotate_idx_mdls(struct cx18 *cx); static inline bool cx18_stream_enabled(struct cx18_stream *s) { - return s->video_dev || s->dvb.enabled || + return s->video_dev || + (s->dvb && s->dvb->enabled) || (s->type == CX18_ENC_STREAM_TYPE_IDX && s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); } diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index bb04914983f..ae85a7a7bd7 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -1,9 +1,9 @@ config VIDEO_CX231XX tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT + depends on VIDEO_DEV && I2C select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on RC_CORE select VIDEOBUF_VMALLOC select VIDEO_CX25840 select VIDEO_CX2341X @@ -14,6 +14,19 @@ config VIDEO_CX231XX To compile this driver as a module, choose M here: the module will be called cx231xx +config VIDEO_CX231XX_RC + bool "Conexant cx231xx Remote Controller additional support" + depends on RC_CORE + depends on VIDEO_CX231XX + default y + ---help--- + cx231xx hardware has a builtin RX/TX support. However, a few + designs opted to not use it, but, instead, some other hardware. + This module enables the usage of those other hardware, like the + ones used with ISDB-T boards. + + On most cases, all you need for IR is mceusb module. + config VIDEO_CX231XX_ALSA tristate "Conexant Cx231xx ALSA audio module" depends on VIDEO_CX231XX && SND @@ -30,6 +43,8 @@ config VIDEO_CX231XX_DVB depends on VIDEO_CX231XX && DVB_CORE select VIDEOBUF_DVB select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE + select DVB_MB86A20S if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile index a6bc4cc5467..2c248435544 100644 --- a/drivers/media/video/cx231xx/Makefile +++ b/drivers/media/video/cx231xx/Makefile @@ -1,5 +1,6 @@ -cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ - cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o +cx231xx-y += cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o +cx231xx-y += cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o +cx231xx-$(CONFIG_VIDEO_CX231XX_RC) += cx231xx-input.o cx231xx-alsa-objs := cx231xx-audio.o diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c index 4c7cac3b625..fc9526a5b74 100644 --- a/drivers/media/video/cx231xx/cx231xx-417.c +++ b/drivers/media/video/cx231xx/cx231xx-417.c @@ -940,14 +940,14 @@ static int cx231xx_load_firmware(struct cx231xx *dev) u16 _buffer_size = 4096; u8 *p_buffer; - p_current_fw = (u32 *)vmalloc(1884180*4); + p_current_fw = vmalloc(1884180 * 4); p_fw = p_current_fw; if (p_current_fw == 0) { dprintk(2, "FAIL!!!\n"); return -1; } - p_buffer = (u8 *)vmalloc(4096); + p_buffer = vmalloc(4096); if (p_buffer == 0) { dprintk(2, "FAIL!!!\n"); return -1; diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index cf50fafa8ab..c53e97295a0 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -274,7 +274,7 @@ int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) if (ch1_setting != 0) { status = afe_read_byte(dev, ADC_INPUT_CH1, &value); - value &= (!INPUT_SEL_MASK); + value &= ~INPUT_SEL_MASK; value |= (ch1_setting - 1) << 4; value &= 0xff; status = afe_write_byte(dev, ADC_INPUT_CH1, value); @@ -282,7 +282,7 @@ int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) if (ch2_setting != 0) { status = afe_read_byte(dev, ADC_INPUT_CH2, &value); - value &= (!INPUT_SEL_MASK); + value &= ~INPUT_SEL_MASK; value |= (ch2_setting - 1) << 4; value &= 0xff; status = afe_write_byte(dev, ADC_INPUT_CH2, value); @@ -292,7 +292,7 @@ int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) 7 less than the input number */ if (ch3_setting != 0) { status = afe_read_byte(dev, ADC_INPUT_CH3, &value); - value &= (!INPUT_SEL_MASK); + value &= ~INPUT_SEL_MASK; value |= (ch3_setting - 1) << 4; value &= 0xff; status = afe_write_byte(dev, ADC_INPUT_CH3, value); @@ -354,6 +354,7 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev, case CX231XX_BOARD_CNXT_VIDEO_GRABBER: case CX231XX_BOARD_HAUPPAUGE_EXETER: case CX231XX_BOARD_HAUPPAUGE_USBLIVE2: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: if (avmode == POLARIS_AVMODE_ANALOGT_TV) { while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | FLD_PWRDN_ENABLE_PLL)) { diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 05b65057b8a..588f3e8f028 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -34,6 +34,7 @@ #include <media/cx25840.h> #include "dvb-usb-ids.h" #include "xc5000.h" +#include "tda18271.h" #include "cx231xx.h" @@ -395,6 +396,45 @@ struct cx231xx_board cx231xx_boards[] = { .gpio = 0, } }, }, + [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { + .name = "Pixelview PlayTV USB Hybrid", + .tuner_type = TUNER_NXP_TDA18271, + .tuner_addr = 0x60, + .decoder = CX231XX_AVDECODER, + .output_mode = OUT_MODE_VIP11, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */ + .tuner_sif_gpio = -1, + .tuner_scl_gpio = -1, + .tuner_sda_gpio = -1, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 2, + .demod_i2c_master = 1, + .ir_i2c_master = 2, + .rc_map_name = RC_MAP_PIXELVIEW_002T, + .has_dvb = 1, + .demod_addr = 0x10, + .norm = V4L2_STD_PAL_M, + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } }, + }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); @@ -402,8 +442,6 @@ const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); struct usb_device_id cx231xx_id_table[] = { {USB_DEVICE(0x0572, 0x5A3C), .driver_info = CX231XX_BOARD_UNKNOWN}, - {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff), - .driver_info = CX231XX_BOARD_UNKNOWN}, {USB_DEVICE(0x0572, 0x58A2), .driver_info = CX231XX_BOARD_CNXT_CARRAERA}, {USB_DEVICE(0x0572, 0x58A1), @@ -424,6 +462,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, {USB_DEVICE(0x2040, 0xc200), .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2}, + {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001), + .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, {}, }; @@ -453,6 +493,16 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) 1); msleep(10); } + } else if (dev->tuner_type == TUNER_NXP_TDA18271) { + switch (command) { + case TDA18271_CALLBACK_CMD_AGC_ENABLE: + if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID) + rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg); + break; + default: + rc = -EINVAL; + break; + } } return rc; } @@ -560,7 +610,7 @@ void cx231xx_card_setup(struct cx231xx *dev) if (dev->board.decoder == CX231XX_AVDECODER) { dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[0].i2c_adap, - NULL, "cx25840", 0x88 >> 1, NULL); + "cx25840", 0x88 >> 1, NULL); if (dev->sd_cx25840 == NULL) cx231xx_info("cx25840 subdev registration failure\n"); cx25840_call(dev, core, load_fw); @@ -571,7 +621,7 @@ void cx231xx_card_setup(struct cx231xx *dev) if (dev->board.tuner_type != TUNER_ABSENT) { dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - NULL, "tuner", + "tuner", dev->tuner_addr, NULL); if (dev->sd_tuner == NULL) cx231xx_info("tuner subdev registration failure\n"); @@ -615,8 +665,11 @@ void cx231xx_release_resources(struct cx231xx *dev) cx231xx_remove_from_devlist(dev); + /* Release I2C buses */ cx231xx_dev_uninit(dev); + cx231xx_ir_exit(dev); + usb_put_dev(dev->udev); /* Mark device as unused */ @@ -731,16 +784,14 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, retval = cx231xx_register_analog_devices(dev); if (retval < 0) { cx231xx_release_resources(dev); - goto fail_reg_devices; + return retval; } + cx231xx_ir_init(dev); + cx231xx_init_extension(dev); return 0; - -fail_reg_devices: - mutex_unlock(&dev->lock); - return retval; } #if defined(CONFIG_MODULES) && defined(MODULE) diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index 4af46fca9b0..7d62d58617f 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -740,6 +740,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_HAUPPAUGE_EXETER: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: @@ -1288,7 +1289,7 @@ int cx231xx_dev_init(struct cx231xx *dev) /* Internal Master 3 Bus */ dev->i2c_bus[2].nr = 2; dev->i2c_bus[2].dev = dev; - dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */ + dev->i2c_bus[2].i2c_period = I2C_SPEED_100K; /* 100kHz */ dev->i2c_bus[2].i2c_nostop = 0; dev->i2c_bus[2].i2c_reserve = 0; @@ -1381,6 +1382,7 @@ int cx231xx_dev_init(struct cx231xx *dev) case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_HAUPPAUGE_EXETER: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: @@ -1513,7 +1515,7 @@ int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ @@ -1564,7 +1566,7 @@ int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ @@ -1598,7 +1600,7 @@ int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ @@ -1639,7 +1641,7 @@ int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index 5feb3ee640d..fe59a1c3f06 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -33,6 +33,7 @@ #include "tda18271.h" #include "s5h1411.h" #include "lgdt3305.h" +#include "mb86a20s.h" MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); @@ -88,6 +89,11 @@ static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = { .if_lvl = 1, .rfagc_top = 0x37, }, }; +static struct tda18271_std_map mb86a20s_tda18271_config = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 7, .rfagc_top = 0x37, }, +}; + static struct tda18271_config cnxt_rde253s_tunerconfig = { .std_map = &cnxt_rde253s_tda18271_std_map, .gate = TDA18271_GATE_ANALOG, @@ -135,6 +141,17 @@ static struct tda18271_config hcw_tda18271_config = { .gate = TDA18271_GATE_DIGITAL, }; +static const struct mb86a20s_config pv_mb86a20s_config = { + .demod_address = 0x10, + .is_serial = true, +}; + +static struct tda18271_config pv_tda18271_config = { + .std_map = &mb86a20s_tda18271_config, + .gate = TDA18271_GATE_DIGITAL, + .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, +}; + static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -687,6 +704,29 @@ static int dvb_init(struct cx231xx *dev) &hcw_tda18271_config); break; + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: + + printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n", + __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap)); + + dev->dvb->frontend = dvb_attach(mb86a20s_attach, + &pv_mb86a20s_config, + &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); + + if (dev->dvb->frontend == NULL) { + printk(DRIVER_NAME + ": Failed to attach mb86a20s demod\n"); + result = -EINVAL; + goto out_free; + } + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + dvb_attach(tda18271_attach, dev->dvb->frontend, + 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, + &pv_tda18271_config); + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c new file mode 100644 index 00000000000..45e14cac462 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -0,0 +1,112 @@ +/* + * cx231xx IR glue driver + * + * Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com> + * + * Polaris (cx231xx) has its support for IR's with a design close to MCE. + * however, a few designs are using an external I2C chip for IR, instead + * of using the one provided by the chip. + * This driver provides support for those extra devices + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include "cx231xx.h" +#include <linux/usb.h> +#include <linux/slab.h> + +#define MODULE_NAME "cx231xx-input" + +static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, + u32 *ir_raw) +{ + u8 cmd, scancode; + + dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); + + /* poll IR chip */ + if (1 != i2c_master_recv(ir->c, &cmd, 1)) + return -EIO; + + /* it seems that 0xFE indicates that a button is still hold + down, while 0xff indicates that no button is hold + down. 0xfe sequences are sometimes interrupted by 0xFF */ + + if (cmd == 0xff) + return 0; + + scancode = + ((cmd & 0x01) ? 0x80 : 0) | + ((cmd & 0x02) ? 0x40 : 0) | + ((cmd & 0x04) ? 0x20 : 0) | + ((cmd & 0x08) ? 0x10 : 0) | + ((cmd & 0x10) ? 0x08 : 0) | + ((cmd & 0x20) ? 0x04 : 0) | + ((cmd & 0x40) ? 0x02 : 0) | + ((cmd & 0x80) ? 0x01 : 0); + + dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n", + cmd, scancode); + + *ir_key = scancode; + *ir_raw = scancode; + return 1; +} + +int cx231xx_ir_init(struct cx231xx *dev) +{ + struct i2c_board_info info; + u8 ir_i2c_bus; + + dev_dbg(&dev->udev->dev, "%s\n", __func__); + + /* Only initialize if a rc keycode map is defined */ + if (!cx231xx_boards[dev->model].rc_map_name) + return -ENODEV; + + request_module("ir-kbd-i2c"); + + memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + dev->init_data.rc_dev = rc_allocate_device(); + if (!dev->init_data.rc_dev) + return -ENOMEM; + + dev->init_data.name = cx231xx_boards[dev->model].name; + + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + info.platform_data = &dev->init_data; + + /* + * Board-dependent values + * + * For now, there's just one type of hardware design using + * an i2c device. + */ + dev->init_data.get_key = get_key_isdbt; + dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name; + /* The i2c micro-controller only outputs the cmd part of NEC protocol */ + dev->init_data.rc_dev->scanmask = 0xff; + dev->init_data.rc_dev->driver_name = "cx231xx"; + dev->init_data.type = RC_TYPE_NEC; + info.addr = 0x30; + + /* Load and bind ir-kbd-i2c */ + ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; + dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", + ir_i2c_bus, info.addr); + i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); + + return 0; +} + +void cx231xx_ir_exit(struct cx231xx *dev) +{ +} diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index b13b69fb2af..7e3e8c4f19b 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -2044,15 +2044,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct cx231xx_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ @@ -2507,9 +2498,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static struct video_device cx231xx_vbi_template; diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index d067df9b81e..72bbea2bcd5 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -34,7 +34,8 @@ #include <media/videobuf-vmalloc.h> #include <media/v4l2-device.h> -#include <media/ir-core.h> +#include <media/rc-core.h> +#include <media/ir-kbd-i2c.h> #include <media/videobuf-dvb.h> #include "cx231xx-reg.h" @@ -62,6 +63,7 @@ #define CX231XX_BOARD_CNXT_RDU_250 7 #define CX231XX_BOARD_HAUPPAUGE_EXETER 8 #define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9 +#define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10 /* Limits minimum and default number of buffers */ #define CX231XX_MIN_BUF 4 @@ -344,6 +346,10 @@ struct cx231xx_board { /* i2c masters */ u8 tuner_i2c_master; u8 demod_i2c_master; + u8 ir_i2c_master; + + /* for devices with I2C chips for IR */ + char *rc_map_name; unsigned int max_range_640_480:1; unsigned int has_dvb:1; @@ -356,7 +362,7 @@ struct cx231xx_board { struct cx231xx_input input[MAX_CX231XX_INPUT]; struct cx231xx_input radio; - struct ir_scancode_table *ir_codes; + struct rc_map *ir_codes; }; /* device states */ @@ -605,6 +611,9 @@ struct cx231xx { struct cx231xx_board board; + /* For I2C IR support */ + struct IR_i2c_init_data init_data; + unsigned int stream_on:1; /* Locks streams */ unsigned int vbi_stream_on:1; /* Locks streams for VBI */ unsigned int has_audio_class:1; @@ -616,8 +625,6 @@ struct cx231xx { struct v4l2_subdev *sd_cx25840; struct v4l2_subdev *sd_tuner; - struct cx231xx_IR *ir; - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ atomic_t stream_started; /* stream should be running if true */ @@ -954,6 +961,17 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); extern int cx231xx_417_register(struct cx231xx *dev); extern void cx231xx_417_unregister(struct cx231xx *dev); +/* cx23885-input.c */ + +#if defined(CONFIG_VIDEO_CX231XX_RC) +int cx231xx_ir_init(struct cx231xx *dev); +void cx231xx_ir_exit(struct cx231xx *dev); +#else +#define cx231xx_ir_init(dev) (0) +#define cx231xx_ir_exit(dev) (0) +#endif + + /* printk macros */ #define cx231xx_err(fmt, arg...) do {\ diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index e5c3c8da4be..103ef6bad2e 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -853,9 +853,9 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, } EXPORT_SYMBOL(cx2341x_ctrl_query); -const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) +const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) { - static const char *mpeg_stream_type_without_ts[] = { + static const char * const mpeg_stream_type_without_ts[] = { "MPEG-2 Program Stream", "", "MPEG-1 System Stream", @@ -952,7 +952,7 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; struct v4l2_queryctrl qctrl; - const char **menu_items = NULL; + const char * const *menu_items = NULL; qctrl.id = ctrl->id; err = cx2341x_ctrl_query(params, &qctrl); @@ -1135,7 +1135,7 @@ EXPORT_SYMBOL(cx2341x_update); static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id) { - const char **menu = cx2341x_ctrl_get_menu(p, id); + const char * const *menu = cx2341x_ctrl_get_menu(p, id); struct v4l2_ext_control ctrl; if (menu == NULL) diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index e1367b35647..6b4a516addf 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -5,7 +5,7 @@ config VIDEO_CX23885 select VIDEO_BTCX select VIDEO_TUNER select VIDEO_TVEEPROM - depends on IR_CORE + depends on RC_CORE select VIDEOBUF_DVB select VIDEOBUF_DMA_SG select VIDEO_CX25840 diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index c95e7bc1474..209b971bd26 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c @@ -368,7 +368,7 @@ static void netup_read_ci_status(struct work_struct *work) DVB_CA_EN50221_POLL_CAM_READY; else state->status = 0; - }; + } } /* CI irq handler */ @@ -377,16 +377,24 @@ int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status) struct cx23885_tsport *port = NULL; struct netup_ci_state *state = NULL; - if (pci_status & PCI_MSK_GPIO0) - port = &dev->ts1; - else if (pci_status & PCI_MSK_GPIO1) - port = &dev->ts2; - else /* who calls ? */ + ci_dbg_print("%s:\n", __func__); + + if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1))) return 0; - state = port->port_priv; + if (pci_status & PCI_MSK_GPIO0) { + port = &dev->ts1; + state = port->port_priv; + schedule_work(&state->work); + ci_dbg_print("%s: Wakeup CI0\n", __func__); + } - schedule_work(&state->work); + if (pci_status & PCI_MSK_GPIO1) { + port = &dev->ts2; + state = port->port_priv; + schedule_work(&state->work); + ci_dbg_print("%s: Wakeup CI1\n", __func__); + } return 1; } diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index db054004e46..b298b730943 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -309,6 +309,26 @@ struct cx23885_board cx23885_boards[] = { CX25840_COMPONENT_ON, } }, }, + [CX23885_BOARD_GOTVIEW_X5_3D_HYBRID] = { + .name = "GoTView X5 3D Hybrid", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x64, + .porta = CX23885_ANALOG_VIDEO, + .portb = CX23885_MPEG_DVB, + .input = {{ + .type = CX23885_VMUX_TELEVISION, + .vmux = CX25840_VIN2_CH1 | + CX25840_VIN5_CH2, + .gpio0 = 0x02, + }, { + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX23885_VMUX_COMPOSITE1, + }, { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_SVIDEO_LUMA3 | + CX25840_SVIDEO_CHROMA4, + } }, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -496,6 +516,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x107d, .subdevice = 0x6f22, .card = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200, + }, { + .subvendor = 0x5654, + .subdevice = 0x2390, + .card = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -712,6 +736,10 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) else if (port->nr == 2) bitmask = 0x04; break; + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: + /* Tuner Reset Command */ + bitmask = 0x02; + break; } if (bitmask) { @@ -967,6 +995,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* CX24228 GPIO */ /* Connected to IF / Mux */ break; + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: + cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */ + break; } } @@ -1218,6 +1249,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -1245,9 +1277,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_MAGICPRO_PROHDTVE2: case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, - NULL, "cx25840", 0x88 >> 1, NULL); + "cx25840", 0x88 >> 1, NULL); if (dev->sd_cx25840) { dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE; v4l2_subdev_call(dev->sd_cx25840, core, load_fw); diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 4a326fe0b01..199b9964bbe 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -35,9 +35,8 @@ * 02110-1301, USA. */ -#include <linux/input.h> #include <linux/slab.h> -#include <media/ir-core.h> +#include <media/rc-core.h> #include <media/v4l2-subdev.h> #include "cx23885.h" @@ -62,16 +61,16 @@ static void cx23885_input_process_measurements(struct cx23885_dev *dev, count = num / sizeof(struct ir_raw_event); for (i = 0; i < count; i++) { - ir_raw_event_store(kernel_ir->inp_dev, + ir_raw_event_store(kernel_ir->rc, &ir_core_event[i]); handle = true; } } while (num != 0); if (overrun) - ir_raw_event_reset(kernel_ir->inp_dev); + ir_raw_event_reset(kernel_ir->rc); else if (handle) - ir_raw_event_handle(kernel_ir->inp_dev); + ir_raw_event_handle(kernel_ir->rc); } void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) @@ -197,9 +196,9 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev) return 0; } -static int cx23885_input_ir_open(void *priv) +static int cx23885_input_ir_open(struct rc_dev *rc) { - struct cx23885_kernel_ir *kernel_ir = priv; + struct cx23885_kernel_ir *kernel_ir = rc->priv; if (kernel_ir->cx == NULL) return -ENODEV; @@ -232,9 +231,9 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) } } -static void cx23885_input_ir_close(void *priv) +static void cx23885_input_ir_close(struct rc_dev *rc) { - struct cx23885_kernel_ir *kernel_ir = priv; + struct cx23885_kernel_ir *kernel_ir = rc->priv; if (kernel_ir->cx != NULL) cx23885_input_ir_stop(kernel_ir->cx); @@ -243,9 +242,7 @@ static void cx23885_input_ir_close(void *priv) int cx23885_input_init(struct cx23885_dev *dev) { struct cx23885_kernel_ir *kernel_ir; - struct input_dev *inp_dev; - struct ir_dev_props *props; - + struct rc_dev *rc; char *rc_map; enum rc_driver_type driver_type; unsigned long allowed_protos; @@ -265,14 +262,14 @@ int cx23885_input_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1250: /* Integrated CX2388[58] IR controller */ driver_type = RC_DRIVER_IR_RAW; - allowed_protos = IR_TYPE_ALL; + allowed_protos = RC_TYPE_ALL; /* The grey Hauppauge RC-5 remote */ rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; break; case CX23885_BOARD_TEVII_S470: /* Integrated CX23885 IR controller */ driver_type = RC_DRIVER_IR_RAW; - allowed_protos = IR_TYPE_ALL; + allowed_protos = RC_TYPE_ALL; /* A guess at the remote */ rc_map = RC_MAP_TEVII_NEC; break; @@ -292,37 +289,36 @@ int cx23885_input_init(struct cx23885_dev *dev) pci_name(dev->pci)); /* input device */ - inp_dev = input_allocate_device(); - if (inp_dev == NULL) { + rc = rc_allocate_device(); + if (!rc) { ret = -ENOMEM; goto err_out_free; } - kernel_ir->inp_dev = inp_dev; - inp_dev->name = kernel_ir->name; - inp_dev->phys = kernel_ir->phys; - inp_dev->id.bustype = BUS_PCI; - inp_dev->id.version = 1; + kernel_ir->rc = rc; + rc->input_name = kernel_ir->name; + rc->input_phys = kernel_ir->phys; + rc->input_id.bustype = BUS_PCI; + rc->input_id.version = 1; if (dev->pci->subsystem_vendor) { - inp_dev->id.vendor = dev->pci->subsystem_vendor; - inp_dev->id.product = dev->pci->subsystem_device; + rc->input_id.vendor = dev->pci->subsystem_vendor; + rc->input_id.product = dev->pci->subsystem_device; } else { - inp_dev->id.vendor = dev->pci->vendor; - inp_dev->id.product = dev->pci->device; + rc->input_id.vendor = dev->pci->vendor; + rc->input_id.product = dev->pci->device; } - inp_dev->dev.parent = &dev->pci->dev; - - /* kernel ir device properties */ - props = &kernel_ir->props; - props->driver_type = driver_type; - props->allowed_protos = allowed_protos; - props->priv = kernel_ir; - props->open = cx23885_input_ir_open; - props->close = cx23885_input_ir_close; + rc->dev.parent = &dev->pci->dev; + rc->driver_type = driver_type; + rc->allowed_protos = allowed_protos; + rc->priv = kernel_ir; + rc->open = cx23885_input_ir_open; + rc->close = cx23885_input_ir_close; + rc->map_name = rc_map; + rc->driver_name = MODULE_NAME; /* Go */ dev->kernel_ir = kernel_ir; - ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME); + ret = rc_register_device(rc); if (ret) goto err_out_stop; @@ -331,7 +327,7 @@ int cx23885_input_init(struct cx23885_dev *dev) err_out_stop: cx23885_input_ir_stop(dev); dev->kernel_ir = NULL; - /* TODO: double check clean-up of kernel_ir->inp_dev */ + rc_free_device(rc); err_out_free: kfree(kernel_ir->phys); kfree(kernel_ir->name); @@ -346,7 +342,7 @@ void cx23885_input_fini(struct cx23885_dev *dev) if (dev->kernel_ir == NULL) return; - ir_input_unregister(dev->kernel_ir->inp_dev); + rc_unregister_device(dev->kernel_ir->rc); kfree(dev->kernel_ir->phys); kfree(dev->kernel_ir->name); kfree(dev->kernel_ir); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 3cc9f462d08..644fcb808c0 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1024,35 +1024,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, - struct video_mbuf *mbuf) -{ - struct cx23885_fh *fh = priv; - struct videobuf_queue *q; - struct v4l2_requestbuffers req; - unsigned int i; - int err; - - q = get_queue(fh); - memset(&req, 0, sizeof(req)); - req.type = q->type; - req.count = 8; - req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(q, &req); - if (err < 0) - return err; - - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; - } - return 0; -} -#endif - static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { @@ -1155,7 +1126,6 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) if (0 == INPUT(n)->type) return -EINVAL; - memset(i, 0, sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, iname[INPUT(n)->type]); @@ -1427,9 +1397,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, @@ -1507,10 +1474,10 @@ int cx23885_video_register(struct cx23885_dev *dev) if (dev->tuner_addr) sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - NULL, "tuner", dev->tuner_addr, NULL); + "tuner", dev->tuner_addr, NULL); else sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_bus[1].i2c_adap, NULL, + &dev->i2c_bus[1].i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV)); if (sd) { struct tuner_setup tun_setup; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index ed94b17dd8a..62e41ab6581 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -30,7 +30,7 @@ #include <media/tveeprom.h> #include <media/videobuf-dma-sg.h> #include <media/videobuf-dvb.h> -#include <media/ir-core.h> +#include <media/rc-core.h> #include "btcx-risc.h" #include "cx23885-reg.h" @@ -84,6 +84,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 #define CX23885_BOARD_MYGICA_X8558PRO 27 #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28 +#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID 29 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 @@ -310,8 +311,7 @@ struct cx23885_kernel_ir { char *name; char *phys; - struct input_dev *inp_dev; - struct ir_dev_props props; + struct rc_dev *rc; }; struct cx23885_dev { diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index e78e3e4c811..e37be6fcf67 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -26,7 +26,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> -#include <media/ir-core.h> +#include <media/rc-core.h> #include "cx23885.h" diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index dfb198d0415..f16461844c5 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1989,8 +1989,23 @@ static int cx25840_probe(struct i2c_client *client, v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops, V4L2_CID_HUE, -128, 127, 1, 0); if (!is_cx2583x(state)) { - default_volume = 228 - cx25840_read(client, 0x8d4); - default_volume = ((default_volume / 2) + 23) << 9; + default_volume = cx25840_read(client, 0x8d4); + /* + * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume + * scale mapping limits to avoid -ERANGE errors when + * initializing the volume control + */ + if (default_volume > 228) { + /* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */ + default_volume = 228; + cx25840_write(client, 0x8d4, 228); + } + else if (default_volume < 20) { + /* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */ + default_volume = 20; + cx25840_write(client, 0x8d4, 20); + } + default_volume = (((228 - default_volume) >> 1) + 23) << 9; state->volume = v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME, diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c index 97a4e9b25fe..627926f6bde 100644 --- a/drivers/media/video/cx25840/cx25840-ir.c +++ b/drivers/media/video/cx25840/cx25840-ir.c @@ -24,7 +24,7 @@ #include <linux/slab.h> #include <linux/kfifo.h> #include <media/cx25840.h> -#include <media/ir-core.h> +#include <media/rc-core.h> #include "cx25840-core.h" diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0fa85cbefbb..5c42abdf422 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,12 +1,11 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && INPUT + depends on VIDEO_DEV && PCI && I2C && RC_CORE select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Conexant 2388x based diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 4aaa47c0eab..54b7fcd469a 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -40,7 +40,6 @@ #include <sound/control.h> #include <sound/initval.h> #include <sound/tlv.h> -#include <media/wm8775.h> #include "cx88.h" #include "cx88-reg.h" @@ -587,47 +586,26 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, int left, right, v, b; int changed = 0; u32 old; - struct v4l2_control client_ctl; - - /* Pass volume & balance onto any WM8775 */ - if (value->value.integer.value[0] >= value->value.integer.value[1]) { - v = value->value.integer.value[0] << 10; - b = value->value.integer.value[0] ? - (0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] : - 0x8000; - } else { - v = value->value.integer.value[1] << 10; - b = value->value.integer.value[1] ? - 0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] : - 0x8000; - } - client_ctl.value = v; - client_ctl.id = V4L2_CID_AUDIO_VOLUME; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - - client_ctl.value = b; - client_ctl.id = V4L2_CID_AUDIO_BALANCE; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); left = value->value.integer.value[0] & 0x3f; right = value->value.integer.value[1] & 0x3f; b = right - left; if (b < 0) { - v = 0x3f - left; - b = (-b) | 0x40; + v = 0x3f - left; + b = (-b) | 0x40; } else { - v = 0x3f - right; + v = 0x3f - right; } /* Do we really know this will always be called with IRQs on? */ spin_lock_irq(&chip->reg_lock); old = cx_read(AUD_VOL_CTL); if (v != (old & 0x3f)) { - cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v); - changed = 1; + cx_write(AUD_VOL_CTL, (old & ~0x3f) | v); + changed = 1; } - if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) { - cx_write(AUD_BAL_CTL, b); - changed = 1; + if (cx_read(AUD_BAL_CTL) != b) { + cx_write(AUD_BAL_CTL, b); + changed = 1; } spin_unlock_irq(&chip->reg_lock); @@ -640,7 +618,7 @@ static const struct snd_kcontrol_new snd_cx88_volume = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Analog-TV Volume", + .name = "Playback Volume", .info = snd_cx88_volume_info, .get = snd_cx88_volume_get, .put = snd_cx88_volume_put, @@ -671,14 +649,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, vol = cx_read(AUD_VOL_CTL); if (value->value.integer.value[0] != !(vol & bit)) { vol ^= bit; - cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); - /* Pass mute onto any WM8775 */ - if ((1<<6) == bit) { - struct v4l2_control client_ctl; - client_ctl.value = 0 != (vol & bit); - client_ctl.id = V4L2_CID_AUDIO_MUTE; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - } + cx_write(AUD_VOL_CTL, vol); ret = 1; } spin_unlock_irq(&chip->reg_lock); @@ -687,7 +658,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new snd_cx88_dac_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Audio-Out Switch", + .name = "Playback Switch", .info = snd_ctl_boolean_mono_info, .get = snd_cx88_switch_get, .put = snd_cx88_switch_put, @@ -696,49 +667,13 @@ static const struct snd_kcontrol_new snd_cx88_dac_switch = { static const struct snd_kcontrol_new snd_cx88_source_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog-TV Switch", + .name = "Capture Switch", .info = snd_ctl_boolean_mono_info, .get = snd_cx88_switch_get, .put = snd_cx88_switch_put, .private_value = (1<<6), }; -static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - struct v4l2_control client_ctl; - - client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; - call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl); - value->value.integer.value[0] = client_ctl.value ? 1 : 0; - - return 0; -} - -static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - struct v4l2_control client_ctl; - - client_ctl.value = 0 != value->value.integer.value[0]; - client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - - return 0; -} - -static struct snd_kcontrol_new snd_cx88_alc_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line-In ALC Switch", - .info = snd_ctl_boolean_mono_info, - .get = snd_cx88_alc_get, - .put = snd_cx88_alc_put, -}; - /**************************************************************************** Basic Flow for Sound Devices ****************************************************************************/ @@ -860,7 +795,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, { struct snd_card *card; snd_cx88_card_t *chip; - struct v4l2_subdev *sd; int err; if (devno >= SNDRV_CARDS) @@ -896,15 +830,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, if (err < 0) goto error; - /* If there's a wm8775 then add a Line-In ALC switch */ - list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) { - if (WM8775_GID == sd->grp_id) { - snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, - chip)); - break; - } - } - strcpy (card->driver, "CX88x"); sprintf(card->shortname, "Conexant CX%x", pci->device); sprintf(card->longname, "%s at %#llx", diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index d7c94848249..bca307eb1e2 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1064,7 +1064,7 @@ static int mpeg_open(struct file *file) err = drv->request_acquire(drv); if(err != 0) { dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); - mutex_unlock(&dev->core->lock);; + mutex_unlock(&dev->core->lock); return err; } } diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index b26fcba8600..4e6ee5584cb 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -47,7 +47,7 @@ MODULE_PARM_DESC(latency,"pci latency timer"); static int disable_ir; module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(latency, "Disable IR support"); +MODULE_PARM_DESC(disable_ir, "Disable IR support"); #define info_printk(core, fmt, arg...) \ printk(KERN_INFO "%s: " fmt, core->name , ## arg) @@ -1007,15 +1007,22 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .audio_chip = V4L2_IDENT_WM8775, .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + /* 2: Line-In */ + .audioroute = 2, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, + /* 2: Line-In */ + .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, + /* 2: Line-In */ + .audioroute = 2, }}, .mpeg = CX88_MPEG_DVB, }, @@ -3515,19 +3522,18 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) later code configures a tea5767. */ v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - NULL, "tuner", - 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); if (has_demod) v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, NULL, "tuner", + &core->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, NULL, "tuner", + &core->i2c_adap, "tuner", 0, has_demod ? tv_addrs + 4 : tv_addrs); } else { v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - NULL, "tuner", core->board.tuner_addr, NULL); + "tuner", core->board.tuner_addr, NULL); } } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 367a653f4c9..90717ee944e 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -67,6 +67,10 @@ static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); +static unsigned int dvb_buf_tscnt = 32; +module_param(dvb_buf_tscnt, int, 0644); +MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]"); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define dprintk(level,fmt, arg...) if (debug >= level) \ @@ -80,10 +84,10 @@ static int dvb_buf_setup(struct videobuf_queue *q, struct cx8802_dev *dev = q->priv_data; dev->ts_packet_size = 188 * 4; - dev->ts_packet_count = 32; + dev->ts_packet_count = dvb_buf_tscnt; *size = dev->ts_packet_size * dev->ts_packet_count; - *count = 32; + *count = dvb_buf_tscnt; return 0; } diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index f53836bb6a5..a1fe0abb6e4 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -146,7 +146,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); core->i2c_adap.owner = THIS_MODULE; - core->i2c_adap.id = I2C_HW_B_CX2388x; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index fc777bc6e71..06f7d1d0094 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -24,14 +24,12 @@ #include <linux/init.h> #include <linux/hrtimer.h> -#include <linux/input.h> #include <linux/pci.h> #include <linux/slab.h> #include <linux/module.h> #include "cx88.h" -#include <media/ir-core.h> -#include <media/ir-common.h> +#include <media/rc-core.h> #define MODULE_NAME "cx88xx" @@ -39,9 +37,7 @@ struct cx88_IR { struct cx88_core *core; - struct input_dev *input; - struct ir_dev_props props; - u64 ir_type; + struct rc_dev *dev; int users; @@ -50,8 +46,6 @@ struct cx88_IR { /* sample from gpio pin 16 */ u32 sampling; - u32 samples[16]; - int scount; /* poll external decoder */ int polling; @@ -63,6 +57,10 @@ struct cx88_IR { u32 mask_keyup; }; +static unsigned ir_samplerate = 4; +module_param(ir_samplerate, uint, 0444); +MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4"); + static int ir_debug; module_param(ir_debug, int, 0644); /* debug level [IR] */ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); @@ -70,6 +68,9 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); #define ir_dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg) +#define dprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "cx88 IR: " fmt , ##arg) + /* ---------------------------------------------------------------------- */ static void cx88_ir_handle_key(struct cx88_IR *ir) @@ -125,21 +126,26 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) data = (data << 4) | ((gpio_key & 0xf0) >> 4); - ir_keydown(ir->input, data, 0); + rc_keydown(ir->dev, data, 0); } else if (ir->mask_keydown) { /* bit set on keydown */ if (gpio & ir->mask_keydown) - ir_keydown(ir->input, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); + else + rc_keyup(ir->dev); } else if (ir->mask_keyup) { /* bit cleared on keydown */ if (0 == (gpio & ir->mask_keyup)) - ir_keydown(ir->input, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); + else + rc_keyup(ir->dev); } else { /* can't distinguish keydown/up :-/ */ - ir_keydown(ir->input, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); + rc_keyup(ir->dev); } } @@ -176,8 +182,8 @@ static int __cx88_ir_start(void *priv) } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; - cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ - cx_write(MO_DDSCFG_IO, 0x5); /* enable */ + cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */ + cx_write(MO_DDSCFG_IO, 0x5); /* enable */ } return 0; } @@ -214,17 +220,17 @@ void cx88_ir_stop(struct cx88_core *core) __cx88_ir_stop(core); } -static int cx88_ir_open(void *priv) +static int cx88_ir_open(struct rc_dev *rc) { - struct cx88_core *core = priv; + struct cx88_core *core = rc->priv; core->ir->users++; return __cx88_ir_start(core); } -static void cx88_ir_close(void *priv) +static void cx88_ir_close(struct rc_dev *rc) { - struct cx88_core *core = priv; + struct cx88_core *core = rc->priv; core->ir->users--; if (!core->ir->users) @@ -236,20 +242,20 @@ static void cx88_ir_close(void *priv) int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) { struct cx88_IR *ir; - struct input_dev *input_dev; + struct rc_dev *dev; char *ir_codes = NULL; - u64 ir_type = IR_TYPE_OTHER; + u64 rc_type = RC_TYPE_OTHER; int err = -ENOMEM; u32 hardware_mask = 0; /* For devices with a hardware mask, when * used with a full-code IR table */ ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) + dev = rc_allocate_device(); + if (!ir || !dev) goto err_out_free; - ir->input = input_dev; + ir->dev = dev; /* detect & configure */ switch (core->boardnr) { @@ -264,7 +270,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: ir_codes = RC_MAP_CINERGY_1400; - ir_type = IR_TYPE_NEC; ir->sampling = 0xeb04; /* address */ break; case CX88_BOARD_HAUPPAUGE: @@ -279,7 +284,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PCHDTV_HD5500: case CX88_BOARD_HAUPPAUGE_IRONLY: ir_codes = RC_MAP_HAUPPAUGE_NEW; - ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: @@ -367,18 +371,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: ir_codes = RC_MAP_TBS_NEC; - ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: ir_codes = RC_MAP_TEVII_NEC; - ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; - ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: @@ -396,7 +397,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: ir_codes = RC_MAP_PINNACLE_PCTV_HD; - ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_POWERCOLOR_REAL_ANGEL: @@ -407,12 +407,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_TWINHAN_VP1027_DVBS: ir_codes = RC_MAP_TWINHAN_VP1027_DVBS; - ir_type = IR_TYPE_NEC; + rc_type = RC_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; } - if (NULL == ir_codes) { + if (!ir_codes) { err = -ENODEV; goto err_out_free; } @@ -436,37 +436,45 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); - ir->ir_type = ir_type; - - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + dev->input_name = ir->name; + dev->input_phys = ir->phys; + dev->input_id.bustype = BUS_PCI; + dev->input_id.version = 1; if (pci->subsystem_vendor) { - input_dev->id.vendor = pci->subsystem_vendor; - input_dev->id.product = pci->subsystem_device; + dev->input_id.vendor = pci->subsystem_vendor; + dev->input_id.product = pci->subsystem_device; } else { - input_dev->id.vendor = pci->vendor; - input_dev->id.product = pci->device; + dev->input_id.vendor = pci->vendor; + dev->input_id.product = pci->device; } - input_dev->dev.parent = &pci->dev; - /* record handles to ourself */ + dev->dev.parent = &pci->dev; + dev->map_name = ir_codes; + dev->driver_name = MODULE_NAME; + dev->priv = core; + dev->open = cx88_ir_open; + dev->close = cx88_ir_close; + dev->scanmask = hardware_mask; + + if (ir->sampling) { + dev->driver_type = RC_DRIVER_IR_RAW; + dev->timeout = 10 * 1000 * 1000; /* 10 ms */ + } else { + dev->driver_type = RC_DRIVER_SCANCODE; + dev->allowed_protos = rc_type; + } + ir->core = core; core->ir = ir; - ir->props.priv = core; - ir->props.open = cx88_ir_open; - ir->props.close = cx88_ir_close; - ir->props.scanmask = hardware_mask; - /* all done */ - err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); + err = rc_register_device(dev); if (err) goto err_out_free; return 0; - err_out_free: +err_out_free: + rc_free_device(dev); core->ir = NULL; kfree(ir); return err; @@ -481,7 +489,7 @@ int cx88_ir_fini(struct cx88_core *core) return 0; cx88_ir_stop(core); - ir_input_unregister(ir->input); + rc_unregister_device(ir->dev); kfree(ir); /* done */ @@ -494,135 +502,75 @@ int cx88_ir_fini(struct cx88_core *core) void cx88_ir_irq(struct cx88_core *core) { struct cx88_IR *ir = core->ir; - u32 samples, ircode; - int i, start, range, toggle, dev, code; + u32 samples; + unsigned todo, bits; + struct ir_raw_event ev; - if (NULL == ir) - return; - if (!ir->sampling) + if (!ir || !ir->sampling) return; + /* + * Samples are stored in a 32 bit register, oldest sample in + * the msb. A set bit represents space and an unset bit + * represents a pulse. + */ samples = cx_read(MO_SAMPLE_IO); - if (0 != samples && 0xffffffff != samples) { - /* record sample data */ - if (ir->scount < ARRAY_SIZE(ir->samples)) - ir->samples[ir->scount++] = samples; - return; - } - if (!ir->scount) { - /* nothing to sample */ - return; - } - - /* have a complete sample */ - if (ir->scount < ARRAY_SIZE(ir->samples)) - ir->samples[ir->scount++] = samples; - for (i = 0; i < ir->scount; i++) - ir->samples[i] = ~ir->samples[i]; - if (ir_debug) - ir_dump_samples(ir->samples, ir->scount); - /* decode it */ - switch (core->boardnr) { - case CX88_BOARD_TEVII_S460: - case CX88_BOARD_TEVII_S420: - case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - case CX88_BOARD_OMICOM_SS4_PCI: - case CX88_BOARD_SATTRADE_ST4200: - case CX88_BOARD_TBS_8920: - case CX88_BOARD_TBS_8910: - case CX88_BOARD_PROF_7300: - case CX88_BOARD_PROF_7301: - case CX88_BOARD_PROF_6200: - case CX88_BOARD_TWINHAN_VP1027_DVBS: - ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); - - if (ircode == 0xffffffff) { /* decoding error */ - ir_dprintk("pulse distance decoding error\n"); - break; - } - - ir_dprintk("pulse distance decoded: %x\n", ircode); + if (samples == 0xff && ir->dev->idle) + return; - if (ircode == 0) { /* key still pressed */ - ir_dprintk("pulse distance decoded repeat code\n"); - ir_repeat(ir->input); - break; - } + init_ir_raw_event(&ev); + for (todo = 32; todo > 0; todo -= bits) { + ev.pulse = samples & 0x80000000 ? false : true; + bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples)); + ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate); + ir_raw_event_store_with_filter(ir->dev, &ev); + samples <<= bits; + } + ir_raw_event_handle(ir->dev); +} - if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */ - ir_dprintk("pulse distance decoded wrong address\n"); - break; - } +static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + int flags, code; - if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */ - ir_dprintk("pulse distance decoded wrong check sum\n"); - break; - } + /* poll IR chip */ + flags = i2c_smbus_read_byte_data(ir->c, 0x10); + if (flags < 0) { + dprintk("read error\n"); + return 0; + } + /* key pressed ? */ + if (0 == (flags & 0x80)) + return 0; - ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0xff); - ir_keydown(ir->input, (ircode >> 16) & 0xff, 0); - break; - case CX88_BOARD_HAUPPAUGE: - case CX88_BOARD_HAUPPAUGE_DVB_T1: - case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: - case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - case CX88_BOARD_PCHDTV_HD3000: - case CX88_BOARD_PCHDTV_HD5500: - case CX88_BOARD_HAUPPAUGE_IRONLY: - ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); - ir_dprintk("biphase decoded: %x\n", ircode); - /* - * RC5 has an extension bit which adds a new range - * of available codes, this is detected here. Also - * hauppauge remotes (black/silver) always use - * specific device ids. If we do not filter the - * device ids then messages destined for devices - * such as TVs (id=0) will get through to the - * device causing mis-fired events. - */ - /* split rc5 data block ... */ - start = (ircode & 0x2000) >> 13; - range = (ircode & 0x1000) >> 12; - toggle= (ircode & 0x0800) >> 11; - dev = (ircode & 0x07c0) >> 6; - code = (ircode & 0x003f) | ((range << 6) ^ 0x0040); - if( start != 1) - /* no key pressed */ - break; - if ( dev != 0x1e && dev != 0x1f ) - /* not a hauppauge remote */ - break; - ir_keydown(ir->input, code, toggle); - break; - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); - ir_dprintk("biphase decoded: %x\n", ircode); - if ((ircode & 0xfffff000) != 0x3000) - break; - /* Note: bit 0x800 being the toggle is assumed, not checked - with real hardware */ - ir_keydown(ir->input, ircode & 0x3f, ircode & 0x0800 ? 1 : 0); - break; + /* read actual key code */ + code = i2c_smbus_read_byte_data(ir->c, 0x00); + if (code < 0) { + dprintk("read error\n"); + return 0; } - ir->scount = 0; - return; -} + dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", + code & 0xff, flags & 0xff); + *ir_key = code & 0xff; + *ir_raw = code; + return 1; +} void cx88_i2c_init_ir(struct cx88_core *core) { struct i2c_board_info info; - const unsigned short addr_list[] = { + const unsigned short default_addr_list[] = { 0x18, 0x6b, 0x71, I2C_CLIENT_END }; + const unsigned short pvr2000_addr_list[] = { + 0x18, 0x1a, + I2C_CLIENT_END + }; + const unsigned short *addr_list = default_addr_list; const unsigned short *addrp; /* Instantiate the IR receiver device, if present */ if (0 != core->i2c_rc) @@ -631,6 +579,16 @@ void cx88_i2c_init_ir(struct cx88_core *core) memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + switch (core->boardnr) { + case CX88_BOARD_LEADTEK_PVR2000: + addr_list = pvr2000_addr_list; + core->init_data.name = "cx88 Leadtek PVR 2000 remote"; + core->init_data.type = RC_TYPE_UNKNOWN; + core->init_data.get_key = get_key_pvr2000; + core->init_data.ir_codes = RC_MAP_EMPTY; + break; + } + /* * We can't call i2c_new_probed_device() because it uses * quick writes for probing and at least some RC receiver @@ -646,7 +604,7 @@ void cx88_i2c_init_ir(struct cx88_core *core) /* Hauppauge XVR */ core->init_data.name = "cx88 Hauppauge XVR remote"; core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; - core->init_data.type = IR_TYPE_RC5; + core->init_data.type = RC_TYPE_RC5; core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; info.platform_data = &core->init_data; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 88b51194f91..508dabbed98 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -40,7 +40,6 @@ #include "cx88.h" #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#include <media/wm8775.h> MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); @@ -977,7 +976,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) const struct cx88_ctrl *c = NULL; u32 value,mask; int i; - struct v4l2_control client_ctl; for (i = 0; i < CX8800_CTLS; i++) { if (cx8800_ctls[i].v.id == ctl->id) { @@ -991,27 +989,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) ctl->value = c->v.minimum; if (ctl->value > c->v.maximum) ctl->value = c->v.maximum; - - /* Pass changes onto any WM8775 */ - client_ctl.id = ctl->id; - switch (ctl->id) { - case V4L2_CID_AUDIO_MUTE: - client_ctl.value = ctl->value; - break; - case V4L2_CID_AUDIO_VOLUME: - client_ctl.value = (ctl->value) ? - (0x90 + ctl->value) << 8 : 0; - break; - case V4L2_CID_AUDIO_BALANCE: - client_ctl.value = ctl->value << 9; - break; - default: - client_ctl.id = 0; - break; - } - if (client_ctl.id) - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - mask=c->mask; switch (ctl->id) { case V4L2_CID_AUDIO_BALANCE: @@ -1179,15 +1156,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct cx8800_fh *fh = priv; - - return videobuf_cgmbuf (get_queue(fh), mbuf, 8); -} -#endif - static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) { struct cx8800_fh *fh = priv; @@ -1558,9 +1526,7 @@ static int radio_queryctrl (struct file *file, void *priv, if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) return -EINVAL; - if (c->id == V4L2_CID_AUDIO_MUTE || - c->id == V4L2_CID_AUDIO_VOLUME || - c->id == V4L2_CID_AUDIO_BALANCE) { + if (c->id == V4L2_CID_AUDIO_MUTE) { for (i = 0; i < CX8800_CTLS; i++) { if (cx8800_ctls[i].v.id == c->id) break; @@ -1731,9 +1697,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, @@ -1895,14 +1858,13 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (core->board.audio_chip == V4L2_IDENT_WM8775) v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - NULL, "wm8775", 0x36 >> 1, NULL); + "wm8775", 0x36 >> 1, NULL); if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ - v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, - NULL, "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, + "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); } switch (core->boardnr) { diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index ec5476d8b10..d77f8ecab9d 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -125,7 +125,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) strlcpy(vp3054_i2c->adap.name, core->name, sizeof(vp3054_i2c->adap.name)); vp3054_i2c->adap.owner = THIS_MODULE; - vp3054_i2c->adap.id = I2C_HW_B_CX2388x; vp3054_i2c->algo.data = dev; i2c_set_adapdata(&vp3054_i2c->adap, dev); vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e8c732e7ae4..c9981e77416 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -398,19 +398,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx88_core, v4l2_dev); } -#define call_hw(core, grpid, o, f, args...) \ +#define call_all(core, o, f, args...) \ do { \ if (!core->i2c_rc) { \ if (core->gate_ctrl) \ core->gate_ctrl(core, 1); \ - v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \ + v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \ if (core->gate_ctrl) \ core->gate_ctrl(core, 0); \ } \ } while (0) -#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) - struct cx8800_dev; struct cx8802_dev; diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c deleted file mode 100644 index f3e25e91366..00000000000 --- a/drivers/media/video/dabusb.c +++ /dev/null @@ -1,914 +0,0 @@ -/*****************************************************************************/ - -/* - * dabusb.c -- dab usb driver. - * - * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * - * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ - * - */ - -/*****************************************************************************/ - -#include <linux/module.h> -#include <linux/socket.h> -#include <linux/list.h> -#include <linux/vmalloc.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <asm/uaccess.h> -#include <asm/atomic.h> -#include <linux/delay.h> -#include <linux/usb.h> -#include <linux/mutex.h> -#include <linux/firmware.h> -#include <linux/ihex.h> - -#include "dabusb.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.54" -#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" -#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" - -/* --------------------------------------------------------------------- */ - -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define NRDABUSB 256 -#else -#define NRDABUSB 4 -#endif - -/*-------------------------------------------------------------------*/ - -static dabusb_t dabusb[NRDABUSB]; -static int buffers = 256; -static struct usb_driver dabusb_driver; - -/*-------------------------------------------------------------------*/ - -static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src) -{ - unsigned long flags; - struct list_head *tmp; - int ret = 0; - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (src)) { - // no elements in source buffer - ret = -1; - goto err; - } - tmp = src->next; - list_move_tail (tmp, dst); - - err: spin_unlock_irqrestore (&s->lock, flags); - return ret; -} -/*-------------------------------------------------------------------*/ -#ifdef DEBUG -static void dump_urb (struct urb *urb) -{ - dbg("urb :%p", urb); - dbg("dev :%p", urb->dev); - dbg("pipe :%08X", urb->pipe); - dbg("status :%d", urb->status); - dbg("transfer_flags :%08X", urb->transfer_flags); - dbg("transfer_buffer :%p", urb->transfer_buffer); - dbg("transfer_buffer_length:%d", urb->transfer_buffer_length); - dbg("actual_length :%d", urb->actual_length); - dbg("setup_packet :%p", urb->setup_packet); - dbg("start_frame :%d", urb->start_frame); - dbg("number_of_packets :%d", urb->number_of_packets); - dbg("interval :%d", urb->interval); - dbg("error_count :%d", urb->error_count); - dbg("context :%p", urb->context); - dbg("complete :%p", urb->complete); -} -#endif -/*-------------------------------------------------------------------*/ -static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) -{ - unsigned long flags; - pbuff_t b; - - dbg("dabusb_cancel_queue"); - - spin_lock_irqsave (&s->lock, flags); - - list_for_each_entry(b, q, buff_list) { -#ifdef DEBUG - dump_urb(b->purb); -#endif - usb_unlink_urb (b->purb); - } - spin_unlock_irqrestore (&s->lock, flags); - return 0; -} -/*-------------------------------------------------------------------*/ -static int dabusb_free_queue (struct list_head *q) -{ - struct list_head *tmp; - struct list_head *p; - pbuff_t b; - - dbg("dabusb_free_queue"); - for (p = q->next; p != q;) { - b = list_entry (p, buff_t, buff_list); - -#ifdef DEBUG - dump_urb(b->purb); -#endif - kfree(b->purb->transfer_buffer); - usb_free_urb(b->purb); - tmp = p->next; - list_del (p); - kfree (b); - p = tmp; - } - - return 0; -} -/*-------------------------------------------------------------------*/ -static int dabusb_free_buffers (pdabusb_t s) -{ - unsigned long flags; - dbg("dabusb_free_buffers"); - - spin_lock_irqsave(&s->lock, flags); - - dabusb_free_queue (&s->free_buff_list); - dabusb_free_queue (&s->rec_buff_list); - - spin_unlock_irqrestore(&s->lock, flags); - - s->got_mem = 0; - return 0; -} -/*-------------------------------------------------------------------*/ -static void dabusb_iso_complete (struct urb *purb) -{ - pbuff_t b = purb->context; - pdabusb_t s = b->s; - int i; - int len; - int dst = 0; - void *buf = purb->transfer_buffer; - - dbg("dabusb_iso_complete"); - - // process if URB was not killed - if (purb->status != -ENOENT) { - unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); - for (i = 0; i < purb->number_of_packets; i++) - if (!purb->iso_frame_desc[i].status) { - len = purb->iso_frame_desc[i].actual_length; - if (len <= pipesize) { - memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len); - dst += len; - } - else - dev_err(&purb->dev->dev, - "dabusb_iso_complete: invalid len %d\n", len); - } - else - dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status); - if (dst != purb->actual_length) - dev_err(&purb->dev->dev, - "dst!=purb->actual_length:%d!=%d\n", - dst, purb->actual_length); - } - - if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { - s->overruns++; - dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns); - } - wake_up (&s->wait); -} -/*-------------------------------------------------------------------*/ -static int dabusb_alloc_buffers (pdabusb_t s) -{ - int transfer_len = 0; - pbuff_t b; - unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); - int packets = _ISOPIPESIZE / pipesize; - int transfer_buffer_length = packets * pipesize; - int i; - - dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", - pipesize, packets, transfer_buffer_length); - - while (transfer_len < (s->total_buffer_size << 10)) { - b = kzalloc(sizeof (buff_t), GFP_KERNEL); - if (!b) { - dev_err(&s->usbdev->dev, - "kzalloc(sizeof(buff_t))==NULL\n"); - goto err; - } - b->s = s; - b->purb = usb_alloc_urb(packets, GFP_KERNEL); - if (!b->purb) { - dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n"); - kfree (b); - goto err; - } - - b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL); - if (!b->purb->transfer_buffer) { - kfree (b->purb); - kfree (b); - dev_err(&s->usbdev->dev, - "kmalloc(%d)==NULL\n", transfer_buffer_length); - goto err; - } - - b->purb->transfer_buffer_length = transfer_buffer_length; - b->purb->number_of_packets = packets; - b->purb->complete = dabusb_iso_complete; - b->purb->context = b; - b->purb->dev = s->usbdev; - b->purb->pipe = pipe; - b->purb->transfer_flags = URB_ISO_ASAP; - - for (i = 0; i < packets; i++) { - b->purb->iso_frame_desc[i].offset = i * pipesize; - b->purb->iso_frame_desc[i].length = pipesize; - } - - transfer_len += transfer_buffer_length; - list_add_tail (&b->buff_list, &s->free_buff_list); - } - s->got_mem = transfer_len; - - return 0; - - err: - dabusb_free_buffers (s); - return -ENOMEM; -} -/*-------------------------------------------------------------------*/ -static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) -{ - int ret; - unsigned int pipe; - int actual_length; - - dbg("dabusb_bulk"); - - if (!pb->pipe) - pipe = usb_rcvbulkpipe (s->usbdev, 2); - else - pipe = usb_sndbulkpipe (s->usbdev, 2); - - ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); - if(ret<0) { - dev_err(&s->usbdev->dev, - "usb_bulk_msg failed(%d)\n", ret); - - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - dev_err(&s->usbdev->dev, "set_interface failed\n"); - return -EINVAL; - } - - } - - if( ret == -EPIPE ) { - dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n"); - if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) - dev_err(&s->usbdev->dev, "request failed\n"); - } - - pb->size = actual_length; - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data, - int len) -{ - int ret; - unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); - - if (!transfer_buffer) { - dev_err(&s->usbdev->dev, - "dabusb_writemem: kmalloc(%d) failed.\n", len); - return -ENOMEM; - } - - memcpy (transfer_buffer, data, len); - - ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300); - - kfree (transfer_buffer); - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) -{ - dbg("dabusb_8051_reset: %d",reset_bit); - return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1); -} -/* --------------------------------------------------------------------- */ -static int dabusb_loadmem (pdabusb_t s, const char *fname) -{ - int ret; - const struct ihex_binrec *rec; - const struct firmware *uninitialized_var(fw); - - dbg("Enter dabusb_loadmem (internal)"); - - ret = request_ihex_firmware(&fw, "dabusb/firmware.fw", &s->usbdev->dev); - if (ret) { - dev_err(&s->usbdev->dev, - "Failed to load \"dabusb/firmware.fw\": %d\n", ret); - goto out; - } - ret = dabusb_8051_reset (s, 1); - - for (rec = (const struct ihex_binrec *)fw->data; rec; - rec = ihex_next_binrec(rec)) { - dbg("dabusb_writemem: %04X %p %d)", be32_to_cpu(rec->addr), - rec->data, be16_to_cpu(rec->len)); - - ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data, - be16_to_cpu(rec->len)); - if (ret < 0) { - dev_err(&s->usbdev->dev, - "dabusb_writemem failed (%d %04X %p %d)\n", - ret, be32_to_cpu(rec->addr), - rec->data, be16_to_cpu(rec->len)); - break; - } - } - ret = dabusb_8051_reset (s, 0); - release_firmware(fw); - out: - dbg("dabusb_loadmem: exit"); - - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b) -{ - b->size = 4; - b->data[0] = 0x2a; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 0; - - dbg("dabusb_fpga_clear"); - - return dabusb_bulk (s, b); -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) -{ - b->size = 4; - b->data[0] = 0x2c; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 0; - - dbg("dabusb_fpga_init"); - - return dabusb_bulk (s, b); -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_download (pdabusb_t s, const char *fname) -{ - pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); - const struct firmware *fw; - unsigned int blen, n; - int ret; - - dbg("Enter dabusb_fpga_download (internal)"); - - if (!b) { - dev_err(&s->usbdev->dev, - "kmalloc(sizeof(bulk_transfer_t))==NULL\n"); - return -ENOMEM; - } - - ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev); - if (ret) { - dev_err(&s->usbdev->dev, - "Failed to load \"dabusb/bitstream.bin\": %d\n", ret); - kfree(b); - return ret; - } - - b->pipe = 1; - ret = dabusb_fpga_clear (s, b); - mdelay (10); - blen = fw->data[73] + (fw->data[72] << 8); - - dbg("Bitstream len: %i", blen); - - b->data[0] = 0x2b; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 60; - - for (n = 0; n <= blen + 60; n += 60) { - // some cclks for startup - b->size = 64; - memcpy (b->data + 4, fw->data + 74 + n, 60); - ret = dabusb_bulk (s, b); - if (ret < 0) { - dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n"); - break; - } - mdelay (1); - } - - ret = dabusb_fpga_init (s, b); - kfree (b); - release_firmware(fw); - - dbg("exit dabusb_fpga_download"); - - return ret; -} - -static int dabusb_stop (pdabusb_t s) -{ - dbg("dabusb_stop"); - - s->state = _stopped; - dabusb_cancel_queue (s, &s->rec_buff_list); - - dbg("pending_io: %d", s->pending_io.counter); - - s->pending_io.counter = 0; - return 0; -} - -static int dabusb_startrek (pdabusb_t s) -{ - if (!s->got_mem && s->state != _started) { - - dbg("dabusb_startrek"); - - if (dabusb_alloc_buffers (s) < 0) - return -ENOMEM; - dabusb_stop (s); - s->state = _started; - s->readptr = 0; - } - - if (!list_empty (&s->free_buff_list)) { - pbuff_t end; - int ret; - - while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { - - dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); - - end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); - - ret = usb_submit_urb (end->purb, GFP_KERNEL); - if (ret) { - dev_err(&s->usbdev->dev, - "usb_submit_urb returned:%d\n", ret); - if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - dev_err(&s->usbdev->dev, - "startrek: dabusb_add_buf_tail failed\n"); - break; - } - else - atomic_inc (&s->pending_io); - } - dbg("pending_io: %d",s->pending_io.counter); - } - - return 0; -} - -static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - unsigned long flags; - unsigned ret = 0; - int rem; - int cnt; - pbuff_t b; - struct urb *purb = NULL; - - dbg("dabusb_read"); - - if (*ppos) - return -ESPIPE; - - if (s->remove_pending) - return -EIO; - - - if (!s->usbdev) - return -EIO; - - while (count > 0) { - dabusb_startrek (s); - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (&s->rec_buff_list)) { - - spin_unlock_irqrestore(&s->lock, flags); - - dev_err(&s->usbdev->dev, - "error: rec_buf_list is empty\n"); - goto err; - } - - b = list_entry (s->rec_buff_list.next, buff_t, buff_list); - purb = b->purb; - - spin_unlock_irqrestore(&s->lock, flags); - - if (purb->status == -EINPROGRESS) { - if (file->f_flags & O_NONBLOCK) // return nonblocking - { - if (!ret) - ret = -EAGAIN; - goto err; - } - - interruptible_sleep_on (&s->wait); - - if (signal_pending (current)) { - if (!ret) - ret = -ERESTARTSYS; - goto err; - } - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (&s->rec_buff_list)) { - spin_unlock_irqrestore(&s->lock, flags); - dev_err(&s->usbdev->dev, - "error: still no buffer available.\n"); - goto err; - } - spin_unlock_irqrestore(&s->lock, flags); - s->readptr = 0; - } - if (s->remove_pending) { - ret = -EIO; - goto err; - } - - rem = purb->actual_length - s->readptr; // set remaining bytes to copy - - if (count >= rem) - cnt = rem; - else - cnt = count; - - dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); - - if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { - dev_err(&s->usbdev->dev, "read: copy_to_user failed\n"); - if (!ret) - ret = -EFAULT; - goto err; - } - - s->readptr += cnt; - count -= cnt; - buf += cnt; - ret += cnt; - - if (s->readptr == purb->actual_length) { - // finished, take next buffer - if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - dev_err(&s->usbdev->dev, - "read: dabusb_add_buf_tail failed\n"); - s->readptr = 0; - } - } - err: //mutex_unlock(&s->mutex); - return ret; -} - -static int dabusb_open (struct inode *inode, struct file *file) -{ - int devnum = iminor(inode); - pdabusb_t s; - int r; - - if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) - return -EIO; - - s = &dabusb[devnum - DABUSB_MINOR]; - - dbg("dabusb_open"); - mutex_lock(&s->mutex); - - while (!s->usbdev || s->opened) { - mutex_unlock(&s->mutex); - - if (file->f_flags & O_NONBLOCK) - return -EBUSY; - msleep_interruptible(500); - - if (signal_pending (current)) - return -EAGAIN; - mutex_lock(&s->mutex); - } - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - mutex_unlock(&s->mutex); - dev_err(&s->usbdev->dev, "set_interface failed\n"); - return -EINVAL; - } - s->opened = 1; - mutex_unlock(&s->mutex); - - file->f_pos = 0; - file->private_data = s; - - r = nonseekable_open(inode, file); - return r; -} - -static int dabusb_release (struct inode *inode, struct file *file) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - - dbg("dabusb_release"); - - mutex_lock(&s->mutex); - dabusb_stop (s); - dabusb_free_buffers (s); - mutex_unlock(&s->mutex); - - if (!s->remove_pending) { - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) - dev_err(&s->usbdev->dev, "set_interface failed\n"); - } - else - wake_up (&s->remove_ok); - - s->opened = 0; - return 0; -} - -static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - pbulk_transfer_t pbulk; - int ret = 0; - int version = DABUSB_VERSION; - - dbg("dabusb_ioctl"); - - if (s->remove_pending) - return -EIO; - - mutex_lock(&s->mutex); - - if (!s->usbdev) { - mutex_unlock(&s->mutex); - return -EIO; - } - - switch (cmd) { - - case IOCTL_DAB_BULK: - pbulk = memdup_user((void __user *)arg, - sizeof(bulk_transfer_t)); - - if (IS_ERR(pbulk)) { - ret = PTR_ERR(pbulk); - break; - } - - ret=dabusb_bulk (s, pbulk); - if(ret==0) - if (copy_to_user((void __user *)arg, pbulk, - sizeof(bulk_transfer_t))) - ret = -EFAULT; - kfree (pbulk); - break; - - case IOCTL_DAB_OVERRUNS: - ret = put_user (s->overruns, (unsigned int __user *) arg); - break; - - case IOCTL_DAB_VERSION: - ret = put_user (version, (unsigned int __user *) arg); - break; - - default: - ret = -ENOIOCTLCMD; - break; - } - mutex_unlock(&s->mutex); - return ret; -} - -static const struct file_operations dabusb_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = dabusb_read, - .unlocked_ioctl = dabusb_ioctl, - .open = dabusb_open, - .release = dabusb_release, -}; - -static char *dabusb_devnode(struct device *dev, mode_t *mode) -{ - return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); -} - -static struct usb_class_driver dabusb_class = { - .name = "dabusb%d", - .devnode = dabusb_devnode, - .fops = &dabusb_fops, - .minor_base = DABUSB_MINOR, -}; - - -/* --------------------------------------------------------------------- */ -static int dabusb_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - int retval; - pdabusb_t s; - - dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct), - intf->altsetting->desc.bInterfaceNumber); - - /* We don't handle multiple configurations */ - if (usbdev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && - le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999) - return -ENODEV; - - - - s = &dabusb[intf->minor]; - - mutex_lock(&s->mutex); - s->remove_pending = 0; - s->usbdev = usbdev; - s->devnum = intf->minor; - - if (usb_reset_configuration (usbdev) < 0) { - dev_err(&intf->dev, "reset_configuration failed\n"); - goto reject; - } - if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { - dabusb_loadmem (s, NULL); - goto reject; - } - else { - dabusb_fpga_download (s, NULL); - - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { - dev_err(&intf->dev, "set_interface failed\n"); - goto reject; - } - } - dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); - usb_set_intfdata (intf, s); - mutex_unlock(&s->mutex); - - retval = usb_register_dev(intf, &dabusb_class); - if (retval) { - usb_set_intfdata (intf, NULL); - return -ENOMEM; - } - - return 0; - - reject: - mutex_unlock(&s->mutex); - s->usbdev = NULL; - return -ENODEV; -} - -static void dabusb_disconnect (struct usb_interface *intf) -{ - wait_queue_t __wait; - pdabusb_t s = usb_get_intfdata (intf); - - dbg("dabusb_disconnect"); - - init_waitqueue_entry(&__wait, current); - - usb_set_intfdata (intf, NULL); - if (s) { - usb_deregister_dev (intf, &dabusb_class); - s->remove_pending = 1; - wake_up (&s->wait); - add_wait_queue(&s->remove_ok, &__wait); - set_current_state(TASK_UNINTERRUPTIBLE); - if (s->state == _started) - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&s->remove_ok, &__wait); - - s->usbdev = NULL; - s->overruns = 0; - } -} - -static struct usb_device_id dabusb_ids [] = { - // { USB_DEVICE(0x0547, 0x2131) }, /* An2131 chip, no boot ROM */ - { USB_DEVICE(0x0547, 0x9999) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, dabusb_ids); - -static struct usb_driver dabusb_driver = { - .name = "dabusb", - .probe = dabusb_probe, - .disconnect = dabusb_disconnect, - .id_table = dabusb_ids, -}; - -/* --------------------------------------------------------------------- */ - -static int __init dabusb_init (void) -{ - int retval; - unsigned u; - - /* initialize struct */ - for (u = 0; u < NRDABUSB; u++) { - pdabusb_t s = &dabusb[u]; - memset (s, 0, sizeof (dabusb_t)); - mutex_init (&s->mutex); - s->usbdev = NULL; - s->total_buffer_size = buffers; - init_waitqueue_head (&s->wait); - init_waitqueue_head (&s->remove_ok); - spin_lock_init (&s->lock); - INIT_LIST_HEAD (&s->free_buff_list); - INIT_LIST_HEAD (&s->rec_buff_list); - } - - /* register misc device */ - retval = usb_register(&dabusb_driver); - if (retval) - goto out; - - dbg("dabusb_init: driver registered"); - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - -out: - return retval; -} - -static void __exit dabusb_cleanup (void) -{ - dbg("dabusb_cleanup"); - - usb_deregister (&dabusb_driver); -} - -/* --------------------------------------------------------------------- */ - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("dabusb/firmware.fw"); -MODULE_FIRMWARE("dabusb/bitstream.bin"); - -module_param(buffers, int, 0); -MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); - -module_init (dabusb_init); -module_exit (dabusb_cleanup); - -/* --------------------------------------------------------------------- */ diff --git a/drivers/media/video/dabusb.h b/drivers/media/video/dabusb.h deleted file mode 100644 index 00eb34c863e..00000000000 --- a/drivers/media/video/dabusb.h +++ /dev/null @@ -1,85 +0,0 @@ -#define _BULK_DATA_LEN 64 -typedef struct -{ - unsigned char data[_BULK_DATA_LEN]; - unsigned int size; - unsigned int pipe; -}bulk_transfer_t,*pbulk_transfer_t; - -#define DABUSB_MINOR 240 /* some unassigned USB minor */ -#define DABUSB_VERSION 0x1000 -#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) -#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) -#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) - -#ifdef __KERNEL__ - -typedef enum { _stopped=0, _started } driver_state_t; - -typedef struct -{ - struct mutex mutex; - struct usb_device *usbdev; - wait_queue_head_t wait; - wait_queue_head_t remove_ok; - spinlock_t lock; - atomic_t pending_io; - driver_state_t state; - int remove_pending; - int got_mem; - int total_buffer_size; - unsigned int overruns; - int readptr; - int opened; - int devnum; - struct list_head free_buff_list; - struct list_head rec_buff_list; -} dabusb_t,*pdabusb_t; - -typedef struct -{ - pdabusb_t s; - struct urb *purb; - struct list_head buff_list; -} buff_t,*pbuff_t; - -typedef struct -{ - wait_queue_head_t wait; -} bulk_completion_context_t, *pbulk_completion_context_t; - - -#define _DABUSB_IF 2 -#define _DABUSB_ISOPIPE 0x09 -#define _ISOPIPESIZE 16384 - -#define _BULK_DATA_LEN 64 -// Vendor specific request code for Anchor Upload/Download -// This one is implemented in the core -#define ANCHOR_LOAD_INTERNAL 0xA0 - -// EZ-USB Control and Status Register. Bit 0 controls 8051 reset -#define CPUCS_REG 0x7F92 -#define _TOTAL_BUFFERS 384 - -#define MAX_INTEL_HEX_RECORD_LENGTH 16 - -#ifndef _BYTE_DEFINED -#define _BYTE_DEFINED -typedef unsigned char BYTE; -#endif // !_BYTE_DEFINED - -#ifndef _WORD_DEFINED -#define _WORD_DEFINED -typedef unsigned short WORD; -#endif // !_WORD_DEFINED - -typedef struct _INTEL_HEX_RECORD -{ - BYTE Length; - WORD Address; - BYTE Type; - BYTE Data[MAX_INTEL_HEX_RECORD_LENGTH]; -} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD; - -#endif diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index d8e38cc4ec4..353eadaa823 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1276,7 +1276,7 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq, vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; vb->field = field; - ret = videobuf_iolock(vq, vb, NULL);; + ret = videobuf_iolock(vq, vb, NULL); if (ret < 0) return ret; @@ -1986,7 +1986,6 @@ static __init int vpfe_probe(struct platform_device *pdev) vpfe_dev->sd[i] = v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, i2c_adap, - NULL, &sdinfo->board_info, NULL); if (vpfe_dev->sd[i]) { diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 6ac6acd1635..193abab6b35 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -2013,7 +2013,6 @@ static __init int vpif_probe(struct platform_device *pdev) vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, i2c_adap, - NULL, &subdevdata->board_info, NULL); diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 685f6a6ee60..412c65d54fe 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -1553,7 +1553,7 @@ static __init int vpif_probe(struct platform_device *pdev) for (i = 0; i < subdev_count; i++) { vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, - i2c_adap, NULL, + i2c_adap, &subdevdata[i].board_info, NULL); if (!vpif_obj.sd[i]) { diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 66aefd6eef5..985100ea17a 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,9 +1,9 @@ config VIDEO_EM28XX tristate "Empia EM28xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT + depends on VIDEO_DEV && I2C select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on RC_CORE select VIDEOBUF_VMALLOC select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO @@ -37,6 +37,7 @@ config VIDEO_EM28XX_DVB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE + select DVB_S921 if !DVB_FE_CUSTOMISE select VIDEOBUF_DVB ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index d60538bb22b..099d5df8c57 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -268,6 +268,20 @@ static struct em28xx_reg_seq dikom_dk300_digital[] = { }; +/* Reset for the most [digital] boards */ +static struct em28xx_reg_seq leadership_digital[] = { + {EM2874_R80_GPIO, 0x70, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq leadership_reset[] = { + {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO, 0xb0, 0xff, 10}, + {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + { -1, -1, -1, -1}, +}; + + /* * Board definitions */ @@ -1224,6 +1238,19 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE0, } }, }, + + [EM2874_LEADERSHIP_ISDBT] = { + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ, + .xclk = EM28XX_XCLK_FREQUENCY_10MHZ, + .name = "EM2874 Leadership ISDBT", + .tuner_type = TUNER_ABSENT, + .tuner_gpio = leadership_reset, + .dvb_gpio = leadership_digital, + .has_dvb = 1, + }, + [EM2880_BOARD_MSI_DIGIVOX_AD] = { .name = "MSI DigiVox A/D", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1469,7 +1496,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2882_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS (em2882)", + .name = "Terratec Cinnergy Hybrid T USB XS (em2882)", .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, @@ -1633,11 +1660,11 @@ struct em28xx_board em28xx_boards[] = { .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, } }, }, [EM2860_BOARD_TERRATEC_AV350] = { @@ -1754,6 +1781,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2868), .driver_info = EM2820_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2875), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0xe300), .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, { USB_DEVICE(0xeb1a, 0xe303), @@ -1791,7 +1820,7 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0x0ccd, 0x005e), .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0042), - .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, + .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0043), .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), @@ -1873,6 +1902,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, + {0x6b800080, EM2874_LEADERSHIP_ISDBT, TUNER_ABSENT}, }; /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ @@ -2408,7 +2438,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;; + dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; break; @@ -2430,8 +2460,36 @@ void em28xx_card_setup(struct em28xx *dev) dev->board.is_webcam = 0; else dev->progressive = 1; - } else - em28xx_set_model(dev); + } + + if (!dev->board.is_webcam) { + switch (dev->model) { + case EM2820_BOARD_UNKNOWN: + case EM2800_BOARD_UNKNOWN: + /* + * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. + * + * This occurs because they share identical USB vendor and + * product IDs. + * + * What we do here is look up the EEPROM hash of the K-WORLD + * and if it is found then we decide that we do not have + * a DIGIVOX and reset the device to the K-WORLD instead. + * + * This solution is only valid if they do not share eeprom + * hash identities which has not been determined as yet. + */ + if (em28xx_hint_board(dev) < 0) + em28xx_errdev("Board not discovered\n"); + else { + em28xx_set_model(dev); + em28xx_pre_card_setup(dev); + } + break; + default: + em28xx_set_model(dev); + } + } em28xx_info("Identified as %s (card=%d)\n", dev->board.name, dev->model); @@ -2554,39 +2612,39 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->board.has_msp34xx) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "msp3400", 0, msp3400_addrs); + "msp3400", 0, msp3400_addrs); if (dev->board.decoder == EM28XX_SAA711X) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "saa7115_auto", 0, saa711x_addrs); + "saa7115_auto", 0, saa711x_addrs); if (dev->board.decoder == EM28XX_TVP5150) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tvp5150", 0, tvp5150_addrs); + "tvp5150", 0, tvp5150_addrs); if (dev->em28xx_sensor == EM28XX_MT9V011) { struct v4l2_subdev *sd; sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "mt9v011", 0, mt9v011_addrs); + &dev->i2c_adap, "mt9v011", 0, mt9v011_addrs); v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); } if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tvaudio", dev->board.tvaudio_addr, NULL); + "tvaudio", dev->board.tvaudio_addr, NULL); if (dev->board.tuner_type != TUNER_ABSENT) { int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); if (dev->board.radio.type) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tuner", dev->board.radio_addr, NULL); + "tuner", dev->board.radio_addr, NULL); if (has_demod) v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "tuner", + &dev->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == 0) { enum v4l2_i2c_tuner_type type = @@ -2594,14 +2652,14 @@ void em28xx_card_setup(struct em28xx *dev) struct v4l2_subdev *sd; sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "tuner", + &dev->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(type)); if (sd) dev->tuner_addr = v4l2_i2c_subdev_addr(sd); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tuner", dev->tuner_addr, NULL); + "tuner", dev->tuner_addr, NULL); } } @@ -2755,8 +2813,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { - /* Sets I2C speed to 100 KHz */ - retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); + /* Resets I2C speed */ + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); if (retval < 0) { em28xx_errdev("%s: em28xx_write_regs_req failed!" " retval [%d]\n", diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 3ac8d3025fe..c7c04bf712a 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -37,6 +37,7 @@ #include "mt352_priv.h" /* FIXME */ #include "tda1002x.h" #include "tda18271.h" +#include "s921.h" MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); @@ -245,6 +246,10 @@ static struct lgdt3305_config em2870_lgdt3304_dev = { .qam_if_khz = 4000, }; +static struct s921_config sharp_isdbt = { + .demod_address = 0x30 >> 1 +}; + static struct zl10353_config em28xx_zl10353_with_xc3028 = { .demod_address = (0x1e >> 1), .no_tuner = 1, @@ -481,6 +486,7 @@ static int dvb_init(struct em28xx *dev) if (!dev->board.has_dvb) { /* This device does not support the extension */ + printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); return 0; } @@ -496,6 +502,16 @@ static int dvb_init(struct em28xx *dev) em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { + case EM2874_LEADERSHIP_ISDBT: + dvb->frontend = dvb_attach(s921_attach, + &sharp_isdbt, &dev->i2c_adap); + + if (!dvb->frontend) { + result = -EINVAL; + goto out_free; + } + + break; case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 99403c720e3..ba1ba8648c8 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -25,7 +25,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> -#include <linux/input.h> #include <linux/usb.h> #include <linux/slab.h> @@ -64,7 +63,7 @@ struct em28xx_ir_poll_result { struct em28xx_IR { struct em28xx *dev; - struct input_dev *input; + struct rc_dev *rc; char name[32]; char phys[32]; @@ -75,10 +74,6 @@ struct em28xx_IR { unsigned int last_readcount; int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); - - /* IR device properties */ - - struct ir_dev_props props; }; /********************************************************** @@ -302,12 +297,12 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) poll_result.toggle_bit, poll_result.read_count, poll_result.rc_address, poll_result.rc_data[0]); if (ir->full_code) - ir_keydown(ir->input, + rc_keydown(ir->rc, poll_result.rc_address << 8 | poll_result.rc_data[0], poll_result.toggle_bit); else - ir_keydown(ir->input, + rc_keydown(ir->rc, poll_result.rc_data[0], poll_result.toggle_bit); @@ -331,9 +326,9 @@ static void em28xx_ir_work(struct work_struct *work) schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } -static int em28xx_ir_start(void *priv) +static int em28xx_ir_start(struct rc_dev *rc) { - struct em28xx_IR *ir = priv; + struct em28xx_IR *ir = rc->priv; INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); schedule_delayed_work(&ir->work, 0); @@ -341,30 +336,30 @@ static int em28xx_ir_start(void *priv) return 0; } -static void em28xx_ir_stop(void *priv) +static void em28xx_ir_stop(struct rc_dev *rc) { - struct em28xx_IR *ir = priv; + struct em28xx_IR *ir = rc->priv; cancel_delayed_work_sync(&ir->work); } -int em28xx_ir_change_protocol(void *priv, u64 ir_type) +int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) { int rc = 0; - struct em28xx_IR *ir = priv; + struct em28xx_IR *ir = rc_dev->priv; struct em28xx *dev = ir->dev; u8 ir_config = EM2874_IR_RC5; /* Adjust xclk based o IR table for RC5/NEC tables */ - if (ir_type == IR_TYPE_RC5) { + if (rc_type == RC_TYPE_RC5) { dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; ir->full_code = 1; - } else if (ir_type == IR_TYPE_NEC) { + } else if (rc_type == RC_TYPE_NEC) { dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; ir_config = EM2874_IR_NEC; ir->full_code = 1; - } else if (ir_type != IR_TYPE_UNKNOWN) + } else if (rc_type != RC_TYPE_UNKNOWN) rc = -EINVAL; em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, @@ -391,7 +386,7 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) int em28xx_ir_init(struct em28xx *dev) { struct em28xx_IR *ir; - struct input_dev *input_dev; + struct rc_dev *rc; int err = -ENOMEM; if (dev->board.ir_codes == NULL) { @@ -400,28 +395,27 @@ int em28xx_ir_init(struct em28xx *dev) } ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) + rc = rc_allocate_device(); + if (!ir || !rc) goto err_out_free; /* record handles to ourself */ ir->dev = dev; dev->ir = ir; - - ir->input = input_dev; + ir->rc = rc; /* * em2874 supports more protocols. For now, let's just announce * the two protocols that were already tested */ - ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.priv = ir; - ir->props.change_protocol = em28xx_ir_change_protocol; - ir->props.open = em28xx_ir_start; - ir->props.close = em28xx_ir_stop; + rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; + rc->priv = ir; + rc->change_protocol = em28xx_ir_change_protocol; + rc->open = em28xx_ir_start; + rc->close = em28xx_ir_stop; /* By default, keep protocol field untouched */ - err = em28xx_ir_change_protocol(ir, IR_TYPE_UNKNOWN); + err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN); if (err) goto err_out_free; @@ -435,27 +429,27 @@ int em28xx_ir_init(struct em28xx *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_USB; - input_dev->id.version = 1; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - - input_dev->dev.parent = &dev->udev->dev; - - + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_USB; + rc->input_id.version = 1; + rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + rc->dev.parent = &dev->udev->dev; + rc->map_name = dev->board.ir_codes; + rc->driver_name = MODULE_NAME; /* all done */ - err = ir_input_register(ir->input, dev->board.ir_codes, - &ir->props, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_stop; return 0; + err_out_stop: dev->ir = NULL; err_out_free: + rc_free_device(rc); kfree(ir); return err; } @@ -468,8 +462,8 @@ int em28xx_ir_fini(struct em28xx *dev) if (!ir) return 0; - em28xx_ir_stop(ir); - ir_input_unregister(ir->input); + em28xx_ir_stop(ir->rc); + rc_unregister_device(ir->rc); kfree(ir); /* done */ diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c index 7f1c4a2173b..2b4c9cba2d6 100644 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ b/drivers/media/video/em28xx/em28xx-vbi.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/hardirq.h> #include <linux/init.h> #include "em28xx.h" diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 908e3bc8830..f34d524ccb0 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1434,7 +1434,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ if (rc == 1) { - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); + rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); /* * In the case of non-AC97 volume controls, we still need @@ -1708,11 +1708,15 @@ static int vidioc_streamoff(struct file *file, void *priv, fh, type, fh->resources, dev->resources); if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, EM28XX_RESOURCE_VIDEO); + if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->vb_vidq); + res_free(fh, EM28XX_RESOURCE_VIDEO); + } } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, EM28XX_RESOURCE_VBI); + if (res_check(fh, EM28XX_RESOURCE_VBI)) { + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh, EM28XX_RESOURCE_VBI); + } } return 0; @@ -1934,19 +1938,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct em28xx_fh *fh = priv; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); - else - return videobuf_cgmbuf(&fh->vb_vbiq, mbuf, 8); -} -#endif - - /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ @@ -2359,9 +2350,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_register = vidioc_s_register, .vidioc_g_chip_ident = vidioc_g_chip_ident, #endif -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static const struct video_device em28xx_video_template = { @@ -2377,7 +2365,7 @@ static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = em28xx_v4l2_open, .release = em28xx_v4l2_close, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6a75e6a4fc2..6f2795a3d4b 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -33,7 +33,7 @@ #include <media/videobuf-vmalloc.h> #include <media/v4l2-device.h> #include <media/ir-kbd-i2c.h> -#include <media/ir-core.h> +#include <media/rc-core.h> #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) #include <media/videobuf-dvb.h> #endif @@ -117,6 +117,8 @@ #define EM2800_BOARD_VC211A 74 #define EM2882_BOARD_DIKOM_DK300 75 #define EM2870_BOARD_KWORLD_A340 76 +#define EM2874_LEADERSHIP_ISDBT 77 + /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index a5cfc76b40b..a982750dcef 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -1610,6 +1610,7 @@ et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); i.type = V4L2_INPUT_TYPE_CAMERA; + i.capabilities = V4L2_IN_CAP_STD; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; @@ -2530,7 +2531,7 @@ static const struct v4l2_file_operations et61x251_fops = { .owner = THIS_MODULE, .open = et61x251_open, .release = et61x251_release, - .ioctl = et61x251_ioctl, + .unlocked_ioctl = et61x251_ioctl, .read = et61x251_read, .poll = et61x251_poll, .mmap = et61x251_mmap, diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 9a075d83dd1..e4bba88254c 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c @@ -194,6 +194,8 @@ struct viu_dev { /* decoder */ struct v4l2_subdev *decoder; + + v4l2_std_id std; }; struct viu_fh { @@ -915,6 +917,8 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (fh->type != i) return -EINVAL; + viu_start_dma(fh->dev); + return videobuf_streamon(&fh->vb_vidq); } @@ -927,20 +931,39 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) if (fh->type != i) return -EINVAL; + viu_stop_dma(fh->dev); + return videobuf_streamoff(&fh->vb_vidq); } #define decoder_call(viu, o, f, args...) \ v4l2_subdev_call(viu->decoder, o, f, ##args) +static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct viu_fh *fh = priv; + + decoder_call(fh->dev, video, querystd, std_id); + return 0; +} + static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) { struct viu_fh *fh = priv; + fh->dev->std = *id; decoder_call(fh->dev, core, s_std, *id); return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct viu_fh *fh = priv; + + *std_id = fh->dev->std; + return 0; +} + /* only one input in this driver */ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) @@ -1331,6 +1354,7 @@ static int viu_release(struct file *file) viu_stop_dma(dev); videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); kfree(fh); @@ -1397,7 +1421,9 @@ static const struct v4l2_ioctl_ops viu_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1486,7 +1512,7 @@ static int __devinit viu_of_probe(struct platform_device *op, ad = i2c_get_adapter(0); viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad, - NULL, "saa7113", VIU_VIDEO_DECODER_ADDR, NULL); + "saa7113", VIU_VIDEO_DECODER_ADDR, NULL); viu_dev->vidq.timeout.function = viu_vid_timeout; viu_dev->vidq.timeout.data = (unsigned long)viu_dev; diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 9b121681d13..c1ae05f4661 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); /* constant value's */ #define MAGIC_0 0x19 #define MAGIC_1 0x68 -#define DATA_IN 0xC0 +#define DATA_IN 0xc0 #define DATA_OUT 0x40 #define VIDEOSIZE_QCIF 0 /* 176x144 */ #define VIDEOSIZE_CIF 1 /* 352x288 */ @@ -660,9 +660,9 @@ static int do_command(struct gspca_dev *gspca_dev, u16 command, if (sd->params.qx3.button) { /* button pressed - unlock the latch */ do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xDF, 0xDF, 0); + 3, 0xdf, 0xdf, 0); do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xFF, 0xFF, 0); + 3, 0xff, 0xff, 0); } /* test whether microscope is cradled */ @@ -829,7 +829,7 @@ static int goto_low_power(struct gspca_dev *gspca_dev) if (ret) return ret; - do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); + ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); if (ret) return ret; @@ -1110,12 +1110,12 @@ static int command_setlights(struct gspca_dev *gspca_dev) p2 = (sd->params.qx3.toplight == 0) << 3; ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, - 0x90, 0x8F, 0x50, 0); + 0x90, 0x8f, 0x50, 0); if (ret) return ret; return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, - p1 | p2 | 0xE0, 0); + p1 | p2 | 0xe0, 0); } static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 8fe8fb486d6..442970073e8 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 10, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 11, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; @@ -224,12 +224,12 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, buffer, buffer_len, int_irq, (void *)gspca_dev, interval); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - gspca_dev->int_urb = urb; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { PDEBUG(D_ERR, "submit int URB failed with error %i", ret); goto error_submit; } + gspca_dev->int_urb = urb; return ret; error_submit: @@ -318,14 +318,9 @@ static void fill_frame(struct gspca_dev *gspca_dev, } pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { + len = urb->iso_frame_desc[i].actual_length; /* check the packet status and length */ - len = urb->iso_frame_desc[i].actual_length; - if (len == 0) { - if (gspca_dev->empty_packet == 0) - gspca_dev->empty_packet = 1; - continue; - } st = urb->iso_frame_desc[i].status; if (st) { err("ISOC data error: [%d] len=%d, status=%d", @@ -333,6 +328,11 @@ static void fill_frame(struct gspca_dev *gspca_dev, gspca_dev->last_packet_type = DISCARD_PACKET; continue; } + if (len == 0) { + if (gspca_dev->empty_packet == 0) + gspca_dev->empty_packet = 1; + continue; + } /* let the packet be analyzed by the subdriver */ PDEBUG(D_PACK, "packet [%d] o:%d l:%d", @@ -652,16 +652,12 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) : USB_ENDPOINT_XFER_ISOC; i = gspca_dev->alt; /* previous alt setting */ if (gspca_dev->cam.reverse_alts) { - if (gspca_dev->audio && i < gspca_dev->nbalt - 2) - i++; while (++i < gspca_dev->nbalt) { ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) break; } } else { - if (gspca_dev->audio && i > 1) - i--; while (--i >= 0) { ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) @@ -676,13 +672,11 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) i, ep->desc.bEndpointAddress); gspca_dev->alt = i; /* memorize the current alt setting */ if (gspca_dev->nbalt > 1) { - gspca_input_destroy_urb(gspca_dev); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { err("set alt %d err %d", i, ret); ep = NULL; } - gspca_input_create_urb(gspca_dev); } return ep; } @@ -759,7 +753,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, } } else { /* bulk */ urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, - ep->desc.bEndpointAddress), + ep->desc.bEndpointAddress); urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; urb->complete = bulk_irq; } @@ -781,7 +775,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (!gspca_dev->present) { ret = -ENODEV; - goto out; + goto unlock; } /* reset the streaming variables */ @@ -802,8 +796,10 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (gspca_dev->sd_desc->isoc_init) { ret = gspca_dev->sd_desc->isoc_init(gspca_dev); if (ret < 0) - goto out; + goto unlock; } + + gspca_input_destroy_urb(gspca_dev); ep = get_ep(gspca_dev); if (ep == NULL) { ret = -EIO; @@ -873,6 +869,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) } } out: + gspca_input_create_urb(gspca_dev); +unlock: mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1299,17 +1297,19 @@ static int vidioc_querycap(struct file *file, void *priv, ret = -ENODEV; goto out; } - strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); + strncpy((char *) cap->driver, gspca_dev->sd_desc->name, + sizeof cap->driver); if (gspca_dev->dev->product != NULL) { - strncpy(cap->card, gspca_dev->dev->product, + strncpy((char *) cap->card, gspca_dev->dev->product, sizeof cap->card); } else { - snprintf(cap->card, sizeof cap->card, + snprintf((char *) cap->card, sizeof cap->card, "USB Camera (%04x:%04x)", le16_to_cpu(gspca_dev->dev->descriptor.idVendor), le16_to_cpu(gspca_dev->dev->descriptor.idProduct)); } - usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info)); + usb_make_path(gspca_dev->dev, (char *) cap->bus_info, + sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING @@ -1710,12 +1710,13 @@ static int vidioc_g_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - gspca_dev->usb_err = 0; - if (gspca_dev->present) - ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, - parm); - else + if (gspca_dev->present) { + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + ret = gspca_dev->usb_err; + } else { ret = -ENODEV; + } mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1740,12 +1741,13 @@ static int vidioc_s_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - gspca_dev->usb_err = 0; - if (gspca_dev->present) - ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, - parm); - else + if (gspca_dev->present) { + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + ret = gspca_dev->usb_err; + } else { ret = -ENODEV; + } mutex_unlock(&gspca_dev->usb_lock); return ret; } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index d4d210b56b4..97b77a26a2e 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -62,7 +62,7 @@ struct gspca_ctrl { /* device information - set at probe time */ struct cam { const struct v4l2_pix_format *cam_mode; /* size nmodes */ - const struct framerates *mode_framerates; /* must have size nmode, + const struct framerates *mode_framerates; /* must have size nmodes, * just like cam_mode */ struct gspca_ctrl *ctrls; /* control table - size nctrls */ /* may be NULL */ @@ -93,7 +93,7 @@ typedef int (*cam_reg_op) (struct gspca_dev *, struct v4l2_dbg_register *); typedef int (*cam_ident_op) (struct gspca_dev *, struct v4l2_dbg_chip_ident *); -typedef int (*cam_streamparm_op) (struct gspca_dev *, +typedef void (*cam_streamparm_op) (struct gspca_dev *, struct v4l2_streamparm *); typedef int (*cam_qmnu_op) (struct gspca_dev *, struct v4l2_querymenu *); diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 8ded8b10057..703d48670a2 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -624,7 +624,7 @@ static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | - (i2c_data & 0x3F); + (i2c_data & 0x3f); err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) return err; diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 6cf6855aa50..e1c3b9328ac 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -75,14 +75,14 @@ struct sd { struct gspca_ctrl ctrls[NCTRL]; - __u8 packet_nr; + u8 packet_nr; char bridge; #define BRIDGE_OV511 0 #define BRIDGE_OV511PLUS 1 #define BRIDGE_OV518 2 #define BRIDGE_OV518PLUS 3 -#define BRIDGE_OV519 4 +#define BRIDGE_OV519 4 /* = ov530 */ #define BRIDGE_OVFX2 5 #define BRIDGE_W9968CF 6 #define BRIDGE_MASK 7 @@ -94,42 +94,44 @@ struct sd { char snapshot_needs_reset; /* Determined by sensor type */ - __u8 sif; + u8 sif; - __u8 quality; + u8 quality; #define QUALITY_MIN 50 #define QUALITY_MAX 70 #define QUALITY_DEF 50 - __u8 stopped; /* Streaming is temporarily paused */ - __u8 first_frame; - - __u8 frame_rate; /* current Framerate */ - __u8 clockdiv; /* clockdiv override */ - - char sensor; /* Type of image sensor chip (SEN_*) */ -#define SEN_UNKNOWN 0 -#define SEN_OV2610 1 -#define SEN_OV3610 2 -#define SEN_OV6620 3 -#define SEN_OV6630 4 -#define SEN_OV66308AF 5 -#define SEN_OV7610 6 -#define SEN_OV7620 7 -#define SEN_OV7620AE 8 -#define SEN_OV7640 9 -#define SEN_OV7648 10 -#define SEN_OV7670 11 -#define SEN_OV76BE 12 -#define SEN_OV8610 13 + u8 stopped; /* Streaming is temporarily paused */ + u8 first_frame; + + u8 frame_rate; /* current Framerate */ + u8 clockdiv; /* clockdiv override */ + + s8 sensor; /* Type of image sensor chip (SEN_*) */ u8 sensor_addr; - int sensor_width; - int sensor_height; - int sensor_reg_cache[256]; + u16 sensor_width; + u16 sensor_height; + s16 sensor_reg_cache[256]; u8 jpeg_hdr[JPEG_HDR_SZ]; }; +enum sensors { + SEN_OV2610, + SEN_OV3610, + SEN_OV6620, + SEN_OV6630, + SEN_OV66308AF, + SEN_OV7610, + SEN_OV7620, + SEN_OV7620AE, + SEN_OV7640, + SEN_OV7648, + SEN_OV7660, + SEN_OV7670, + SEN_OV76BE, + SEN_OV8610, +}; /* Note this is a bit of a hack, but the w9968cf driver needs the code for all the ov sensors which is already present here. When we have the time we @@ -182,7 +184,7 @@ static const struct ctrl sd_ctrls[] = { }, .set_control = setcolors, }, -/* The flip controls work with ov7670 only */ +/* The flip controls work for sensors ov7660 and ov7670 only */ [HFLIP] = { { .id = V4L2_CID_HFLIP, @@ -225,7 +227,7 @@ static const struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_MENU, .name = "Light frequency filter", .minimum = 0, - .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ + .maximum = 2, /* 0: no flicker, 1: 50Hz, 2:60Hz, 3: auto */ .step = 1, .default_value = 0, }, @@ -233,6 +235,53 @@ static const struct ctrl sd_ctrls[] = { }, }; +/* table of the disabled controls */ +static const unsigned ctrl_dis[] = { +[SEN_OV2610] = (1 << NCTRL) - 1, /* no control */ + +[SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ + +[SEN_OV6620] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV6630] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV66308AF] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7610] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7620] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7620AE] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7640] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << AUTOBRIGHT) | + (1 << CONTRAST), + +[SEN_OV7648] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << AUTOBRIGHT) | + (1 << CONTRAST), + +[SEN_OV7660] = (1 << AUTOBRIGHT), + +[SEN_OV7670] = (1 << COLORS) | + (1 << AUTOBRIGHT), + +[SEN_OV76BE] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV8610] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), +}; + static const struct v4l2_pix_format ov519_vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, @@ -412,7 +461,6 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { .priv = 0}, }; - /* Registers common to OV511 / OV518 */ #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ #define R51x_SYS_RESET 0x50 @@ -420,7 +468,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV511_RESET_OMNICE 0x08 #define R51x_SYS_INIT 0x53 #define R51x_SYS_SNAP 0x52 -#define R51x_SYS_CUST_ID 0x5F +#define R51x_SYS_CUST_ID 0x5f #define R51x_COMP_LUT_BEGIN 0x80 /* OV511 Camera interface register numbers */ @@ -435,13 +483,13 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define R511_CAM_OPTS 0x18 #define R511_SNAP_FRAME 0x19 -#define R511_SNAP_PXCNT 0x1A -#define R511_SNAP_LNCNT 0x1B -#define R511_SNAP_PXDIV 0x1C -#define R511_SNAP_LNDIV 0x1D -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_OPTS 0x1F +#define R511_SNAP_PXCNT 0x1a +#define R511_SNAP_LNCNT 0x1b +#define R511_SNAP_PXDIV 0x1c +#define R511_SNAP_LNDIV 0x1d +#define R511_SNAP_UV_EN 0x1e +#define R511_SNAP_UV_EN 0x1e +#define R511_SNAP_OPTS 0x1f #define R511_DRAM_FLOW_CTL 0x20 #define R511_FIFO_OPTS 0x31 @@ -466,13 +514,14 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV519_R25_FORMAT 0x25 /* OV519 System Controller register numbers */ -#define OV519_SYS_RESET1 0x51 -#define OV519_SYS_EN_CLK1 0x54 +#define OV519_R51_RESET1 0x51 +#define OV519_R54_EN_CLK1 0x54 +#define OV519_R57_SNAPSHOT 0x57 #define OV519_GPIO_DATA_OUT0 0x71 #define OV519_GPIO_IO_CTRL0 0x72 -#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ +/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */ /* * The FX2 chip does not give us a zero length read at end of frame. @@ -526,80 +575,81 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ #define OV7610_REG_COM_I 0x29 /* misc settings */ -/* OV7670 registers */ -#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ -#define OV7670_REG_BLUE 0x01 /* blue gain */ -#define OV7670_REG_RED 0x02 /* red gain */ -#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ -#define OV7670_REG_COM1 0x04 /* Control 1 */ -#define OV7670_REG_AECHH 0x07 /* AEC MS 5 bits */ -#define OV7670_REG_COM3 0x0c /* Control 3 */ -#define OV7670_REG_COM4 0x0d /* Control 4 */ -#define OV7670_REG_COM5 0x0e /* All "reserved" */ -#define OV7670_REG_COM6 0x0f /* Control 6 */ -#define OV7670_REG_AECH 0x10 /* More bits of AEC value */ -#define OV7670_REG_CLKRC 0x11 /* Clock control */ -#define OV7670_REG_COM7 0x12 /* Control 7 */ -#define OV7670_COM7_FMT_VGA 0x00 -#define OV7670_COM7_YUV 0x00 /* YUV */ -#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ -#define OV7670_COM7_FMT_MASK 0x38 -#define OV7670_COM7_RESET 0x80 /* Register reset */ -#define OV7670_REG_COM8 0x13 /* Control 8 */ -#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ -#define OV7670_COM8_AWB 0x02 /* White balance enable */ -#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ -#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ -#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ -#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ -#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */ -#define OV7670_REG_COM10 0x15 /* Control 10 */ -#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */ -#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */ -#define OV7670_REG_VSTART 0x19 /* Vert start high bits */ -#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ -#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ -#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ -#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ -#define OV7670_REG_AEW 0x24 /* AGC upper limit */ -#define OV7670_REG_AEB 0x25 /* AGC lower limit */ -#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */ -#define OV7670_REG_HREF 0x32 /* HREF pieces */ -#define OV7670_REG_TSLB 0x3a /* lots of stuff */ -#define OV7670_REG_COM11 0x3b /* Control 11 */ -#define OV7670_COM11_EXP 0x02 -#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ -#define OV7670_REG_COM12 0x3c /* Control 12 */ -#define OV7670_REG_COM13 0x3d /* Control 13 */ -#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ -#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ -#define OV7670_REG_COM14 0x3e /* Control 14 */ -#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */ -#define OV7670_REG_COM15 0x40 /* Control 15 */ -#define OV7670_COM15_R00FF 0xc0 /* 00 to FF */ -#define OV7670_REG_COM16 0x41 /* Control 16 */ -#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ -#define OV7670_REG_BRIGHT 0x55 /* Brightness */ -#define OV7670_REG_CONTRAS 0x56 /* Contrast control */ -#define OV7670_REG_GFIX 0x69 /* Fix gain control */ -#define OV7670_REG_RGB444 0x8c /* RGB 444 control */ -#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ -#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ -#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */ -#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ -#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ -#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ -#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ -#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ -#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ +/* OV7660 and OV7670 registers */ +#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ +#define OV7670_R01_BLUE 0x01 /* blue gain */ +#define OV7670_R02_RED 0x02 /* red gain */ +#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ +#define OV7670_R04_COM1 0x04 /* Control 1 */ +/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */ +#define OV7670_R0C_COM3 0x0c /* Control 3 */ +#define OV7670_R0D_COM4 0x0d /* Control 4 */ +#define OV7670_R0E_COM5 0x0e /* All "reserved" */ +#define OV7670_R0F_COM6 0x0f /* Control 6 */ +#define OV7670_R10_AECH 0x10 /* More bits of AEC value */ +#define OV7670_R11_CLKRC 0x11 /* Clock control */ +#define OV7670_R12_COM7 0x12 /* Control 7 */ +#define OV7670_COM7_FMT_VGA 0x00 +/*#define OV7670_COM7_YUV 0x00 * YUV */ +#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ +#define OV7670_COM7_FMT_MASK 0x38 +#define OV7670_COM7_RESET 0x80 /* Register reset */ +#define OV7670_R13_COM8 0x13 /* Control 8 */ +#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ +#define OV7670_COM8_AWB 0x02 /* White balance enable */ +#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ +#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ +#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ +#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ +#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */ +#define OV7670_R15_COM10 0x15 /* Control 10 */ +#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */ +#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */ +#define OV7670_R19_VSTART 0x19 /* Vert start high bits */ +#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */ +#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */ +#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ +#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ +#define OV7670_R24_AEW 0x24 /* AGC upper limit */ +#define OV7670_R25_AEB 0x25 /* AGC lower limit */ +#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */ +#define OV7670_R32_HREF 0x32 /* HREF pieces */ +#define OV7670_R3A_TSLB 0x3a /* lots of stuff */ +#define OV7670_R3B_COM11 0x3b /* Control 11 */ +#define OV7670_COM11_EXP 0x02 +#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ +#define OV7670_R3C_COM12 0x3c /* Control 12 */ +#define OV7670_R3D_COM13 0x3d /* Control 13 */ +#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ +#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ +#define OV7670_R3E_COM14 0x3e /* Control 14 */ +#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */ +#define OV7670_R40_COM15 0x40 /* Control 15 */ +/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ +#define OV7670_R41_COM16 0x41 /* Control 16 */ +#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ +/* end of ov7660 common registers */ +#define OV7670_R55_BRIGHT 0x55 /* Brightness */ +#define OV7670_R56_CONTRAS 0x56 /* Contrast control */ +#define OV7670_R69_GFIX 0x69 /* Fix gain control */ +/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */ +#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */ +#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ +#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */ +#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ +#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ +#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ +#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ +#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */ +#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */ struct ov_regvals { - __u8 reg; - __u8 val; + u8 reg; + u8 val; }; struct ov_i2c_regvals { - __u8 reg; - __u8 val; + u8 reg; + u8 val; }; /* Settings for OV2610 camera chip */ @@ -617,7 +667,6 @@ static const struct ov_i2c_regvals norm_3620b[] = { * "wait 4096 external clock ... to make sure the sensor is * stable and ready to access registers" i.e. 160us at 24MHz */ - { 0x12, 0x80 }, /* COMH reset */ { 0x12, 0x00 }, /* QXGA, master */ @@ -650,7 +699,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMI[0] "Exposure control" * = 0 (0x00) .......0 "Manual" */ - { 0x13, 0xC0 }, + { 0x13, 0xc0 }, /* * 09 COMC "Common Control C" @@ -706,7 +755,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COME[0] "Auto zero circuit select" * = 1 (0x01) .......1 "On" */ - { 0x0d, 0xA1 }, + { 0x0d, 0xa1 }, /* * 0E COMF "Common Control F" @@ -770,7 +819,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMJ[0] "Reserved" * = 0 (0x00) .......0 */ - { 0x14, 0xC6 }, + { 0x14, 0xc6 }, /* * 15 COMK "Common Control K" @@ -876,7 +925,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * FVOPT[7:0] "Range" * = 31 (0x1F) 00011111 */ - { 0x3c, 0x1F }, + { 0x3c, 0x1f }, /* * 44 Undocumented = 0 (0x00) 00000000 @@ -925,7 +974,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * 48[7:0] "It's a secret" * = 192 (0xC0) 11000000 */ - { 0x48, 0xC0 }, + { 0x48, 0xc0 }, /* * 49 Undocumented = 25 (0x19) 00011001 @@ -939,18 +988,18 @@ static const struct ov_i2c_regvals norm_3620b[] = { * 4B[7:0] "It's a secret" * = 128 (0x80) 10000000 */ - { 0x4B, 0x80 }, + { 0x4b, 0x80 }, /* * 4D Undocumented = 196 (0xC4) 11000100 * 4D[7:0] "It's a secret" * = 196 (0xC4) 11000100 */ - { 0x4D, 0xC4 }, + { 0x4d, 0xc4 }, /* * 35 VREF "Reference Voltage Control" - * = 76 (0x4C) 01001100 + * = 76 (0x4c) 01001100 * VREF[7:5] "Column high reference control" * = 2 (0x02) 010..... "higher voltage" * VREF[4:2] "Column low reference control" @@ -958,21 +1007,21 @@ static const struct ov_i2c_regvals norm_3620b[] = { * VREF[1:0] "Reserved" * = 0 (0x00) ......00 */ - { 0x35, 0x4C }, + { 0x35, 0x4c }, /* * 3D Undocumented = 0 (0x00) 00000000 * 3D[7:0] "It's a secret" * = 0 (0x00) 00000000 */ - { 0x3D, 0x00 }, + { 0x3d, 0x00 }, /* * 3E Undocumented = 0 (0x00) 00000000 * 3E[7:0] "It's a secret" * = 0 (0x00) 00000000 */ - { 0x3E, 0x00 }, + { 0x3e, 0x00 }, /* * 3B FREFB "Internal Reference Adjustment" @@ -1012,7 +1061,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * VBLM[3:0] "Sensor current control" * = 10 (0x0A) ....1010 */ - { 0x34, 0x5A }, + { 0x34, 0x5a }, /* * 3B FREFB "Internal Reference Adjustment" @@ -1078,7 +1127,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFST[7:0] "Horizontal window start, 8 MSBs" * = 31 (0x1F) 00011111 */ - { 0x17, 0x1F }, + { 0x17, 0x1f }, /* * 18 HREFEND "Horizontal window end" @@ -1086,7 +1135,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFEND[7:0] "Horizontal Window End, 8 MSBs" * = 95 (0x5F) 01011111 */ - { 0x18, 0x5F }, + { 0x18, 0x5f }, /* * 19 VSTRT "Vertical window start" @@ -1126,7 +1175,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMA[1:0] "Vertical window start line control 2 LSBs" * = 2 (0x02) ......10 */ - { 0x03, 0x4A }, + { 0x03, 0x4a }, /* * 11 CLKRC "Clock Rate Control" @@ -1183,7 +1232,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFST[7:0] "Horizontal window start, 8 MSBs" * = 31 (0x1F) 00011111 */ - { 0x17, 0x1F }, + { 0x17, 0x1f }, /* * 18 HREFEND "Horizontal window end" @@ -1191,7 +1240,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFEND[7:0] "Horizontal Window End, 8 MSBs" * = 95 (0x5F) 01011111 */ - { 0x18, 0x5F }, + { 0x18, 0x5f }, /* * 19 VSTRT "Vertical window start" @@ -1231,7 +1280,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMA[1:0] "Vertical window start line control 2 LSBs" * = 2 (0x02) ......10 */ - { 0x03, 0x4A }, + { 0x03, 0x4a }, /* * 02 RED "Red Gain Control" @@ -1241,7 +1290,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * RED[6:0] "Value" * = 47 (0x2F) .0101111 */ - { 0x02, 0xAF }, + { 0x02, 0xaf }, /* * 2D ADDVSL "VSYNC Pulse Width" @@ -1249,7 +1298,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * ADDVSL[7:0] "VSYNC pulse width, LSB" * = 210 (0xD2) 11010010 */ - { 0x2d, 0xD2 }, + { 0x2d, 0xd2 }, /* * 00 GAIN = 24 (0x18) 00011000 @@ -1272,7 +1321,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * BLUE[6:0] "Value" * = 112 (0x70) .1110000 */ - { 0x01, 0xF0 }, + { 0x01, 0xf0 }, /* * 10 AEC "Automatic Exposure Control" @@ -1280,14 +1329,14 @@ static const struct ov_i2c_regvals norm_3620b[] = { * AEC[7:0] "Automatic Exposure Control, 8 MSBs" * = 10 (0x0A) 00001010 */ - { 0x10, 0x0A }, - - { 0xE1, 0x67 }, - { 0xE3, 0x03 }, - { 0xE4, 0x26 }, - { 0xE5, 0x3E }, - { 0xF8, 0x01 }, - { 0xFF, 0x01 }, + { 0x10, 0x0a }, + + { 0xe1, 0x67 }, + { 0xe3, 0x03 }, + { 0xe4, 0x26 }, + { 0xe5, 0x3e }, + { 0xf8, 0x01 }, + { 0xff, 0x01 }, }; static const struct ov_i2c_regvals norm_6x20[] = { @@ -1296,7 +1345,7 @@ static const struct ov_i2c_regvals norm_6x20[] = { { 0x03, 0x60 }, { 0x05, 0x7f }, /* For when autoadjust is off */ { 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ + /* The ratio of 0x0c and 0x0d controls the white point */ { 0x0c, 0x24 }, { 0x0d, 0x24 }, { 0x0f, 0x15 }, /* COMS */ @@ -1464,7 +1513,7 @@ static const struct ov_i2c_regvals norm_7620[] = { { 0x00, 0x00 }, /* gain */ { 0x01, 0x80 }, /* blue gain */ { 0x02, 0x80 }, /* red gain */ - { 0x03, 0xc0 }, /* OV7670_REG_VREF */ + { 0x03, 0xc0 }, /* OV7670_R03_VREF */ { 0x06, 0x60 }, { 0x07, 0x00 }, { 0x0c, 0x24 }, @@ -1532,33 +1581,177 @@ static const struct ov_i2c_regvals norm_7640[] = { { 0x12, 0x14 }, }; +static const struct ov_regvals init_519_ov7660[] = { + { 0x5d, 0x03 }, /* Turn off suspend mode */ + { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ + { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { 0xa2, 0x20 }, /* a2-a5 are undocumented */ + { 0xa3, 0x18 }, + { 0xa4, 0x04 }, + { 0xa5, 0x28 }, + { 0x37, 0x00 }, /* SetUsbInit */ + { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ + /* Enable both fields, YUV Input, disable defect comp (why?) */ + { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ + { 0x21, 0x38 }, + { 0x22, 0x1d }, + { 0x17, 0x50 }, /* undocumented */ + { 0x37, 0x00 }, /* undocumented */ + { 0x40, 0xff }, /* I2C timeout counter */ + { 0x46, 0x00 }, /* I2C clock prescaler */ +}; +static const struct ov_i2c_regvals norm_7660[] = { + {OV7670_R12_COM7, OV7670_COM7_RESET}, + {OV7670_R11_CLKRC, 0x81}, + {0x92, 0x00}, /* DM_LNL */ + {0x93, 0x00}, /* DM_LNH */ + {0x9d, 0x4c}, /* BD50ST */ + {0x9e, 0x3f}, /* BD60ST */ + {OV7670_R3B_COM11, 0x02}, + {OV7670_R13_COM8, 0xf5}, + {OV7670_R10_AECH, 0x00}, + {OV7670_R00_GAIN, 0x00}, + {OV7670_R01_BLUE, 0x7c}, + {OV7670_R02_RED, 0x9d}, + {OV7670_R12_COM7, 0x00}, + {OV7670_R04_COM1, 00}, + {OV7670_R18_HSTOP, 0x01}, + {OV7670_R17_HSTART, 0x13}, + {OV7670_R32_HREF, 0x92}, + {OV7670_R19_VSTART, 0x02}, + {OV7670_R1A_VSTOP, 0x7a}, + {OV7670_R03_VREF, 0x00}, + {OV7670_R0E_COM5, 0x04}, + {OV7670_R0F_COM6, 0x62}, + {OV7670_R15_COM10, 0x00}, + {0x16, 0x02}, /* RSVD */ + {0x1b, 0x00}, /* PSHFT */ + {OV7670_R1E_MVFP, 0x01}, + {0x29, 0x3c}, /* RSVD */ + {0x33, 0x00}, /* CHLF */ + {0x34, 0x07}, /* ARBLM */ + {0x35, 0x84}, /* RSVD */ + {0x36, 0x00}, /* RSVD */ + {0x37, 0x04}, /* ADC */ + {0x39, 0x43}, /* OFON */ + {OV7670_R3A_TSLB, 0x00}, + {OV7670_R3C_COM12, 0x6c}, + {OV7670_R3D_COM13, 0x98}, + {OV7670_R3F_EDGE, 0x23}, + {OV7670_R40_COM15, 0xc1}, + {OV7670_R41_COM16, 0x22}, + {0x6b, 0x0a}, /* DBLV */ + {0xa1, 0x08}, /* RSVD */ + {0x69, 0x80}, /* HV */ + {0x43, 0xf0}, /* RSVD.. */ + {0x44, 0x10}, + {0x45, 0x78}, + {0x46, 0xa8}, + {0x47, 0x60}, + {0x48, 0x80}, + {0x59, 0xba}, + {0x5a, 0x9a}, + {0x5b, 0x22}, + {0x5c, 0xb9}, + {0x5d, 0x9b}, + {0x5e, 0x10}, + {0x5f, 0xe0}, + {0x60, 0x85}, + {0x61, 0x60}, + {0x9f, 0x9d}, /* RSVD */ + {0xa0, 0xa0}, /* DSPC2 */ + {0x4f, 0x60}, /* matrix */ + {0x50, 0x64}, + {0x51, 0x04}, + {0x52, 0x18}, + {0x53, 0x3c}, + {0x54, 0x54}, + {0x55, 0x40}, + {0x56, 0x40}, + {0x57, 0x40}, + {0x58, 0x0d}, /* matrix sign */ + {0x8b, 0xcc}, /* RSVD */ + {0x8c, 0xcc}, + {0x8d, 0xcf}, + {0x6c, 0x40}, /* gamma curve */ + {0x6d, 0xe0}, + {0x6e, 0xa0}, + {0x6f, 0x80}, + {0x70, 0x70}, + {0x71, 0x80}, + {0x72, 0x60}, + {0x73, 0x60}, + {0x74, 0x50}, + {0x75, 0x40}, + {0x76, 0x38}, + {0x77, 0x3c}, + {0x78, 0x32}, + {0x79, 0x1a}, + {0x7a, 0x28}, + {0x7b, 0x24}, + {0x7c, 0x04}, /* gamma curve */ + {0x7d, 0x12}, + {0x7e, 0x26}, + {0x7f, 0x46}, + {0x80, 0x54}, + {0x81, 0x64}, + {0x82, 0x70}, + {0x83, 0x7c}, + {0x84, 0x86}, + {0x85, 0x8e}, + {0x86, 0x9c}, + {0x87, 0xab}, + {0x88, 0xc4}, + {0x89, 0xd1}, + {0x8a, 0xe5}, + {OV7670_R14_COM9, 0x1e}, + {OV7670_R24_AEW, 0x80}, + {OV7670_R25_AEB, 0x72}, + {OV7670_R26_VPT, 0xb3}, + {0x62, 0x80}, /* LCC1 */ + {0x63, 0x80}, /* LCC2 */ + {0x64, 0x06}, /* LCC3 */ + {0x65, 0x00}, /* LCC4 */ + {0x66, 0x01}, /* LCC5 */ + {0x94, 0x0e}, /* RSVD.. */ + {0x95, 0x14}, + {OV7670_R13_COM8, OV7670_COM8_FASTAEC + | OV7670_COM8_AECSTEP + | OV7670_COM8_BFILT + | 0x10 + | OV7670_COM8_AGC + | OV7670_COM8_AWB + | OV7670_COM8_AEC}, + {0xa1, 0xc8} +}; + /* 7670. Defaults taken from OmniVision provided data, * as provided by Jonathan Corbet of OLPC */ static const struct ov_i2c_regvals norm_7670[] = { - { OV7670_REG_COM7, OV7670_COM7_RESET }, - { OV7670_REG_TSLB, 0x04 }, /* OV */ - { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ - { OV7670_REG_CLKRC, 0x01 }, + { OV7670_R12_COM7, OV7670_COM7_RESET }, + { OV7670_R3A_TSLB, 0x04 }, /* OV */ + { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ + { OV7670_R11_CLKRC, 0x01 }, /* * Set the hardware window. These values from OV don't entirely * make sense - hstop is less than hstart. But they work... */ - { OV7670_REG_HSTART, 0x13 }, - { OV7670_REG_HSTOP, 0x01 }, - { OV7670_REG_HREF, 0xb6 }, - { OV7670_REG_VSTART, 0x02 }, - { OV7670_REG_VSTOP, 0x7a }, - { OV7670_REG_VREF, 0x0a }, - - { OV7670_REG_COM3, 0x00 }, - { OV7670_REG_COM14, 0x00 }, + { OV7670_R17_HSTART, 0x13 }, + { OV7670_R18_HSTOP, 0x01 }, + { OV7670_R32_HREF, 0xb6 }, + { OV7670_R19_VSTART, 0x02 }, + { OV7670_R1A_VSTOP, 0x7a }, + { OV7670_R03_VREF, 0x0a }, + + { OV7670_R0C_COM3, 0x00 }, + { OV7670_R3E_COM14, 0x00 }, /* Mystery scaling numbers */ { 0x70, 0x3a }, { 0x71, 0x35 }, { 0x72, 0x11 }, { 0x73, 0xf0 }, { 0xa2, 0x02 }, -/* { OV7670_REG_COM10, 0x0 }, */ +/* { OV7670_R15_COM10, 0x0 }, */ /* Gamma curve values */ { 0x7a, 0x20 }, @@ -1580,37 +1773,37 @@ static const struct ov_i2c_regvals norm_7670[] = { /* AGC and AEC parameters. Note we start by disabling those features, then turn them only after tweaking the values. */ - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT }, - { OV7670_REG_GAIN, 0x00 }, - { OV7670_REG_AECH, 0x00 }, - { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ - { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ - { OV7670_REG_BD50MAX, 0x05 }, - { OV7670_REG_BD60MAX, 0x07 }, - { OV7670_REG_AEW, 0x95 }, - { OV7670_REG_AEB, 0x33 }, - { OV7670_REG_VPT, 0xe3 }, - { OV7670_REG_HAECC1, 0x78 }, - { OV7670_REG_HAECC2, 0x68 }, + { OV7670_R00_GAIN, 0x00 }, + { OV7670_R10_AECH, 0x00 }, + { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */ + { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ + { OV7670_RA5_BD50MAX, 0x05 }, + { OV7670_RAB_BD60MAX, 0x07 }, + { OV7670_R24_AEW, 0x95 }, + { OV7670_R25_AEB, 0x33 }, + { OV7670_R26_VPT, 0xe3 }, + { OV7670_R9F_HAECC1, 0x78 }, + { OV7670_RA0_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ - { OV7670_REG_HAECC3, 0xd8 }, - { OV7670_REG_HAECC4, 0xd8 }, - { OV7670_REG_HAECC5, 0xf0 }, - { OV7670_REG_HAECC6, 0x90 }, - { OV7670_REG_HAECC7, 0x94 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_RA6_HAECC3, 0xd8 }, + { OV7670_RA7_HAECC4, 0xd8 }, + { OV7670_RA8_HAECC5, 0xf0 }, + { OV7670_RA9_HAECC6, 0x90 }, + { OV7670_RAA_HAECC7, 0x94 }, + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT | OV7670_COM8_AGC | OV7670_COM8_AEC }, /* Almost all of these are magic "reserved" values. */ - { OV7670_REG_COM5, 0x61 }, - { OV7670_REG_COM6, 0x4b }, + { OV7670_R0E_COM5, 0x61 }, + { OV7670_R0F_COM6, 0x4b }, { 0x16, 0x02 }, - { OV7670_REG_MVFP, 0x07 }, + { OV7670_R1E_MVFP, 0x07 }, { 0x21, 0x02 }, { 0x22, 0x91 }, { 0x29, 0x07 }, @@ -1619,10 +1812,10 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x37, 0x1d }, { 0x38, 0x71 }, { 0x39, 0x2a }, - { OV7670_REG_COM12, 0x78 }, + { OV7670_R3C_COM12, 0x78 }, { 0x4d, 0x40 }, { 0x4e, 0x20 }, - { OV7670_REG_GFIX, 0x00 }, + { OV7670_R69_GFIX, 0x00 }, { 0x6b, 0x4a }, { 0x74, 0x10 }, { 0x8d, 0x4f }, @@ -1657,9 +1850,9 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x6f, 0x9f }, /* "9e for advance AWB" */ { 0x6a, 0x40 }, - { OV7670_REG_BLUE, 0x40 }, - { OV7670_REG_RED, 0x60 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_R01_BLUE, 0x40 }, + { OV7670_R02_RED, 0x60 }, + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT | OV7670_COM8_AGC @@ -1675,22 +1868,22 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x54, 0x80 }, { 0x58, 0x9e }, - { OV7670_REG_COM16, OV7670_COM16_AWBGAIN }, - { OV7670_REG_EDGE, 0x00 }, + { OV7670_R41_COM16, OV7670_COM16_AWBGAIN }, + { OV7670_R3F_EDGE, 0x00 }, { 0x75, 0x05 }, { 0x76, 0xe1 }, { 0x4c, 0x00 }, { 0x77, 0x01 }, - { OV7670_REG_COM13, OV7670_COM13_GAMMA + { OV7670_R3D_COM13, OV7670_COM13_GAMMA | OV7670_COM13_UVSAT | 2}, /* was 3 */ { 0x4b, 0x09 }, { 0xc9, 0x60 }, - { OV7670_REG_COM16, 0x38 }, + { OV7670_R41_COM16, 0x38 }, { 0x56, 0x40 }, { 0x34, 0x11 }, - { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, + { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, { 0xa4, 0x88 }, { 0x96, 0x00 }, { 0x97, 0x30 }, @@ -1825,10 +2018,13 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) } /* Write a OV519 register */ -static int reg_w(struct sd *sd, __u16 index, __u16 value) +static void reg_w(struct sd *sd, u16 index, u16 value) { int ret, req = 0; + if (sd->gspca_dev.usb_err < 0) + return; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -1838,6 +2034,8 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value) req = 0x0a; /* fall through */ case BRIDGE_W9968CF: + PDEBUG(D_USBO, "SET %02x %04x %04x", + req, value, index); ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), req, @@ -1848,6 +2046,8 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value) req = 1; } + PDEBUG(D_USBO, "SET %02x 0000 %04x %02x", + req, index, value); sd->gspca_dev.usb_buf[0] = value; ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), @@ -1857,22 +2057,22 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value) sd->gspca_dev.usb_buf, 1, 500); leave: if (ret < 0) { - err("Write reg 0x%04x -> [0x%02x] failed", - value, index); - return ret; + err("reg_w %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; + return; } - - PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); - return 0; } /* Read from a OV519 register, note not valid for the w9968cf!! */ /* returns: negative is error, pos or zero is data */ -static int reg_r(struct sd *sd, __u16 index) +static int reg_r(struct sd *sd, u16 index) { int ret; int req; + if (sd->gspca_dev.usb_err < 0) + return -1; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -1893,29 +2093,37 @@ static int reg_r(struct sd *sd, __u16 index) if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); - } else - err("Read reg [0x%02x] failed", index); + PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", + req, index, ret); + } else { + err("reg_r %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; + } return ret; } /* Read 8 values from a OV519 register */ static int reg_r8(struct sd *sd, - __u16 index) + u16 index) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 1, /* REQ_IO */ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 8, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - else - err("Read reg 8 [0x%02x] failed", index); + } else { + err("reg_r8 %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; + } return ret; } @@ -1926,34 +2134,37 @@ static int reg_r8(struct sd *sd, * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ -static int reg_w_mask(struct sd *sd, - __u16 index, - __u8 value, - __u8 mask) +static void reg_w_mask(struct sd *sd, + u16 index, + u8 value, + u8 mask) { int ret; - __u8 oldval; + u8 oldval; if (mask != 0xff) { value &= mask; /* Enforce mask on value */ ret = reg_r(sd, index); if (ret < 0) - return ret; + return; oldval = ret & ~mask; /* Clear the masked bits */ value |= oldval; /* Set the desired bits */ } - return reg_w(sd, index, value); + reg_w(sd, index, value); } /* * Writes multiple (n) byte value to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). */ -static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) +static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); ret = usb_control_msg(sd->gspca_dev.dev, @@ -1963,69 +2174,55 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) 0, index, sd->gspca_dev.usb_buf, n, 500); if (ret < 0) { - err("Write reg32 [%02x] %08x failed", index, value); - return ret; + err("reg_w32 %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; } - - return 0; } -static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) +static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) { int rc, retries; - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value); /* Three byte write cycle */ for (retries = 6; ; ) { /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_3, reg); /* Write "value" to I2C data port of OV511 */ - rc = reg_w(sd, R51x_I2C_DATA, value); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_DATA, value); /* Initiate 3-byte write cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x01); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x01); do { rc = reg_r(sd, R511_I2C_CTL); } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ if (rc < 0) - return rc; + return; if ((rc & 2) == 0) /* Ack? */ break; if (--retries < 0) { PDEBUG(D_USBO, "i2c write retries exhausted"); - return -1; + return; } } - - return 0; } -static int ov511_i2c_r(struct sd *sd, __u8 reg) +static int ov511_i2c_r(struct sd *sd, u8 reg) { int rc, value, retries; /* Two byte write cycle */ for (retries = 6; ; ) { /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_2, reg); /* Initiate 2-byte write cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x03); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x03); do { rc = reg_r(sd, R511_I2C_CTL); @@ -2049,9 +2246,7 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) /* Two byte read cycle */ for (retries = 6; ; ) { /* Initiate 2-byte read cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x05); do { rc = reg_r(sd, R511_I2C_CTL); @@ -2064,9 +2259,7 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) break; /* I2C abort */ - rc = reg_w(sd, R511_I2C_CTL, 0x10); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x10); if (--retries < 0) { PDEBUG(D_USBI, "i2c read retries exhausted"); @@ -2076,12 +2269,10 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value); /* This is needed to make i2c_w() work */ - rc = reg_w(sd, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x05); return value; } @@ -2091,32 +2282,24 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) * This is normally only called from i2c_w(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int ov518_i2c_w(struct sd *sd, - __u8 reg, - __u8 value) +static void ov518_i2c_w(struct sd *sd, + u8 reg, + u8 value) { - int rc; - - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value); /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_3, reg); /* Write "value" to I2C data port of OV511 */ - rc = reg_w(sd, R51x_I2C_DATA, value); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_DATA, value); /* Initiate 3-byte write cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x01); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x01); /* wait for write complete */ msleep(4); - return reg_r8(sd, R518_I2C_CTL); + reg_r8(sd, R518_I2C_CTL); } /* @@ -2126,105 +2309,102 @@ static int ov518_i2c_w(struct sd *sd, * This is normally only called from i2c_r(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int ov518_i2c_r(struct sd *sd, __u8 reg) +static int ov518_i2c_r(struct sd *sd, u8 reg) { - int rc, value; + int value; /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_2, reg); /* Initiate 2-byte write cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x03); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x03); /* Initiate 2-byte read cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x05); value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value); return value; } -static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) +static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), 0x02, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (__u16)value, (__u16)reg, NULL, 0, 500); + (u16) value, (u16) reg, NULL, 0, 500); if (ret < 0) { - err("i2c 0x%02x -> [0x%02x] failed", value, reg); - return ret; + err("ovfx2_i2c_w %02x failed %d", reg, ret); + sd->gspca_dev.usb_err = ret; } - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - return 0; + PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value); } -static int ovfx2_i2c_r(struct sd *sd, __u8 reg) +static int ovfx2_i2c_r(struct sd *sd, u8 reg) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 0x03, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500); + 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500); if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); - } else - err("i2c read [0x%02x] failed", reg); + PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret); + } else { + err("ovfx2_i2c_r %02x failed %d", reg, ret); + sd->gspca_dev.usb_err = ret; + } return ret; } -static int i2c_w(struct sd *sd, __u8 reg, __u8 value) +static void i2c_w(struct sd *sd, u8 reg, u8 value) { - int ret = -1; - if (sd->sensor_reg_cache[reg] == value) - return 0; + return; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_i2c_w(sd, reg, value); + ov511_i2c_w(sd, reg, value); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: case BRIDGE_OV519: - ret = ov518_i2c_w(sd, reg, value); + ov518_i2c_w(sd, reg, value); break; case BRIDGE_OVFX2: - ret = ovfx2_i2c_w(sd, reg, value); + ovfx2_i2c_w(sd, reg, value); break; case BRIDGE_W9968CF: - ret = w9968cf_i2c_w(sd, reg, value); + w9968cf_i2c_w(sd, reg, value); break; } - if (ret >= 0) { + if (sd->gspca_dev.usb_err >= 0) { /* Up on sensor reset empty the register cache */ if (reg == 0x12 && (value & 0x80)) memset(sd->sensor_reg_cache, -1, - sizeof(sd->sensor_reg_cache)); + sizeof(sd->sensor_reg_cache)); else sd->sensor_reg_cache[reg] = value; } - - return ret; } -static int i2c_r(struct sd *sd, __u8 reg) +static int i2c_r(struct sd *sd, u8 reg) { int ret = -1; @@ -2260,95 +2440,99 @@ static int i2c_r(struct sd *sd, __u8 reg) * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ -static int i2c_w_mask(struct sd *sd, - __u8 reg, - __u8 value, - __u8 mask) +static void i2c_w_mask(struct sd *sd, + u8 reg, + u8 value, + u8 mask) { int rc; - __u8 oldval; + u8 oldval; value &= mask; /* Enforce mask on value */ rc = i2c_r(sd, reg); if (rc < 0) - return rc; + return; oldval = rc & ~mask; /* Clear the masked bits */ value |= oldval; /* Set the desired bits */ - return i2c_w(sd, reg, value); + i2c_w(sd, reg, value); } /* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */ -static inline int ov51x_stop(struct sd *sd) +static inline void ov51x_stop(struct sd *sd) { PDEBUG(D_STREAM, "stopping"); sd->stopped = 1; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return reg_w(sd, R51x_SYS_RESET, 0x3d); + reg_w(sd, R51x_SYS_RESET, 0x3d); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + break; case BRIDGE_OV519: - return reg_w(sd, OV519_SYS_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, 0x22, 0x00); /* FRAR */ + break; case BRIDGE_OVFX2: - return reg_w_mask(sd, 0x0f, 0x00, 0x02); + reg_w_mask(sd, 0x0f, 0x00, 0x02); + break; case BRIDGE_W9968CF: - return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + break; } - - return 0; } /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not * actually stopped (for performance). */ -static inline int ov51x_restart(struct sd *sd) +static inline void ov51x_restart(struct sd *sd) { - int rc; - PDEBUG(D_STREAM, "restarting"); if (!sd->stopped) - return 0; + return; sd->stopped = 0; /* Reinitialize the stream */ switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return reg_w(sd, R51x_SYS_RESET, 0x00); + reg_w(sd, R51x_SYS_RESET, 0x00); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - rc = reg_w(sd, 0x2f, 0x80); - if (rc < 0) - return rc; - return reg_w(sd, R51x_SYS_RESET, 0x00); + reg_w(sd, 0x2f, 0x80); + reg_w(sd, R51x_SYS_RESET, 0x00); + break; case BRIDGE_OV519: - return reg_w(sd, OV519_SYS_RESET1, 0x00); + reg_w(sd, OV519_R51_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, 0x22, 0x1d); /* FRAR */ + break; case BRIDGE_OVFX2: - return reg_w_mask(sd, 0x0f, 0x02, 0x02); + reg_w_mask(sd, 0x0f, 0x02, 0x02); + break; case BRIDGE_W9968CF: - return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ + reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ + break; } - - return 0; } -static int ov51x_set_slave_ids(struct sd *sd, __u8 slave); +static void ov51x_set_slave_ids(struct sd *sd, u8 slave); /* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 on failure. */ -static int init_ov_sensor(struct sd *sd, __u8 slave) +static int init_ov_sensor(struct sd *sd, u8 slave) { int i; - if (ov51x_set_slave_ids(sd, slave) < 0) - return -EIO; + ov51x_set_slave_ids(sd, slave); /* Reset the sensor */ - if (i2c_w(sd, 0x12, 0x80) < 0) - return -EIO; + i2c_w(sd, 0x12, 0x80); /* Wait for it to initialize */ msleep(150); @@ -2361,15 +2545,16 @@ static int init_ov_sensor(struct sd *sd, __u8 slave) } /* Reset the sensor */ - if (i2c_w(sd, 0x12, 0x80) < 0) - return -EIO; + i2c_w(sd, 0x12, 0x80); + /* Wait for it to initialize */ msleep(150); + /* Dummy read to sync I2C */ if (i2c_r(sd, 0x00) < 0) - return -EIO; + return -1; } - return -EIO; + return -1; } /* Set the read and write slave IDs. The "slave" argument is the write slave, @@ -2377,53 +2562,40 @@ static int init_ov_sensor(struct sd *sd, __u8 slave) * This should not be called from outside the i2c I/O functions. * Sets I2C read and write slave IDs. Returns <0 for error */ -static int ov51x_set_slave_ids(struct sd *sd, - __u8 slave) +static void ov51x_set_slave_ids(struct sd *sd, + u8 slave) { - int rc; - switch (sd->bridge) { case BRIDGE_OVFX2: - return reg_w(sd, OVFX2_I2C_ADDR, slave); + reg_w(sd, OVFX2_I2C_ADDR, slave); + return; case BRIDGE_W9968CF: sd->sensor_addr = slave; - return 0; + return; } - rc = reg_w(sd, R51x_I2C_W_SID, slave); - if (rc < 0) - return rc; - return reg_w(sd, R51x_I2C_R_SID, slave + 1); + reg_w(sd, R51x_I2C_W_SID, slave); + reg_w(sd, R51x_I2C_R_SID, slave + 1); } -static int write_regvals(struct sd *sd, +static void write_regvals(struct sd *sd, const struct ov_regvals *regvals, int n) { - int rc; - while (--n >= 0) { - rc = reg_w(sd, regvals->reg, regvals->val); - if (rc < 0) - return rc; + reg_w(sd, regvals->reg, regvals->val); regvals++; } - return 0; } -static int write_i2c_regvals(struct sd *sd, - const struct ov_i2c_regvals *regvals, - int n) +static void write_i2c_regvals(struct sd *sd, + const struct ov_i2c_regvals *regvals, + int n) { - int rc; - while (--n >= 0) { - rc = i2c_w(sd, regvals->reg, regvals->val); - if (rc < 0) - return rc; + i2c_w(sd, regvals->reg, regvals->val); regvals++; } - return 0; } /**************************************************************************** @@ -2433,13 +2605,13 @@ static int write_i2c_regvals(struct sd *sd, ***************************************************************************/ /* This initializes the OV2x10 / OV3610 / OV3620 */ -static int ov_hires_configure(struct sd *sd) +static void ov_hires_configure(struct sd *sd) { int high, low; if (sd->bridge != BRIDGE_OVFX2) { err("error hires sensors only supported with ovfx2"); - return -1; + return; } PDEBUG(D_PROBE, "starting ov hires configuration"); @@ -2455,20 +2627,15 @@ static int ov_hires_configure(struct sd *sd) PDEBUG(D_PROBE, "Sensor is an OV3610"); sd->sensor = SEN_OV3610; } else { - err("Error unknown sensor type: 0x%02x%02x", - high, low); - return -1; + err("Error unknown sensor type: %02x%02x", + high, low); } - - /* Set sensor-specific vars */ - return 0; } - /* This initializes the OV8110, OV8610 sensor. The OV8110 uses * the same register settings as the OV8610, since they are very similar. */ -static int ov8xx0_configure(struct sd *sd) +static void ov8xx0_configure(struct sd *sd) { int rc; @@ -2478,27 +2645,21 @@ static int ov8xx0_configure(struct sd *sd) rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } - if ((rc & 3) == 1) { + if ((rc & 3) == 1) sd->sensor = SEN_OV8610; - } else { + else err("Unknown image sensor version: %d", rc & 3); - return -1; - } - - /* Set sensor-specific vars */ - return 0; } /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses * the same register settings as the OV7610, since they are very similar. */ -static int ov7xx0_configure(struct sd *sd) +static void ov7xx0_configure(struct sd *sd) { int rc, high, low; - PDEBUG(D_PROBE, "starting OV7xx0 configuration"); /* Detect sensor (sub)type */ @@ -2508,15 +2669,15 @@ static int ov7xx0_configure(struct sd *sd) * it appears to be wrongly detected as a 7610 by default */ if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } if ((rc & 3) == 3) { /* quick hack to make OV7670s work */ high = i2c_r(sd, 0x0a); low = i2c_r(sd, 0x0b); /* info("%x, %x", high, low); */ - if (high == 0x76 && low == 0x73) { - PDEBUG(D_PROBE, "Sensor is an OV7670"); + if (high == 0x76 && (low & 0xf0) == 0x70) { + PDEBUG(D_PROBE, "Sensor is an OV76%02x", low); sd->sensor = SEN_OV7670; } else { PDEBUG(D_PROBE, "Sensor is an OV7610"); @@ -2536,19 +2697,19 @@ static int ov7xx0_configure(struct sd *sd) high = i2c_r(sd, 0x0a); if (high < 0) { PDEBUG(D_ERR, "Error detecting camera chip PID"); - return high; + return; } low = i2c_r(sd, 0x0b); if (low < 0) { PDEBUG(D_ERR, "Error detecting camera chip VER"); - return low; + return; } if (high == 0x76) { switch (low) { case 0x30: err("Sensor is an OV7630/OV7635"); err("7630 is not supported by this driver"); - return -1; + return; case 0x40: PDEBUG(D_PROBE, "Sensor is an OV7645"); sd->sensor = SEN_OV7640; /* FIXME */ @@ -2561,9 +2722,14 @@ static int ov7xx0_configure(struct sd *sd) PDEBUG(D_PROBE, "Sensor is an OV7648"); sd->sensor = SEN_OV7648; break; + case 0x60: + PDEBUG(D_PROBE, "Sensor is a OV7660"); + sd->sensor = SEN_OV7660; + sd->invert_led = 0; + break; default: PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); - return -1; + return; } } else { PDEBUG(D_PROBE, "Sensor is an OV7620"); @@ -2571,15 +2737,11 @@ static int ov7xx0_configure(struct sd *sd) } } else { err("Unknown image sensor version: %d", rc & 3); - return -1; } - - /* Set sensor-specific vars */ - return 0; } /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ -static int ov6xx0_configure(struct sd *sd) +static void ov6xx0_configure(struct sd *sd) { int rc; PDEBUG(D_PROBE, "starting OV6xx0 configuration"); @@ -2588,7 +2750,7 @@ static int ov6xx0_configure(struct sd *sd) rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } /* Ugh. The first two bits are the version bits, but @@ -2619,13 +2781,11 @@ static int ov6xx0_configure(struct sd *sd) break; default: err("FATAL: Unknown sensor version: 0x%02x", rc); - return -1; + return; } /* Set sensor-specific vars */ sd->sif = 1; - - return 0; } /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ @@ -2637,14 +2797,14 @@ static void ov51x_led_control(struct sd *sd, int on) switch (sd->bridge) { /* OV511 has no LED control */ case BRIDGE_OV511PLUS: - reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); + reg_w(sd, R511_SYS_LED_CTL, on); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); + reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02); break; case BRIDGE_OV519: - reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ + reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1); break; } } @@ -2679,7 +2839,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev) } } -static int ov51x_upload_quan_tables(struct sd *sd) +static void ov51x_upload_quan_tables(struct sd *sd) { const unsigned char yQuanTable511[] = { 0, 1, 1, 2, 2, 3, 3, 4, @@ -2710,7 +2870,6 @@ static int ov51x_upload_quan_tables(struct sd *sd) 6, 6, 6, 6, 7, 7, 7, 8, 7, 7, 6, 7, 7, 7, 8, 8 }; - const unsigned char uvQuanTable518[] = { 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, 7, 7, 7, @@ -2720,18 +2879,18 @@ static int ov51x_upload_quan_tables(struct sd *sd) const unsigned char *pYTable, *pUVTable; unsigned char val0, val1; - int i, size, rc, reg = R51x_COMP_LUT_BEGIN; + int i, size, reg = R51x_COMP_LUT_BEGIN; PDEBUG(D_PROBE, "Uploading quantization tables"); if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { pYTable = yQuanTable511; pUVTable = uvQuanTable511; - size = 32; + size = 32; } else { pYTable = yQuanTable518; pUVTable = uvQuanTable518; - size = 16; + size = 16; } for (i = 0; i < size; i++) { @@ -2740,30 +2899,23 @@ static int ov51x_upload_quan_tables(struct sd *sd) val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg, val0); - if (rc < 0) - return rc; + reg_w(sd, reg, val0); val0 = *pUVTable++; val1 = *pUVTable++; val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg + size, val0); - if (rc < 0) - return rc; + reg_w(sd, reg + size, val0); reg++; } - - return 0; } /* This initializes the OV511/OV511+ and the sensor */ -static int ov511_configure(struct gspca_dev *gspca_dev) +static void ov511_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int rc; /* For 511 and 511+ */ const struct ov_regvals init_511[] = { @@ -2809,42 +2961,27 @@ static int ov511_configure(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); - rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); - if (rc < 0) - return rc; + write_regvals(sd, init_511, ARRAY_SIZE(init_511)); switch (sd->bridge) { case BRIDGE_OV511: - rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); - if (rc < 0) - return rc; + write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); break; case BRIDGE_OV511PLUS: - rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); - if (rc < 0) - return rc; + write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); break; } /* Init compression */ - rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - if (rc < 0) - return rc; - - rc = ov51x_upload_quan_tables(sd); - if (rc < 0) { - PDEBUG(D_ERR, "Error uploading quantization tables"); - return rc; - } + write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - return 0; + ov51x_upload_quan_tables(sd); } /* This initializes the OV518/OV518+ and the sensor */ -static int ov518_configure(struct gspca_dev *gspca_dev) +static void ov518_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int rc; /* For 518 and 518+ */ const struct ov_regvals init_518[] = { @@ -2892,65 +3029,49 @@ static int ov518_configure(struct gspca_dev *gspca_dev) /* First 5 bits of custom ID reg are a revision ID on OV518 */ PDEBUG(D_PROBE, "Device revision %d", - 0x1F & reg_r(sd, R51x_SYS_CUST_ID)); + 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); - rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); - if (rc < 0) - return rc; + write_regvals(sd, init_518, ARRAY_SIZE(init_518)); /* Set LED GPIO pin to output mode */ - rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); - if (rc < 0) - return rc; + reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); switch (sd->bridge) { case BRIDGE_OV518: - rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); - if (rc < 0) - return rc; + write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); break; case BRIDGE_OV518PLUS: - rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); - if (rc < 0) - return rc; + write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); break; } - rc = ov51x_upload_quan_tables(sd); - if (rc < 0) { - PDEBUG(D_ERR, "Error uploading quantization tables"); - return rc; - } + ov51x_upload_quan_tables(sd); - rc = reg_w(sd, 0x2f, 0x80); - if (rc < 0) - return rc; - - return 0; + reg_w(sd, 0x2f, 0x80); } -static int ov519_configure(struct sd *sd) +static void ov519_configure(struct sd *sd) { static const struct ov_regvals init_519[] = { - { 0x5a, 0x6d }, /* EnableSystem */ - { 0x53, 0x9b }, - { 0x54, 0xff }, /* set bit2 to enable jpeg */ - { 0x5d, 0x03 }, - { 0x49, 0x01 }, - { 0x48, 0x00 }, + { 0x5a, 0x6d }, /* EnableSystem */ + { 0x53, 0x9b }, + { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ + { 0x5d, 0x03 }, + { 0x49, 0x01 }, + { 0x48, 0x00 }, /* Set LED pin to output mode. Bit 4 must be cleared or sensor * detection will fail. This deserves further investigation. */ { OV519_GPIO_IO_CTRL0, 0xee }, - { 0x51, 0x0f }, /* SetUsbInit */ - { 0x51, 0x00 }, - { 0x22, 0x00 }, + { OV519_R51_RESET1, 0x0f }, + { OV519_R51_RESET1, 0x00 }, + { 0x22, 0x00 }, /* windows reads 0x55 at this point*/ }; - return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); + write_regvals(sd, init_519, ARRAY_SIZE(init_519)); } -static int ovfx2_configure(struct sd *sd) +static void ovfx2_configure(struct sd *sd) { static const struct ov_regvals init_fx2[] = { { 0x00, 0x60 }, @@ -2964,7 +3085,92 @@ static int ovfx2_configure(struct sd *sd) sd->stopped = 1; - return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); + write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); +} + +/* set the mode */ +/* This function works for ov7660 only */ +static void ov519_set_mode(struct sd *sd) +{ + static const struct ov_regvals bridge_ov7660[2][10] = { + {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, + {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, + {0x25, 0x01}, {0x26, 0x00}}, + {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, + {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, + {0x25, 0x03}, {0x26, 0x00}} + }; + static const struct ov_i2c_regvals sensor_ov7660[2][3] = { + {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, + {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} + }; + static const struct ov_i2c_regvals sensor_ov7660_2[] = { + {OV7670_R17_HSTART, 0x13}, + {OV7670_R18_HSTOP, 0x01}, + {OV7670_R32_HREF, 0x92}, + {OV7670_R19_VSTART, 0x02}, + {OV7670_R1A_VSTOP, 0x7a}, + {OV7670_R03_VREF, 0x00}, +/* {0x33, 0x00}, */ +/* {0x34, 0x07}, */ +/* {0x36, 0x00}, */ +/* {0x6b, 0x0a}, */ + }; + + write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], + ARRAY_SIZE(bridge_ov7660[0])); + write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], + ARRAY_SIZE(sensor_ov7660[0])); + write_i2c_regvals(sd, sensor_ov7660_2, + ARRAY_SIZE(sensor_ov7660_2)); +} + +/* set the frame rate */ +/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ +static void ov519_set_fr(struct sd *sd) +{ + int fr; + u8 clock; + /* frame rate table with indices: + * - mode = 0: 320x240, 1: 640x480 + * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 + * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) + */ + static const u8 fr_tb[2][6][3] = { + {{0x04, 0xff, 0x00}, + {0x04, 0x1f, 0x00}, + {0x04, 0x1b, 0x00}, + {0x04, 0x15, 0x00}, + {0x04, 0x09, 0x00}, + {0x04, 0x01, 0x00}}, + {{0x0c, 0xff, 0x00}, + {0x0c, 0x1f, 0x00}, + {0x0c, 0x1b, 0x00}, + {0x04, 0xff, 0x01}, + {0x04, 0x1f, 0x01}, + {0x04, 0x1b, 0x01}}, + }; + + if (frame_rate > 0) + sd->frame_rate = frame_rate; + if (sd->frame_rate >= 30) + fr = 0; + else if (sd->frame_rate >= 25) + fr = 1; + else if (sd->frame_rate >= 20) + fr = 2; + else if (sd->frame_rate >= 15) + fr = 3; + else if (sd->frame_rate >= 10) + fr = 4; + else + fr = 5; + reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); + reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); + clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; + if (sd->sensor == SEN_OV7660) + clock |= 0x80; /* enable double clock */ + ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); } /* this function is called at probe time */ @@ -2973,99 +3179,119 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; - int ret = 0; sd->bridge = id->driver_info & BRIDGE_MASK; - sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; + sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_configure(gspca_dev); + cam->cam_mode = ov511_vga_mode; + cam->nmodes = ARRAY_SIZE(ov511_vga_mode); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ret = ov518_configure(gspca_dev); + cam->cam_mode = ov518_vga_mode; + cam->nmodes = ARRAY_SIZE(ov518_vga_mode); break; case BRIDGE_OV519: - ret = ov519_configure(sd); + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); + sd->invert_led = !sd->invert_led; break; case BRIDGE_OVFX2: - ret = ovfx2_configure(sd); + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); cam->bulk_size = OVFX2_BULK_SIZE; cam->bulk_nurbs = MAX_NURBS; cam->bulk = 1; break; case BRIDGE_W9968CF: - ret = w9968cf_configure(sd); + cam->cam_mode = w9968cf_vga_mode; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); cam->reverse_alts = 1; break; } - if (ret) - goto error; + gspca_dev->cam.ctrls = sd->ctrls; + sd->quality = QUALITY_DEF; - ov51x_led_control(sd, 0); /* turn LED off */ + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + ov511_configure(gspca_dev); + break; + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + ov518_configure(gspca_dev); + break; + case BRIDGE_OV519: + ov519_configure(sd); + break; + case BRIDGE_OVFX2: + ovfx2_configure(sd); + break; + case BRIDGE_W9968CF: + w9968cf_configure(sd); + break; + } /* The OV519 must be more aggressive about sensor detection since * I2C write will never fail if the sensor is not present. We have * to try to initialize the sensor to detect its presence */ + sd->sensor = -1; /* Test for 76xx */ if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { - if (ov7xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV7xx0"); - goto error; - } + ov7xx0_configure(sd); + /* Test for 6xx0 */ } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { - if (ov6xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV6xx0"); - goto error; - } + ov6xx0_configure(sd); + /* Test for 8xx0 */ } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { - if (ov8xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV8xx0"); - goto error; - } + ov8xx0_configure(sd); + /* Test for 3xxx / 2xxx */ } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { - if (ov_hires_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure high res OV"); - goto error; - } + ov_hires_configure(sd); } else { err("Can't determine sensor slave IDs"); goto error; } + if (sd->sensor < 0) + goto error; + + ov51x_led_control(sd, 0); /* turn LED off */ + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - if (!sd->sif) { - cam->cam_mode = ov511_vga_mode; - cam->nmodes = ARRAY_SIZE(ov511_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov511_sif_mode; cam->nmodes = ARRAY_SIZE(ov511_sif_mode); } break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - if (!sd->sif) { - cam->cam_mode = ov518_vga_mode; - cam->nmodes = ARRAY_SIZE(ov518_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov518_sif_mode; cam->nmodes = ARRAY_SIZE(ov518_sif_mode); } break; case BRIDGE_OV519: - if (!sd->sif) { - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov519_sif_mode; cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } @@ -3077,118 +3303,107 @@ static int sd_config(struct gspca_dev *gspca_dev, } else if (sd->sensor == SEN_OV3610) { cam->cam_mode = ovfx2_ov3610_mode; cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); - } else if (!sd->sif) { - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - } else { + } else if (sd->sif) { cam->cam_mode = ov519_sif_mode; cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } break; case BRIDGE_W9968CF: - cam->cam_mode = w9968cf_vga_mode; - cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); if (sd->sif) - cam->nmodes--; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1; /* w9968cf needs initialisation once the sensor is known */ - if (w9968cf_init(sd) < 0) - goto error; + w9968cf_init(sd); break; } - gspca_dev->cam.ctrls = sd->ctrls; - if (sd->sensor == SEN_OV7670) - gspca_dev->ctrl_dis = 1 << COLORS; - else - gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); - sd->quality = QUALITY_DEF; - if (sd->sensor == SEN_OV7640 || - sd->sensor == SEN_OV7648) - gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT) | (1 << CONTRAST); - if (sd->sensor == SEN_OV7670) - gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT; - /* OV8610 Frequency filter control should work but needs testing */ - if (sd->sensor == SEN_OV8610) - gspca_dev->ctrl_dis |= 1 << FREQ; - /* No controls for the OV2610/OV3610 */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - gspca_dev->ctrl_dis |= (1 << NCTRL) - 1; - return 0; -error: - PDEBUG(D_ERR, "OV519 Config failed"); - return -EBUSY; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; + gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; /* initialize the sensor */ switch (sd->sensor) { case SEN_OV2610: - if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610))) - return -EIO; + write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)); + /* Enable autogain, autoexpo, awb, bandfilter */ - if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) - return -EIO; + i2c_w_mask(sd, 0x13, 0x27, 0x27); break; case SEN_OV3610: - if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b))) - return -EIO; + write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)); + /* Enable autogain, autoexpo, awb, bandfilter */ - if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) - return -EIO; + i2c_w_mask(sd, 0x13, 0x27, 0x27); break; case SEN_OV6620: - if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) - return -EIO; + write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)); break; case SEN_OV6630: case SEN_OV66308AF: sd->ctrls[CONTRAST].def = 200; /* The default is too low for the ov6630 */ - if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) - return -EIO; + write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)); break; default: /* case SEN_OV7610: */ /* case SEN_OV76BE: */ - if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) - return -EIO; - if (i2c_w_mask(sd, 0x0e, 0x00, 0x40)) - return -EIO; + write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)); + i2c_w_mask(sd, 0x0e, 0x00, 0x40); break; case SEN_OV7620: case SEN_OV7620AE: - if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) - return -EIO; + write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)); break; case SEN_OV7640: case SEN_OV7648: - if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) - return -EIO; + write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); + break; + case SEN_OV7660: + i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); + msleep(14); + reg_w(sd, OV519_R57_SNAPSHOT, 0x23); + write_regvals(sd, init_519_ov7660, + ARRAY_SIZE(init_519_ov7660)); + write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); + sd->gspca_dev.curr_mode = 1; /* 640x480 */ + sd->frame_rate = 15; + ov519_set_mode(sd); + ov519_set_fr(sd); + sd->ctrls[COLORS].max = 4; /* 0..4 */ + sd->ctrls[COLORS].val = + sd->ctrls[COLORS].def = 2; + setcolors(gspca_dev); + sd->ctrls[CONTRAST].max = 6; /* 0..6 */ + sd->ctrls[CONTRAST].val = + sd->ctrls[CONTRAST].def = 3; + setcontrast(gspca_dev); + sd->ctrls[BRIGHTNESS].max = 6; /* 0..6 */ + sd->ctrls[BRIGHTNESS].val = + sd->ctrls[BRIGHTNESS].def = 3; + setbrightness(gspca_dev); + sd_reset_snapshot(gspca_dev); + ov51x_restart(sd); + ov51x_stop(sd); /* not in win traces */ + ov51x_led_control(sd, 0); break; case SEN_OV7670: sd->ctrls[FREQ].max = 3; /* auto */ sd->ctrls[FREQ].def = 3; - if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) - return -EIO; + write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)); break; case SEN_OV8610: - if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) - return -EIO; + write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)); break; } - return 0; + return gspca_dev->usb_err; +error: + PDEBUG(D_ERR, "OV519 Config failed"); + return -EINVAL; } /* Set up the OV511/OV511+ with the given image parameters. * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov511_mode_init_regs(struct sd *sd) +static void ov511_mode_init_regs(struct sd *sd) { int hsegs, vsegs, packet_size, fps, needed; int interlaced = 0; @@ -3199,7 +3414,8 @@ static int ov511_mode_init_regs(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) { err("Couldn't get altsetting"); - return -EIO; + sd->gspca_dev.usb_err = -EIO; + return; } packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); @@ -3302,8 +3518,6 @@ static int ov511_mode_init_regs(struct sd *sd) reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); reg_w(sd, R51x_SYS_RESET, 0); - - return 0; } /* Sets up the OV518/OV518+ with the given image parameters @@ -3313,7 +3527,7 @@ static int ov511_mode_init_regs(struct sd *sd) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov518_mode_init_regs(struct sd *sd) +static void ov518_mode_init_regs(struct sd *sd) { int hsegs, vsegs, packet_size; struct usb_host_interface *alt; @@ -3323,14 +3537,14 @@ static int ov518_mode_init_regs(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) { err("Couldn't get altsetting"); - return -EIO; + sd->gspca_dev.usb_err = -EIO; + return; } packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); /******** Set the mode ********/ - reg_w(sd, 0x2b, 0); reg_w(sd, 0x2c, 0); reg_w(sd, 0x2d, 0); @@ -3364,7 +3578,7 @@ static int ov518_mode_init_regs(struct sd *sd) /* Windows driver does this here; who knows why */ reg_w(sd, 0x2f, 0x80); - /******** Set the framerate ********/ + /******** Set the framerate ********/ sd->clockdiv = 1; /* Mode independent, but framerate dependent, regs */ @@ -3427,11 +3641,8 @@ static int ov518_mode_init_regs(struct sd *sd) } reg_w(sd, 0x2f, 0x80); - - return 0; } - /* Sets up the OV519 with the given image parameters * * OV519 needs a completely different approach, until we can figure out what @@ -3439,12 +3650,12 @@ static int ov518_mode_init_regs(struct sd *sd) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov519_mode_init_regs(struct sd *sd) +static void ov519_mode_init_regs(struct sd *sd) { static const struct ov_regvals mode_init_519_ov7670[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ { 0xa2, 0x20 }, /* a2-a5 are undocumented */ { 0xa3, 0x18 }, { 0xa4, 0x04 }, @@ -3467,7 +3678,7 @@ static int ov519_mode_init_regs(struct sd *sd) static const struct ov_regvals mode_init_519[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ { 0xa2, 0x20 }, /* a2-a5 are undocumented */ { 0xa3, 0x18 }, { 0xa4, 0x04 }, @@ -3486,19 +3697,21 @@ static int ov519_mode_init_regs(struct sd *sd) }; /******** Set the mode ********/ - if (sd->sensor != SEN_OV7670) { - if (write_regvals(sd, mode_init_519, - ARRAY_SIZE(mode_init_519))) - return -EIO; + switch (sd->sensor) { + default: + write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); } - } else { - if (write_regvals(sd, mode_init_519_ov7670, - ARRAY_SIZE(mode_init_519_ov7670))) - return -EIO; + break; + case SEN_OV7660: + return; /* done by ov519_set_mode/fr() */ + case SEN_OV7670: + write_regvals(sd, mode_init_519_ov7670, + ARRAY_SIZE(mode_init_519_ov7670)); + break; } reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); @@ -3594,17 +3807,16 @@ static int ov519_mode_init_regs(struct sd *sd) } break; } - return 0; } -static int mode_init_ov_sensor_regs(struct sd *sd) +static void mode_init_ov_sensor_regs(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, xstart, xend, ystart, yend; - __u8 v; + u8 v; gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; + qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { @@ -3616,7 +3828,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - return 0; + return; case SEN_OV3610: if (qvga) { xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); @@ -3640,7 +3852,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w(sd, 0x18, xend >> 4); i2c_w(sd, 0x19, ystart >> 3); i2c_w(sd, 0x1a, yend >> 3); - return 0; + return; case SEN_OV8610: /* For OV8610 qvga means qsvga */ i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); @@ -3687,11 +3899,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd) /* set COM7_FMT_VGA or COM7_FMT_QVGA * do we need to set anything else? * HSTART etc are set in set_ov_sensor_window itself */ - i2c_w_mask(sd, OV7670_REG_COM7, + i2c_w_mask(sd, OV7670_R12_COM7, qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, OV7670_COM7_FMT_MASK); i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB, OV7670_COM8_AWB); if (qvga) { /* QVGA from ov7670.c by * Jonathan Corbet */ @@ -3707,21 +3919,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd) } /* OV7670 hardware window registers are split across * multiple locations */ - i2c_w(sd, OV7670_REG_HSTART, xstart >> 3); - i2c_w(sd, OV7670_REG_HSTOP, xend >> 3); - v = i2c_r(sd, OV7670_REG_HREF); + i2c_w(sd, OV7670_R17_HSTART, xstart >> 3); + i2c_w(sd, OV7670_R18_HSTOP, xend >> 3); + v = i2c_r(sd, OV7670_R32_HREF); v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); msleep(10); /* need to sleep between read and write to * same reg! */ - i2c_w(sd, OV7670_REG_HREF, v); + i2c_w(sd, OV7670_R32_HREF, v); - i2c_w(sd, OV7670_REG_VSTART, ystart >> 2); - i2c_w(sd, OV7670_REG_VSTOP, yend >> 2); - v = i2c_r(sd, OV7670_REG_VREF); + i2c_w(sd, OV7670_R19_VSTART, ystart >> 2); + i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2); + v = i2c_r(sd, OV7670_R03_VREF); v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); msleep(10); /* need to sleep between read and write to * same reg! */ - i2c_w(sd, OV7670_REG_VREF, v); + i2c_w(sd, OV7670_R03_VREF, v); break; case SEN_OV6620: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); @@ -3734,46 +3946,50 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ break; default: - return -EINVAL; + return; } /******** Clock programming ********/ i2c_w(sd, 0x11, sd->clockdiv); - - return 0; } +/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ static void sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor != SEN_OV7670) - return; if (sd->gspca_dev.streaming) - ov51x_stop(sd); - i2c_w_mask(sd, OV7670_REG_MVFP, + reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */ + i2c_w_mask(sd, OV7670_R1E_MVFP, OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val, OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); if (sd->gspca_dev.streaming) - ov51x_restart(sd); + reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */ } -static int set_ov_sensor_window(struct sd *sd) +static void set_ov_sensor_window(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, crop; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; - int ret; /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || - sd->sensor == SEN_OV7670) - return mode_init_ov_sensor_regs(sd); + switch (sd->sensor) { + case SEN_OV2610: + case SEN_OV3610: + case SEN_OV7670: + mode_init_ov_sensor_regs(sd); + return; + case SEN_OV7660: + ov519_set_mode(sd); + ov519_set_fr(sd); + return; + } gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; - crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2; + qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; + crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; /* The different sensor ICs handle setting up of window differently. * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ @@ -3820,7 +4036,7 @@ static int set_ov_sensor_window(struct sd *sd) vwsbase = vwebase = 0x03; break; default: - return -EINVAL; + return; } switch (sd->sensor) { @@ -3855,23 +4071,18 @@ static int set_ov_sensor_window(struct sd *sd) } } - ret = mode_init_ov_sensor_regs(sd); - if (ret < 0) - return ret; + mode_init_ov_sensor_regs(sd); i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); - - return 0; } /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int ret = 0; /* Default for most bridges, allow bridge_mode_init_regs to override */ sd->sensor_width = sd->gspca_dev.width; @@ -3880,50 +4091,46 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_mode_init_regs(sd); + ov511_mode_init_regs(sd); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ret = ov518_mode_init_regs(sd); + ov518_mode_init_regs(sd); break; case BRIDGE_OV519: - ret = ov519_mode_init_regs(sd); + ov519_mode_init_regs(sd); break; /* case BRIDGE_OVFX2: nothing to do */ case BRIDGE_W9968CF: - ret = w9968cf_mode_init_regs(sd); + w9968cf_mode_init_regs(sd); break; } - if (ret < 0) - goto out; - - ret = set_ov_sensor_window(sd); - if (ret < 0) - goto out; - - setcontrast(gspca_dev); - setbrightness(gspca_dev); - setcolors(gspca_dev); - sethvflip(gspca_dev); - setautobright(gspca_dev); - setfreq_i(sd); + + set_ov_sensor_window(sd); + + if (!(sd->gspca_dev.ctrl_dis & (1 << CONTRAST))) + setcontrast(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) + setbrightness(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) + setcolors(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) + sethvflip(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) + setautobright(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) + setfreq_i(sd); /* Force clear snapshot state in case the snapshot button was pressed while we weren't streaming */ sd->snapshot_needs_reset = 1; sd_reset_snapshot(gspca_dev); - sd->snapshot_pressed = 0; sd->first_frame = 3; - ret = ov51x_restart(sd); - if (ret < 0) - goto out; + ov51x_restart(sd); ov51x_led_control(sd, 1); - return 0; -out: - PDEBUG(D_ERR, "camera start error:%d", ret); - return ret; + return gspca_dev->usb_err; } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -3938,8 +4145,21 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!sd->gspca_dev.present) + return; if (sd->bridge == BRIDGE_W9968CF) w9968cf_stop0(sd); + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + /* If the last button state is pressed, release it now! */ + if (sd->snapshot_pressed) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + sd->snapshot_pressed = 0; + } +#endif + if (sd->bridge == BRIDGE_OV519) + reg_w(sd, OV519_R57_SNAPSHOT, 0x23); } static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) @@ -4160,6 +4380,22 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals brit_7660[][7] = { + {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, + {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, + {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, + {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, + {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, + {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, + {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, + {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, + {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, + {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, + {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, + {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, + {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, + {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} + }; val = sd->ctrls[BRIGHTNESS].val; switch (sd->sensor) { @@ -4179,10 +4415,14 @@ static void setbrightness(struct gspca_dev *gspca_dev) if (!sd->ctrls[AUTOBRIGHT].val) i2c_w(sd, OV7610_REG_BRT, val); break; + case SEN_OV7660: + write_i2c_regvals(sd, brit_7660[val], + ARRAY_SIZE(brit_7660[0])); + break; case SEN_OV7670: /*win trace - * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ - i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); + * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ + i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val)); break; } } @@ -4191,6 +4431,64 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals contrast_7660[][31] = { + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, + {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, + {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, + {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, + {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, + {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, + {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, + {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, + {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, + {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, + {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, + {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, + {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, + {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, + {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, + {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, + {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, + {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, + {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, + {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, + {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, + {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, + {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, + {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, + {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, + {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, + {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, + {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, + {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, + {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, + {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, + {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, + {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, + {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, + {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, + {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, + {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, + {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, + {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, + {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, + {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, + {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, + {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, + {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, + {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, + {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, + {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, + {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, + {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, + }; val = sd->ctrls[CONTRAST].val; switch (sd->sensor) { @@ -4203,7 +4501,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); break; case SEN_OV8610: { - static const __u8 ctab[] = { + static const u8 ctab[] = { 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f }; @@ -4213,7 +4511,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) } case SEN_OV7620: case SEN_OV7620AE: { - static const __u8 ctab[] = { + static const u8 ctab[] = { 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff }; @@ -4222,9 +4520,13 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w(sd, 0x64, ctab[val >> 4]); break; } + case SEN_OV7660: + write_i2c_regvals(sd, contrast_7660[val], + ARRAY_SIZE(contrast_7660[0])); + break; case SEN_OV7670: /* check that this isn't just the same as ov7610 */ - i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); + i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); break; } } @@ -4233,6 +4535,18 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals colors_7660[][6] = { + {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, + {0x53, 0x19}, {0x54, 0x23}}, + {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, + {0x53, 0x2c}, {0x54, 0x3e}}, + {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, + {0x53, 0x40}, {0x54, 0x59}}, + {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, + {0x53, 0x53}, {0x54, 0x73}}, + {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, + {0x53, 0x66}, {0x54, 0x8e}}, + }; val = sd->ctrls[COLORS].val; switch (sd->sensor) { @@ -4256,6 +4570,10 @@ static void setcolors(struct gspca_dev *gspca_dev) case SEN_OV7648: i2c_w(sd, OV7610_REG_SAT, val & 0xf0); break; + case SEN_OV7660: + write_i2c_regvals(sd, colors_7660[val], + ARRAY_SIZE(colors_7660[0])); + break; case SEN_OV7670: /* supported later once I work out how to do it * transparently fail now! */ @@ -4268,38 +4586,31 @@ static void setautobright(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 || - sd->sensor == SEN_OV7670 || - sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - return; - i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); } static void setfreq_i(struct sd *sd) { - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - return; - - if (sd->sensor == SEN_OV7670) { + if (sd->sensor == SEN_OV7660 + || sd->sensor == SEN_OV7670) { switch (sd->ctrls[FREQ].val) { case 0: /* Banding filter disabled */ - i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT); + i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); break; case 1: /* 50 hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18); + i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18); break; case 2: /* 60 hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18); + i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18); break; - case 3: /* Auto hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + case 3: /* Auto hz - ov7670 only */ + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO, + i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO, 0x18); break; } @@ -4443,14 +4754,14 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4064), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4068), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0155), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, @@ -4464,7 +4775,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, - {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, + {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 }, {} }; diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 88ef03f6235..0edf93973b1 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1243,34 +1243,26 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, } /* get stream parameters (framerate) */ -static int sd_get_streamparm(struct gspca_dev *gspca_dev, +static void sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - cp->capability |= V4L2_CAP_TIMEPERFRAME; tpf->numerator = 1; tpf->denominator = sd->frame_rate; - - return 0; } /* set stream parameters (framerate) */ -static int sd_set_streamparm(struct gspca_dev *gspca_dev, +static void sd_set_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - /* Set requested framerate */ sd->frame_rate = tpf->denominator / tpf->numerator; if (gspca_dev->streaming) @@ -1279,8 +1271,6 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, /* Return the actual framerate */ tpf->numerator = 1; tpf->denominator = sd->frame_rate; - - return 0; } /* sub-driver description */ diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c index e831f0d280e..c5244b4b477 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/video/gspca/ov534_9.c @@ -945,7 +945,6 @@ static void setautogain(struct gspca_dev *gspca_dev) u8 val; /*fixme: should adjust agc/awb/aec by different controls */ - val = sd->autogain; val = sccb_read(gspca_dev, 0x13); /* com8 */ sccb_write(gspca_dev, 0xff, 0x00); if (sd->autogain) diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 15e97fa4c33..96f9986305b 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -162,7 +162,7 @@ static const __u8 pac207_sensor_init[][8] = { {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84}, {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, - {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, + {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00}, }; static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, @@ -228,7 +228,7 @@ static int sd_config(struct gspca_dev *gspca_dev, idreg[0] = pac207_read_reg(gspca_dev, 0x0000); idreg[1] = pac207_read_reg(gspca_dev, 0x0001); - idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4); + idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4); idreg[1] = idreg[1] & 0x0f; PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X", idreg[0], idreg[1]); diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 55fbea7381b..2700975abce 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -393,7 +393,7 @@ static const __u8 page3_7302[] = { static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, - const char *buffer, int len) + const u8 *buffer, int len) { int ret; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 7657b43b320..6820f5d58b1 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -261,7 +261,7 @@ static const __u8 page4_7311[] = { static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, - const char *buffer, int len) + const u8 *buffer, int len) { int ret; diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 6b155ae3a74..cb08d00d0a3 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -33,6 +33,14 @@ MODULE_LICENSE("GPL"); #define MODULE_NAME "sn9c20x" +/* + * Pixel format private data + */ +#define SCALE_MASK 0x0f +#define SCALE_160x120 0 +#define SCALE_320x240 1 +#define SCALE_640x480 2 +#define SCALE_1280x1024 3 #define MODE_RAW 0x10 #define MODE_JPEG 0x20 #define MODE_SXGA 0x80 @@ -348,47 +356,47 @@ static const struct v4l2_pix_format vga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0 | MODE_JPEG}, + .priv = SCALE_160x120 | MODE_JPEG}, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_RAW}, + .priv = SCALE_160x120 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 240 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, + .priv = SCALE_160x120}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1 | MODE_JPEG}, + .priv = SCALE_320x240 | MODE_JPEG}, {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, + .priv = SCALE_320x240 | MODE_RAW}, {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 480 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, + .priv = SCALE_320x240}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2 | MODE_JPEG}, + .priv = SCALE_640x480 | MODE_JPEG}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, + .priv = SCALE_640x480 | MODE_RAW}, {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 960 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, + .priv = SCALE_640x480}, }; static const struct v4l2_pix_format sxga_mode[] = { @@ -396,52 +404,75 @@ static const struct v4l2_pix_format sxga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0 | MODE_JPEG}, + .priv = SCALE_160x120 | MODE_JPEG}, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_RAW}, + .priv = SCALE_160x120 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 240 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, + .priv = SCALE_160x120}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1 | MODE_JPEG}, + .priv = SCALE_320x240 | MODE_JPEG}, {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, + .priv = SCALE_320x240 | MODE_RAW}, {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 480 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, + .priv = SCALE_320x240}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2 | MODE_JPEG}, + .priv = SCALE_640x480 | MODE_JPEG}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, + .priv = SCALE_640x480 | MODE_RAW}, {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 960 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, + .priv = SCALE_640x480}, {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3 | MODE_RAW | MODE_SXGA}, + .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, +}; + +static const struct v4l2_pix_format mono_mode[] = { + {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_160x120 | MODE_RAW}, + {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_320x240 | MODE_RAW}, + {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_640x480 | MODE_RAW}, + {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, }; static const s16 hsv_red_x[] = { @@ -1029,16 +1060,19 @@ static struct i2c_reg_u16 mt9v011_init[] = { }; static struct i2c_reg_u16 mt9m001_init[] = { - {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e}, - {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501}, - {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, - {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000}, - {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000}, - {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, - {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2}, - {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003}, - {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a}, - {0x2e, 0x0029}, {0x07, 0x0002}, + {0x0d, 0x0001}, + {0x0d, 0x0000}, + {0x04, 0x0500}, /* hres = 1280 */ + {0x03, 0x0400}, /* vres = 1024 */ + {0x20, 0x1100}, + {0x06, 0x0010}, + {0x2b, 0x0024}, + {0x2e, 0x0024}, + {0x35, 0x0024}, + {0x2d, 0x0020}, + {0x2c, 0x0020}, + {0x09, 0x0ad4}, + {0x35, 0x0057}, }; static struct i2c_reg_u16 mt9m111_init[] = { @@ -1224,8 +1258,17 @@ static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) static int ov9650_init_sensor(struct gspca_dev *gspca_dev) { int i; + u16 id; struct sd *sd = (struct sd *) gspca_dev; + if (i2c_r2(gspca_dev, 0x1c, &id) < 0) + return -EINVAL; + + if (id != 0x7fa2) { + err("sensor id for ov9650 doesn't match (0x%04x)", id); + return -ENODEV; + } + for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { if (i2c_w1(gspca_dev, ov9650_init[i].reg, ov9650_init[i].val) < 0) { @@ -1425,6 +1468,25 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; + u16 id; + + if (i2c_r2(gspca_dev, 0x00, &id) < 0) + return -EINVAL; + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (id) { + case 0x8411: + case 0x8421: + info("MT9M001 color sensor detected"); + break; + case 0x8431: + info("MT9M001 mono sensor detected"); + break; + default: + err("No MT9M001 chip detected, ID = %x\n", id); + return -ENODEV; + } + for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { if (i2c_w2(gspca_dev, mt9m001_init[i].reg, mt9m001_init[i].val) < 0) { @@ -1434,8 +1496,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) } /* disable hflip and vflip */ gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); - sd->hstart = 2; - sd->vstart = 2; + sd->hstart = 1; + sd->vstart = 1; return 0; } @@ -1977,6 +2039,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sxga_mode; cam->nmodes = ARRAY_SIZE(sxga_mode); break; + case SENSOR_MT9M001: + cam->cam_mode = mono_mode; + cam->nmodes = ARRAY_SIZE(mono_mode); + break; default: cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); @@ -2075,7 +2141,6 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MT9M001: if (mt9m001_init_sensor(gspca_dev) < 0) return -ENODEV; - info("MT9M001 sensor detected"); break; case SENSOR_HV7131R: if (hv7131r_init_sensor(gspca_dev) < 0) @@ -2173,22 +2238,22 @@ static int sd_start(struct gspca_dev *gspca_dev) else if (mode & MODE_JPEG) fmt = 0x2c; else - fmt = 0x2f; + fmt = 0x2f; /* YUV 420 */ - switch (mode & 0x0f) { - case 3: + switch (mode & SCALE_MASK) { + case SCALE_1280x1024: scale = 0xc0; info("Set 1280x1024"); break; - case 2: + case SCALE_640x480: scale = 0x80; info("Set 640x480"); break; - case 1: + case SCALE_320x240: scale = 0x90; info("Set 320x240"); break; - case 0: + case SCALE_160x120: scale = 0xa0; info("Set 160x120"); break; diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 706f96f9265..73504a3f87b 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -56,6 +56,8 @@ struct sd { int prev_avg_lum; int exp_too_low_cnt; int exp_too_high_cnt; + int header_read; + u8 header[12]; /* Header without sof marker */ unsigned short exposure; unsigned char gain; @@ -71,14 +73,15 @@ struct sd { #define BRIDGE_103 1 __u8 sensor; /* Type of image sensor chip */ -#define SENSOR_HV7131R 0 -#define SENSOR_OV6650 1 -#define SENSOR_OV7630 2 -#define SENSOR_PAS106 3 -#define SENSOR_PAS202 4 -#define SENSOR_TAS5110C 5 -#define SENSOR_TAS5110D 6 -#define SENSOR_TAS5130CXX 7 +#define SENSOR_HV7131D 0 +#define SENSOR_HV7131R 1 +#define SENSOR_OV6650 2 +#define SENSOR_OV7630 3 +#define SENSOR_PAS106 4 +#define SENSOR_PAS202 5 +#define SENSOR_TAS5110C 6 +#define SENSOR_TAS5110D 7 +#define SENSOR_TAS5130CXX 8 __u8 reg11; }; @@ -303,14 +306,29 @@ static const struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; -static const __u8 initHv7131[] = { +static const __u8 initHv7131d[] = { + 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, + 0x28, 0x1e, 0x60, 0x8e, 0x42, + 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c +}; +static const __u8 hv7131d_sensor_init[][8] = { + {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */ + {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */ +}; + +static const __u8 initHv7131r[] = { 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x28, 0x1e, 0x60, 0x8a, 0x20, 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c }; -static const __u8 hv7131_sensor_init[][8] = { +static const __u8 hv7131r_sensor_init[][8] = { {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10}, {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10}, @@ -340,7 +358,7 @@ static const __u8 ov6650_sensor_init[][8] = { * but blue wont be there. Avoid this data ... */ {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */ {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, - {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10}, + {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10}, /* Enable rgb brightness control */ {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10}, /* HDG: Note windows uses the line below, which sets both register 0x60 @@ -505,7 +523,7 @@ static const __u8 pas202_sensor_init[][8] = { {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, - {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, + {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10}, {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, @@ -551,7 +569,8 @@ static const __u8 tas5130_sensor_init[][8] = { }; static struct sensor_data sensor_data[] = { -SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), +SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, F_GAIN, 0, 0x21), @@ -701,7 +720,18 @@ static void setsensorgain(struct gspca_dev *gspca_dev) unsigned char gain = sd->gain; switch (sd->sensor) { + case SENSOR_HV7131D: { + __u8 i2c[] = + {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; + i2c[3] = 0x3f - (sd->gain / 4); + i2c[4] = 0x3f - (sd->gain / 4); + i2c[5] = 0x3f - (sd->gain / 4); + + if (i2c_w(gspca_dev, i2c) < 0) + goto err; + break; + } case SENSOR_TAS5110C: case SENSOR_TAS5110D: { __u8 i2c[] = @@ -788,6 +818,23 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; switch (sd->sensor) { + case SENSOR_HV7131D: { + /* Note the datasheet wrongly says line mode exposure uses reg + 0x26 and 0x27, testing has shown 0x25 + 0x26 */ + __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; + /* The HV7131D's exposure goes from 0 - 65535, we scale our + exposure of 0-1023 to 0-6138. There are 2 reasons for this: + 1) This puts our exposure knee of 200 at approx the point + where the framerate starts dropping + 2) At 6138 the framerate has already dropped to 2 fps, + going any lower makes little sense */ + __u16 reg = sd->exposure * 6; + i2c[3] = reg >> 8; + i2c[4] = reg & 0xff; + if (i2c_w(gspca_dev, i2c) != 0) + goto err; + break; + } case SENSOR_TAS5110C: case SENSOR_TAS5110D: { /* register 19's high nibble contains the sn9c10x clock divider @@ -1177,13 +1224,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) sd_init(gspca_dev); } -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ +static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) { - int i; struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; + int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12; /* frames start with: * ff ff 00 c4 c4 96 synchro @@ -1194,58 +1238,84 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * ll mm brightness sum outside auto exposure * (xx xx xx xx xx) audio values for snc103 */ - if (len > 6 && len < 24) { - for (i = 0; i < len - 6; i++) { - if (data[0 + i] == 0xff - && data[1 + i] == 0xff - && data[2 + i] == 0x00 - && data[3 + i] == 0xc4 - && data[4 + i] == 0xc4 - && data[5 + i] == 0x96) { /* start of frame */ - int lum = -1; - int pkt_type = LAST_PACKET; - int fr_h_sz = (sd->bridge == BRIDGE_103) ? - 18 : 12; - - if (len - i < fr_h_sz) { - PDEBUG(D_STREAM, "packet too short to" - " get avg brightness"); - } else if (sd->bridge == BRIDGE_103) { - lum = data[i + 9] + - (data[i + 10] << 8); - } else { - lum = data[i + 8] + (data[i + 9] << 8); - } - /* When exposure changes midway a frame we - get a lum of 0 in this case drop 2 frames - as the frames directly after an exposure - change have an unstable image. Sometimes lum - *really* is 0 (cam used in low light with - low exposure setting), so do not drop frames - if the previous lum was 0 too. */ - if (lum == 0 && sd->prev_avg_lum != 0) { - lum = -1; - sd->frames_to_drop = 2; - sd->prev_avg_lum = 0; - } else - sd->prev_avg_lum = lum; - atomic_set(&sd->avg_lum, lum); - - if (sd->frames_to_drop) { - sd->frames_to_drop--; - pkt_type = DISCARD_PACKET; - } - - gspca_frame_add(gspca_dev, pkt_type, - NULL, 0); - data += i + fr_h_sz; - len -= i + fr_h_sz; - gspca_frame_add(gspca_dev, FIRST_PACKET, - data, len); - return; + for (i = 0; i < len; i++) { + switch (sd->header_read) { + case 0: + if (data[i] == 0xff) + sd->header_read++; + break; + case 1: + if (data[i] == 0xff) + sd->header_read++; + else + sd->header_read = 0; + break; + case 2: + if (data[i] == 0x00) + sd->header_read++; + else if (data[i] != 0xff) + sd->header_read = 0; + break; + case 3: + if (data[i] == 0xc4) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + case 4: + if (data[i] == 0xc4) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + case 5: + if (data[i] == 0x96) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + default: + sd->header[sd->header_read - 6] = data[i]; + sd->header_read++; + if (sd->header_read == header_size) { + sd->header_read = 0; + return data + i + 1; } } } + return NULL; +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0; + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + u8 *sof; + + sof = find_sof(gspca_dev, data, len); + if (sof) { + if (sd->bridge == BRIDGE_103) { + fr_h_sz = 18; + lum_offset = 3; + } else { + fr_h_sz = 12; + lum_offset = 2; + } + + len_after_sof = len - (sof - data); + len = (sof - data) - fr_h_sz; + if (len < 0) + len = 0; + } if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { /* In raw mode we sometimes get some garbage after the frame @@ -1259,6 +1329,33 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + + if (sof) { + int lum = sd->header[lum_offset] + + (sd->header[lum_offset + 1] << 8); + + /* When exposure changes midway a frame we + get a lum of 0 in this case drop 2 frames + as the frames directly after an exposure + change have an unstable image. Sometimes lum + *really* is 0 (cam used in low light with + low exposure setting), so do not drop frames + if the previous lum was 0 too. */ + if (lum == 0 && sd->prev_avg_lum != 0) { + lum = -1; + sd->frames_to_drop = 2; + sd->prev_avg_lum = 0; + } else + sd->prev_avg_lum = lum; + atomic_set(&sd->avg_lum, lum); + + if (sd->frames_to_drop) + sd->frames_to_drop--; + else + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + + gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof); + } } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) @@ -1431,9 +1528,7 @@ static const struct sd_desc sd_desc = { static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ -#endif {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, @@ -1444,9 +1539,12 @@ static const struct usb_device_id device_table[] __devinitconst = { #endif {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, + {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)}, + /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */ {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, + /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 330dadc0010..2d0bb17a30a 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -63,7 +63,10 @@ struct sd { #define QUALITY_DEF 80 u8 jpegqual; /* webcam quality */ + u8 reg01; + u8 reg17; u8 reg18; + u8 flags; s8 ag_cnt; #define AG_CNT_START 13 @@ -96,6 +99,22 @@ enum sensors { SENSOR_SP80708, }; +/* device flags */ +#define PDN_INV 1 /* inverse pin S_PWR_DN / sn_xxx tables */ + +/* sn9c1xx definitions */ +/* register 0x01 */ +#define S_PWR_DN 0x01 /* sensor power down */ +#define S_PDN_INV 0x02 /* inverse pin S_PWR_DN */ +#define V_TX_EN 0x04 /* video transfer enable */ +#define LED 0x08 /* output to pin LED */ +#define SCL_SEL_OD 0x20 /* open-drain mode */ +#define SYS_SEL_48M 0x40 /* system clock 0: 24MHz, 1: 48MHz */ +/* register 0x17 */ +#define MCK_SIZE_MASK 0x1f /* sensor master clock */ +#define SEN_CLK_EN 0x20 /* enable sensor clock */ +#define DEF_EN 0x80 /* defect pixel by 0: soft, 1: hard */ + /* V4L2 controls supported by the driver */ static void setbrightness(struct gspca_dev *gspca_dev); static void setcontrast(struct gspca_dev *gspca_dev); @@ -1579,22 +1598,22 @@ static void i2c_w_seq(struct gspca_dev *gspca_dev, } } +/* check the ID of the hv7131 sensor */ +/* this sequence is needed because it activates the sensor */ static void hv7131r_probe(struct gspca_dev *gspca_dev) { - i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ + i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); - reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ + reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ msleep(10); - i2c_r(gspca_dev, 0, 5); /* read sensor id */ - if (gspca_dev->usb_buf[0] == 0x02 + i2c_r(gspca_dev, 0, 5); /* read sensor id */ + if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */ && gspca_dev->usb_buf[1] == 0x09 - && gspca_dev->usb_buf[2] == 0x01 - && gspca_dev->usb_buf[3] == 0x00 - && gspca_dev->usb_buf[4] == 0x00) { - PDEBUG(D_PROBE, "Sensor sn9c102P HV7131R found"); + && gspca_dev->usb_buf[2] == 0x01) { + PDEBUG(D_PROBE, "Sensor HV7131R found"); return; } - PDEBUG(D_PROBE, "Sensor 0x%02x 0x%02x 0x%02x - sn9c102P not found", + warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x", gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], gspca_dev->usb_buf[2]); } @@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev) } } -static void bridge_init(struct gspca_dev *gspca_dev, - const u8 *sn9c1xx) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 reg0102[2]; - const u8 *reg9a; - static const u8 reg9a_def[] = - {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; - static const u8 reg9a_spec[] = - {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; - static const u8 regd4[] = {0x60, 0x00, 0x00}; - - /* sensor clock already enabled in sd_init */ - /* reg_w1(gspca_dev, 0xf1, 0x00); */ - reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - - /* configure gpio */ - reg0102[0] = sn9c1xx[1]; - reg0102[1] = sn9c1xx[2]; - if (gspca_dev->audio) - reg0102[1] |= 0x04; /* keep the audio connection */ - reg_w(gspca_dev, 0x01, reg0102, 2); - reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); - reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); - switch (sd->sensor) { - case SENSOR_GC0307: - case SENSOR_OV7660: - case SENSOR_PO1030: - case SENSOR_PO2030N: - case SENSOR_SOI768: - case SENSOR_SP80708: - reg9a = reg9a_spec; - break; - default: - reg9a = reg9a_def; - break; - } - reg_w(gspca_dev, 0x9a, reg9a, 6); - - reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); - - reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); - - switch (sd->sensor) { - case SENSOR_ADCM1700: - reg_w1(gspca_dev, 0x01, 0x43); - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - reg_w1(gspca_dev, 0x01, 0x42); - break; - case SENSOR_GC0307: - msleep(50); - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x22); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - msleep(50); - break; - case SENSOR_MI0360B: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x60); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_MT9V111: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x61); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_OM6802: - msleep(10); - reg_w1(gspca_dev, 0x02, 0x73); - reg_w1(gspca_dev, 0x17, 0x60); - reg_w1(gspca_dev, 0x01, 0x22); - msleep(100); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x17, 0x64); - reg_w1(gspca_dev, 0x17, 0x64); - reg_w1(gspca_dev, 0x01, 0x42); - msleep(10); - reg_w1(gspca_dev, 0x01, 0x42); - i2c_w8(gspca_dev, om6802_init0[0]); - i2c_w8(gspca_dev, om6802_init0[1]); - msleep(15); - reg_w1(gspca_dev, 0x02, 0x71); - msleep(150); - break; - case SENSOR_OV7630: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0xe2); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_OV7648: - reg_w1(gspca_dev, 0x01, 0x63); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - break; - case SENSOR_PO1030: - case SENSOR_SOI768: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_PO2030N: - case SENSOR_OV7660: - reg_w1(gspca_dev, 0x01, 0x63); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - break; - case SENSOR_SP80708: - reg_w1(gspca_dev, 0x01, 0x63); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - msleep(100); - reg_w1(gspca_dev, 0x02, 0x62); - break; - default: -/* case SENSOR_HV7131R: */ -/* case SENSOR_MI0360: */ -/* case SENSOR_MO4000: */ - reg_w1(gspca_dev, 0x01, 0x43); - reg_w1(gspca_dev, 0x17, 0x61); - reg_w1(gspca_dev, 0x01, 0x42); - if (sd->sensor == SENSOR_HV7131R) - hv7131r_probe(gspca_dev); - break; - } -} - /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; sd->bridge = id->driver_info >> 16; - sd->sensor = id->driver_info; + sd->sensor = id->driver_info >> 8; + sd->flags = id->driver_info; cam = &gspca_dev->cam; if (sd->sensor == SENSOR_ADCM1700) { @@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev) /* setup a selector by bridge */ reg_w1(gspca_dev, 0xf1, 0x01); reg_r(gspca_dev, 0x00, 1); - reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]); + reg_w1(gspca_dev, 0xf1, 0x00); reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */ regF1 = gspca_dev->usb_buf[0]; if (gspca_dev->usb_err < 0) @@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - u8 reg1, reg17; + u8 reg01, reg17; + u8 reg0102[2]; const u8 *sn9c1xx; const u8 (*init)[8]; + const u8 *reg9a; int mode; + static const u8 reg9a_def[] = + {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; + static const u8 reg9a_spec[] = + {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; + static const u8 regd4[] = {0x60, 0x00, 0x00}; static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; static const u8 CA_adcm1700[] = @@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev) /* initialize the bridge */ sn9c1xx = sn_tb[sd->sensor]; - bridge_init(gspca_dev, sn9c1xx); + + /* sensor clock already enabled in sd_init */ + /* reg_w1(gspca_dev, 0xf1, 0x00); */ + reg01 = sn9c1xx[1]; + if (sd->flags & PDN_INV) + reg01 ^= S_PDN_INV; /* power down inverted */ + reg_w1(gspca_dev, 0x01, reg01); + + /* configure gpio */ + reg0102[0] = reg01; + reg0102[1] = sn9c1xx[2]; + if (gspca_dev->audio) + reg0102[1] |= 0x04; /* keep the audio connection */ + reg_w(gspca_dev, 0x01, reg0102, 2); + reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); + reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); + switch (sd->sensor) { + case SENSOR_GC0307: + case SENSOR_OV7660: + case SENSOR_PO1030: + case SENSOR_PO2030N: + case SENSOR_SOI768: + case SENSOR_SP80708: + reg9a = reg9a_spec; + break; + default: + reg9a = reg9a_def; + break; + } + reg_w(gspca_dev, 0x9a, reg9a, 6); + + reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); + + reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); + + reg17 = sn9c1xx[0x17]; + switch (sd->sensor) { + case SENSOR_GC0307: + msleep(50); /*fixme: is it useful? */ + break; + case SENSOR_OM6802: + msleep(10); + reg_w1(gspca_dev, 0x02, 0x73); + reg17 |= SEN_CLK_EN; + reg_w1(gspca_dev, 0x17, reg17); + reg_w1(gspca_dev, 0x01, 0x22); + msleep(100); + reg01 = SCL_SEL_OD | S_PDN_INV; + reg17 &= MCK_SIZE_MASK; + reg17 |= 0x04; /* clock / 4 */ + break; + } + reg01 |= SYS_SEL_48M; + reg_w1(gspca_dev, 0x01, reg01); + reg17 |= SEN_CLK_EN; + reg_w1(gspca_dev, 0x17, reg17); + reg01 &= ~S_PWR_DN; /* sensor power on */ + reg_w1(gspca_dev, 0x01, reg01); + reg01 &= ~SYS_SEL_48M; + reg_w1(gspca_dev, 0x01, reg01); + + switch (sd->sensor) { + case SENSOR_HV7131R: + hv7131r_probe(gspca_dev); /*fixme: is it useful? */ + break; + case SENSOR_OM6802: + msleep(10); + reg_w1(gspca_dev, 0x01, reg01); + i2c_w8(gspca_dev, om6802_init0[0]); + i2c_w8(gspca_dev, om6802_init0[1]); + msleep(15); + reg_w1(gspca_dev, 0x02, 0x71); + msleep(150); + break; + case SENSOR_SP80708: + msleep(100); + reg_w1(gspca_dev, 0x02, 0x62); + break; + } /* initialize the sensor */ i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); @@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { - case SENSOR_GC0307: - reg17 = 0xa2; - break; - case SENSOR_MT9V111: - case SENSOR_MI0360B: - reg17 = 0xe0; - break; - case SENSOR_ADCM1700: - case SENSOR_OV7630: - reg17 = 0xe2; - break; - case SENSOR_OV7648: - reg17 = 0x20; - break; - case SENSOR_OV7660: - case SENSOR_SOI768: - reg17 = 0xa0; - break; - case SENSOR_PO1030: - case SENSOR_PO2030N: - reg17 = 0xa0; + case SENSOR_OM6802: +/* case SENSOR_OV7648: * fixme: sometimes */ break; default: - reg17 = 0x60; + reg17 |= DEF_EN; break; } reg_w1(gspca_dev, 0x17, reg17); @@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev) init = NULL; mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (mode) - reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ - else - reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ - reg17 = 0x61; /* 0x:20: enable sensor clock */ + reg01 |= SYS_SEL_48M | V_TX_EN; + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x02; /* clock / 2 */ switch (sd->sensor) { case SENSOR_ADCM1700: init = adcm1700_sensor_param1; - reg1 = 0x46; - reg17 = 0xe2; break; case SENSOR_GC0307: init = gc0307_sensor_param1; - reg17 = 0xa2; - reg1 = 0x44; + break; + case SENSOR_HV7131R: + case SENSOR_MI0360: + if (mode) + reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */ + else + reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x01; /* clock / 1 */ break; case SENSOR_MI0360B: init = mi0360b_sensor_param1; - reg1 &= ~0x02; /* don't inverse pin S_PWR_DN */ - reg17 = 0xe2; break; case SENSOR_MO4000: - if (mode) { -/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ - reg1 = 0x06; /* clk 24Mz */ - } else { - reg17 = 0x22; /* 640 MCKSIZE */ -/* reg1 = 0x06; * 640 clk 24Mz (done) */ + if (mode) { /* if 320x240 */ + reg01 &= ~SYS_SEL_48M; /* clk 24Mz */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x01; /* clock / 1 */ } break; case SENSOR_MT9V111: init = mt9v111_sensor_param1; - if (mode) { - reg1 = 0x04; /* 320 clk 48Mhz */ - } else { -/* reg1 = 0x06; * 640 clk 24Mz (done) */ - reg17 = 0xc2; - } break; case SENSOR_OM6802: init = om6802_sensor_param1; - reg17 = 0x64; /* 640 MCKSIZE */ + if (!mode) { /* if 640x480 */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x04; /* clock / 4 */ + } break; case SENSOR_OV7630: init = ov7630_sensor_param1; - reg17 = 0xe2; - reg1 = 0x44; break; case SENSOR_OV7648: init = ov7648_sensor_param1; - reg17 = 0x21; -/* reg1 = 0x42; * 42 - 46? */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x01; /* clock / 1 */ break; case SENSOR_OV7660: init = ov7660_sensor_param1; - if (sd->bridge == BRIDGE_SN9C120) { - if (mode) { /* 320x240 - 160x120 */ - reg17 = 0xa2; - reg1 = 0x44; /* 48 Mhz, video trf eneble */ - } - } else { - reg17 = 0x22; - reg1 = 0x06; /* 24 Mhz, video trf eneble - * inverse power down */ - } break; case SENSOR_PO1030: init = po1030_sensor_param1; - reg17 = 0xa2; - reg1 = 0x44; break; case SENSOR_PO2030N: init = po2030n_sensor_param1; - reg1 = 0x46; - reg17 = 0xa2; break; case SENSOR_SOI768: init = soi768_sensor_param1; - reg1 = 0x44; - reg17 = 0xa2; break; case SENSOR_SP80708: init = sp80708_sensor_param1; - if (mode) { -/*?? reg1 = 0x04; * 320 clk 48Mhz */ - } else { - reg1 = 0x46; /* 640 clk 48Mz */ - reg17 = 0xa2; - } break; } @@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev) setjpegqual(gspca_dev); reg_w1(gspca_dev, 0x17, reg17); - reg_w1(gspca_dev, 0x01, reg1); + reg_w1(gspca_dev, 0x01, reg01); + sd->reg01 = reg01; + sd->reg17 = reg17; sethvflip(gspca_dev); setbrightness(gspca_dev); @@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev) { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; static const u8 stopsoi768[] = { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; - u8 data; - const u8 *sn9c1xx; + u8 reg01; + u8 reg17; - data = 0x0b; + reg01 = sd->reg01; + reg17 = sd->reg17 & ~SEN_CLK_EN; switch (sd->sensor) { + case SENSOR_ADCM1700: case SENSOR_GC0307: - data = 0x29; + case SENSOR_PO2030N: + case SENSOR_SP80708: + reg01 |= LED; + reg_w1(gspca_dev, 0x01, reg01); + reg01 &= ~(LED | V_TX_EN); + reg_w1(gspca_dev, 0x01, reg01); +/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */ break; case SENSOR_HV7131R: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); i2c_w8(gspca_dev, stophv7131); - data = 0x2b; break; case SENSOR_MI0360: case SENSOR_MI0360B: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); +/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */ i2c_w8(gspca_dev, stopmi0360); - data = 0x29; break; - case SENSOR_OV7648: - i2c_w8(gspca_dev, stopov7648); - /* fall thru */ case SENSOR_MT9V111: - case SENSOR_OV7630: + case SENSOR_OM6802: case SENSOR_PO1030: - data = 0x29; + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); + break; + case SENSOR_OV7630: + case SENSOR_OV7648: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); + i2c_w8(gspca_dev, stopov7648); + break; + case SENSOR_OV7660: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); break; case SENSOR_SOI768: i2c_w8(gspca_dev, stopsoi768); - data = 0x29; break; } - sn9c1xx = sn_tb[sd->sensor]; - reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); - reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - reg_w1(gspca_dev, 0x01, data); + + reg01 |= SCL_SEL_OD; + reg_w1(gspca_dev, 0x01, reg01); + reg01 |= S_PWR_DN; /* sensor power down */ + reg_w1(gspca_dev, 0x01, reg01); + reg_w1(gspca_dev, 0x17, reg17); + reg01 &= ~SYS_SEL_48M; /* clock 24MHz */ + reg_w1(gspca_dev, 0x01, reg01); + reg01 |= LED; + reg_w1(gspca_dev, 0x01, reg01); /* Don't disable sensor clock as that disables the button on the cam */ /* reg_w1(gspca_dev, 0xf1, 0x01); */ } @@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ #define BS(bridge, sensor) \ .driver_info = (BRIDGE_ ## bridge << 16) \ - | SENSOR_ ## sensor + | (SENSOR_ ## sensor << 8) +#define BSF(bridge, sensor, flags) \ + .driver_info = (BRIDGE_ ## bridge << 16) \ + | (SENSOR_ ## sensor << 8) \ + | (flags) static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, #endif - {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, - {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)}, + {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)}, {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index ad73f4812c0..3a162c6d546 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -597,7 +597,7 @@ static void setgain(struct gspca_dev *gspca_dev) else if (sd->gain < 128) gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40; else - gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0; + gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xc0; gspca_dev->usb_buf[1] = 0; reg_w_buf(gspca_dev, 0x8335, 2); diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index c2e88b5303c..8ba19954385 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c @@ -301,6 +301,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x2770, 0x905c)}, {USB_DEVICE(0x2770, 0x9050)}, + {USB_DEVICE(0x2770, 0x9051)}, {USB_DEVICE(0x2770, 0x9052)}, {USB_DEVICE(0x2770, 0x913d)}, {} diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index 3e4b0b94c70..a4a98811b9e 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c @@ -687,10 +687,19 @@ static void cmos_probe(struct gspca_dev *gspca_dev) if (gspca_dev->usb_buf[0] != 0) break; } - if (i >= ARRAY_SIZE(probe_order)) + if (i >= ARRAY_SIZE(probe_order)) { err("Unknown sensor"); - else - sd->sensor = probe_order[i]; + gspca_dev->usb_err = -EINVAL; + return; + } + sd->sensor = probe_order[i]; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV9630: + err("Sensor %s not yet treated", sensor_tb[sd->sensor].name); + gspca_dev->usb_err = -EINVAL; + break; + } } static void mt9v111_init(struct gspca_dev *gspca_dev) @@ -867,6 +876,9 @@ static int sd_init(struct gspca_dev *gspca_dev) */ reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); + if (gspca_dev->usb_err < 0) + return gspca_dev->usb_err; + /* it returns: * 03 00 12 93 0b f6 c9 00 live! ultra * 03 00 07 93 0b f6 ca 00 live! ultra for notebook @@ -900,15 +912,15 @@ static int sd_init(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_MI0360) { /* no sensor probe for icam tracer */ - if (gspca_dev->usb_buf[5] == 0xf6) /* if CMOS */ + if (gspca_dev->usb_buf[5] == 0xf6) /* if ccd */ sd->sensor = SENSOR_ICX098BQ; else cmos_probe(gspca_dev); } - - PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); - - global_init(sd, 1); + if (gspca_dev->usb_err >= 0) { + PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); + global_init(sd, 1); + } return gspca_dev->usb_err; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 086de44a6e5..28ea4175b80 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev *gspca_dev) static int stv06xx_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int err; + struct usb_host_interface *alt; + struct usb_interface *intf; + int err, packet_size; + + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) { + PDEBUG(D_ERR, "Couldn't get altsetting"); + return -EIO; + } + + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); + if (err < 0) + return err; /* Prepare the sensor for start */ err = sd->sensor->start(sd); @@ -282,6 +296,43 @@ out: return (err < 0) ? err : 0; } +static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) +{ + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = + cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); + + return 0; +} + +static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) +{ + int ret, packet_size, min_packet_size; + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; + if (packet_size <= min_packet_size) + return -EIO; + + packet_size -= 100; + if (packet_size < min_packet_size) + packet_size = min_packet_size; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); + + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); + if (ret < 0) + PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret); + + return ret; +} + static void stv06xx_stopN(struct gspca_dev *gspca_dev) { int err; @@ -349,7 +400,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, } /* First byte seem to be 02=data 2nd byte is unknown??? */ - if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200) + if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200) goto frame_data; switch (id) { @@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = { .start = stv06xx_start, .stopN = stv06xx_stopN, .pkt_scan = stv06xx_pkt_scan, + .isoc_init = stv06xx_isoc_init, + .isoc_nego = stv06xx_isoc_nego, #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) .int_pkt_scan = sd_int_pkt_scan, #endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h index cf3d0ccc112..b538dce96f7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h @@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, + /* FIXME (see if we can lower min_packet_size, needs testing, and also + adjusting framerate when the bandwidth gets lower) */ + .min_packet_size = { 847 }, + .max_packet_size = { 847 }, + .init = hdcs_init, .probe = hdcs_probe_1x00, .start = hdcs_start, @@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, + /* FIXME (see if we can lower min_packet_size, needs testing, and also + adjusting framerate when the bandwidthm gets lower) */ + .min_packet_size = { 847 }, + .max_packet_size = { 847 }, + .init = hdcs_init, .probe = hdcs_probe_1020, .start = hdcs_start, @@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] = { {STV_REG04, 0x07}, {STV_SCAN_RATE, 0x20}, - {STV_ISO_SIZE_L, 847}, {STV_Y_CTRL, 0x01}, {STV_X_CTRL, 0x0a} }; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c index 285221e6b39..ac47b4c9438 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c @@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd) static int pb0100_start(struct sd *sd) { - int err; + int err, packet_size, max_packet_size; + struct usb_host_interface *alt; + struct usb_interface *intf; struct cam *cam = &sd->gspca_dev.cam; s32 *sensor_settings = sd->sensor_priv; u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv; + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + + /* If we don't have enough bandwidth use a lower framerate */ + max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode]; + if (packet_size < max_packet_size) + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); + else + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1)); + /* Setup sensor window */ if (mode & PB0100_CROP_TO_VGA) { stv06xx_write_sensor(sd, PB_RSTART, 30); @@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd) stv06xx_write_bridge(sd, STV_REG03, 0x45); stv06xx_write_bridge(sd, STV_REG04, 0x07); - /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */ - stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847); - /* Scan/timing for the sensor */ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); stv06xx_write_sensor(sd, PB_CFILLIN, 14); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h index 4de4fa5ebc5..757de246dc7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h @@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = { .i2c_addr = 0xba, .i2c_len = 2, + .min_packet_size = { 635, 847 }, + .max_packet_size = { 847, 923 }, + .init = pb0100_init, .probe = pb0100_probe, .start = pb0100_start, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h index 934b9cebc1a..fb229d8ded5 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h @@ -53,6 +53,10 @@ struct stv06xx_sensor { /* length of an i2c word */ u8 i2c_len; + /* Isoc packet size (per mode) */ + int min_packet_size[4]; + int max_packet_size[4]; + /* Probes if the sensor is connected */ int (*probe)(struct sd *sd); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index 3af53264a36..8a456de4970 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -28,6 +28,20 @@ #include "stv06xx_st6422.h" +/* controls */ +enum e_ctrl { + BRIGHTNESS, + CONTRAST, + GAIN, + EXPOSURE, + NCTRLS /* number of controls */ +}; + +/* sensor settings */ +struct st6422_settings { + struct gspca_ctrl ctrls[NCTRLS]; +}; + static struct v4l2_pix_format st6422_mode[] = { /* Note we actually get 124 lines of data, of which we skip the 4st 4 as they are garbage */ @@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mode[] = { }, }; -static const struct ctrl st6422_ctrl[] = { -#define BRIGHTNESS_IDX 0 - { +/* V4L2 controls supported by the driver */ +static void st6422_set_brightness(struct gspca_dev *gspca_dev); +static void st6422_set_contrast(struct gspca_dev *gspca_dev); +static void st6422_set_gain(struct gspca_dev *gspca_dev); +static void st6422_set_exposure(struct gspca_dev *gspca_dev); + +static const struct ctrl st6422_ctrl[NCTRLS] = { +[BRIGHTNESS] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 3 }, - .set = st6422_set_brightness, - .get = st6422_get_brightness + .set_control = st6422_set_brightness }, -#define CONTRAST_IDX 1 - { +[CONTRAST] = { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 11 }, - .set = st6422_set_contrast, - .get = st6422_get_contrast + .set_control = st6422_set_contrast }, -#define GAIN_IDX 2 - { +[GAIN] = { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 64 }, - .set = st6422_set_gain, - .get = st6422_get_gain + .set_control = st6422_set_gain }, -#define EXPOSURE_IDX 3 - { +[EXPOSURE] = { { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Exposure", .minimum = 0, - .maximum = 1023, +#define EXPOSURE_MAX 1023 + .maximum = EXPOSURE_MAX, .step = 1, .default_value = 256 }, - .set = st6422_set_exposure, - .get = st6422_get_exposure + .set_control = st6422_set_exposure }, }; static int st6422_probe(struct sd *sd) { - int i; - s32 *sensor_settings; + struct st6422_settings *sensor_settings; if (sd->bridge != BRIDGE_ST6422) return -ENODEV; info("st6422 sensor detected"); - sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32), - GFP_KERNEL); + sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL); if (!sensor_settings) return -ENOMEM; sd->gspca_dev.cam.cam_mode = st6422_mode; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); + sd->gspca_dev.cam.ctrls = sensor_settings->ctrls; sd->desc.ctrls = st6422_ctrl; sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); sd->sensor_priv = sensor_settings; - for (i = 0; i < sd->desc.nctrls; i++) - sensor_settings[i] = st6422_ctrl[i].qctrl.default_value; - return 0; } @@ -151,11 +160,11 @@ static int st6422_init(struct sd *sd) { STV_ISO_ENABLE, 0x00 }, /* disable capture */ { 0x1436, 0x00 }, { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ - { 0x143a, 0xF9 }, /* 0x00-0x0F contrast */ + { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */ { 0x0509, 0x38 }, /* R */ { 0x050a, 0x38 }, /* G */ { 0x050b, 0x38 }, /* B */ - { 0x050c, 0x2A }, + { 0x050c, 0x2a }, { 0x050d, 0x01 }, @@ -213,7 +222,6 @@ static int st6422_init(struct sd *sd) { 0x150e, 0x8e }, { 0x150f, 0x37 }, { 0x15c0, 0x00 }, - { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */ { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */ @@ -235,91 +243,92 @@ static void st6422_disconnect(struct sd *sd) kfree(sd->sensor_priv); } -static int st6422_start(struct sd *sd) +static int setbrightness(struct sd *sd) { - int err, packet_size; - struct cam *cam = &sd->gspca_dev.cam; - s32 *sensor_settings = sd->sensor_priv; - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - err("Couldn't get altsetting"); - return -EIO; - } + struct st6422_settings *sensor_settings = sd->sensor_priv; - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - err = stv06xx_write_bridge(sd, 0x15c1, packet_size); - if (err < 0) - return err; + /* val goes from 0 -> 31 */ + return stv06xx_write_bridge(sd, 0x1432, + sensor_settings->ctrls[BRIGHTNESS].val); +} - if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) - err = stv06xx_write_bridge(sd, 0x1505, 0x0f); - else - err = stv06xx_write_bridge(sd, 0x1505, 0x02); - if (err < 0) - return err; +static int setcontrast(struct sd *sd) +{ + struct st6422_settings *sensor_settings = sd->sensor_priv; + + /* Val goes from 0 -> 15 */ + return stv06xx_write_bridge(sd, 0x143a, + sensor_settings->ctrls[CONTRAST].val | 0xf0); +} + +static int setgain(struct sd *sd) +{ + struct st6422_settings *sensor_settings = sd->sensor_priv; + u8 gain; + int err; + + gain = sensor_settings->ctrls[GAIN].val; - err = st6422_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); + /* Set red, green, blue, gain */ + err = stv06xx_write_bridge(sd, 0x0509, gain); if (err < 0) return err; - err = st6422_set_contrast(&sd->gspca_dev, - sensor_settings[CONTRAST_IDX]); + err = stv06xx_write_bridge(sd, 0x050a, gain); if (err < 0) return err; - err = st6422_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); + err = stv06xx_write_bridge(sd, 0x050b, gain); if (err < 0) return err; - err = st6422_set_gain(&sd->gspca_dev, - sensor_settings[GAIN_IDX]); + /* 2 mystery writes */ + err = stv06xx_write_bridge(sd, 0x050c, 0x2a); if (err < 0) return err; - PDEBUG(D_STREAM, "Starting stream"); - - return 0; + return stv06xx_write_bridge(sd, 0x050d, 0x01); } -static int st6422_stop(struct sd *sd) +static int setexposure(struct sd *sd) { - PDEBUG(D_STREAM, "Halting stream"); - - return 0; -} - -static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BRIGHTNESS_IDX]; + struct st6422_settings *sensor_settings = sd->sensor_priv; + u16 expo; + int err; - PDEBUG(D_V4L2, "Read brightness %d", *val); + expo = sensor_settings->ctrls[EXPOSURE].val; + err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff); + if (err < 0) + return err; - return 0; + return stv06xx_write_bridge(sd, 0x143e, expo >> 8); } -static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +static int st6422_start(struct sd *sd) { int err; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; + struct cam *cam = &sd->gspca_dev.cam; - sensor_settings[BRIGHTNESS_IDX] = val; + if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) + err = stv06xx_write_bridge(sd, 0x1505, 0x0f); + else + err = stv06xx_write_bridge(sd, 0x1505, 0x02); + if (err < 0) + return err; - if (!gspca_dev->streaming) - return 0; + err = setbrightness(sd); + if (err < 0) + return err; - /* val goes from 0 -> 31 */ - PDEBUG(D_V4L2, "Set brightness to %d", val); - err = stv06xx_write_bridge(sd, 0x1432, val); + err = setcontrast(sd); + if (err < 0) + return err; + + err = setexposure(sd); + if (err < 0) + return err; + + err = setgain(sd); if (err < 0) return err; @@ -328,125 +337,65 @@ static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) return (err < 0) ? err : 0; } -static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val) +static int st6422_stop(struct sd *sd) { - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[CONTRAST_IDX]; - - PDEBUG(D_V4L2, "Read contrast %d", *val); + PDEBUG(D_STREAM, "Halting stream"); return 0; } -static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_brightness(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[CONTRAST_IDX] = val; - if (!gspca_dev->streaming) - return 0; - - /* Val goes from 0 -> 15 */ - PDEBUG(D_V4L2, "Set contrast to %d\n", val); - err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val); - if (err < 0) - return err; + err = setbrightness(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; -} - -static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - - PDEBUG(D_V4L2, "Read gain %d", *val); + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return 0; + gspca_dev->usb_err = err; } -static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_contrast(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[GAIN_IDX] = val; - - if (!gspca_dev->streaming) - return 0; - - PDEBUG(D_V4L2, "Set gain to %d", val); - /* Set red, green, blue, gain */ - err = stv06xx_write_bridge(sd, 0x0509, val); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050a, val); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050b, val); - if (err < 0) - return err; - - /* 2 mystery writes */ - err = stv06xx_write_bridge(sd, 0x050c, 0x2a); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050d, 0x01); - if (err < 0) - return err; + err = setcontrast(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + + gspca_dev->usb_err = err; } -static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static void st6422_set_gain(struct gspca_dev *gspca_dev) { + int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - *val = sensor_settings[EXPOSURE_IDX]; + err = setgain(sd); - PDEBUG(D_V4L2, "Read exposure %d", *val); + /* commit settings */ + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return 0; + gspca_dev->usb_err = err; } -static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_exposure(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[EXPOSURE_IDX] = val; - if (!gspca_dev->streaming) - return 0; - - PDEBUG(D_V4L2, "Set exposure to %d\n", val); - err = stv06xx_write_bridge(sd, 0x143d, val & 0xff); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x143e, val >> 8); - if (err < 0) - return err; + err = setexposure(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + + gspca_dev->usb_err = err; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h index b2d45fe5052..d7498e06432 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h @@ -37,18 +37,11 @@ static int st6422_init(struct sd *sd); static int st6422_stop(struct sd *sd); static void st6422_disconnect(struct sd *sd); -/* V4L2 controls supported by the driver */ -static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); - const struct stv06xx_sensor stv06xx_sensor_st6422 = { .name = "ST6422", + /* No known way to lower framerate in case of less bandwidth */ + .min_packet_size = { 300, 847 }, + .max_packet_size = { 300, 847 }, .init = st6422_init, .probe = st6422_probe, .start = st6422_start, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index b3b5508473b..7fe3587f5f7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .i2c_flush = 5, .i2c_addr = 0x20, .i2c_len = 1, + /* FIXME (see if we can lower packet_size-s, needs testing, and also + adjusting framerate when the bandwidth gets lower) */ + .min_packet_size = { 1023 }, + .max_packet_size = { 1023 }, .init = vv6410_init, .probe = vv6410_probe, .start = vv6410_start, @@ -220,10 +224,6 @@ static const u8 x1536[] = { /* 0x1536 - 0x153b */ 0x02, 0x00, 0x60, 0x01, 0x20, 0x01 }; -static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */ - 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */ -}; - static const struct stv_init stv_bridge_init[] = { /* This reg is written twice. Some kind of reset? */ {NULL, 0x1620, 0x80}, @@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_init[] = { {NULL, 0x1423, 0x04}, {x1500, 0x1500, ARRAY_SIZE(x1500)}, {x1536, 0x1536, ARRAY_SIZE(x1536)}, - {x15c1, 0x15c1, ARRAY_SIZE(x15c1)} }; static const u8 vv6410_sensor_init[][2] = { diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index b45f4d0f399..8f0c33116e0 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -487,7 +487,7 @@ static const u8 gamma_table[GAMMA_MAX][17] = { {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, 0xff}, - {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ + {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, 0xff}, {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index d9e3c605078..38c22f0a426 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -132,7 +132,7 @@ static const struct v4l2_pix_format sif_mode[] = { #define R36_PID 0x36 #define R37_PIDH 0x37 #define R39_Test1 0x39 /* GPIO */ -#define R3B_Test3 0x3B /* GPIO */ +#define R3B_Test3 0x3b /* GPIO */ #define R83_AD_IDH 0x83 #define R91_AD_SLOPEREG 0x91 #define R94_AD_BITCONTROL 0x94 diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 38a6efe1a5f..9b2ae1b6cc7 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -47,24 +47,29 @@ struct sd { u8 image_offset; u8 bridge; -#define BRIDGE_VC0321 0 -#define BRIDGE_VC0323 1 u8 sensor; -#define SENSOR_HV7131R 0 -#define SENSOR_MI0360 1 -#define SENSOR_MI1310_SOC 2 -#define SENSOR_MI1320 3 -#define SENSOR_MI1320_SOC 4 -#define SENSOR_OV7660 5 -#define SENSOR_OV7670 6 -#define SENSOR_PO1200 7 -#define SENSOR_PO3130NC 8 -#define SENSOR_POxxxx 9 u8 flags; #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ #define FL_HFLIP 0x02 /* mirrored by default */ #define FL_VFLIP 0x04 /* vertical flipped by default */ }; +enum bridges { + BRIDGE_VC0321, + BRIDGE_VC0323, +}; +enum sensors { + SENSOR_HV7131R, + SENSOR_MI0360, + SENSOR_MI1310_SOC, + SENSOR_MI1320, + SENSOR_MI1320_SOC, + SENSOR_OV7660, + SENSOR_OV7670, + SENSOR_PO1200, + SENSOR_PO3130NC, + SENSOR_POxxxx, + NSENSORS +}; /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); @@ -260,56 +265,56 @@ static const struct ctrl sd_ctrls[] = { }; /* table of the disabled controls */ -static u32 ctrl_dis[] = { -/* SENSOR_HV7131R 0 */ +static u32 ctrl_dis[NSENSORS] = { + [SENSOR_HV7131R] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI0360 1 */ + [SENSOR_MI0360] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1310_SOC 2 */ + [SENSOR_MI1310_SOC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1320 3 */ + [SENSOR_MI1320] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1320_SOC 4 */ + [SENSOR_MI1320_SOC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_OV7660 5 */ + [SENSOR_OV7660] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_OV7670 6 */ + [SENSOR_OV7670] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_PO1200 7 */ + [SENSOR_PO1200] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_PO3130NC 8 */ + [SENSOR_PO3130NC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_POxxxx 9 */ + [SENSOR_POxxxx] = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX), }; @@ -3420,17 +3425,18 @@ static int sd_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int sensor; - static u8 npkt[] = { /* number of packets per ISOC message */ - 64, /* HV7131R 0 */ - 32, /* MI0360 1 */ - 32, /* MI1310_SOC 2 */ - 64, /* MI1320 3 */ - 128, /* MI1320_SOC 4 */ - 32, /* OV7660 5 */ - 64, /* OV7670 6 */ - 128, /* PO1200 7 */ - 128, /* PO3130NC 8 */ - 128, /* POxxxx 9 */ + /* number of packets per ISOC message */ + static u8 npkt[NSENSORS] = { + [SENSOR_HV7131R] = 64, + [SENSOR_MI0360] = 32, + [SENSOR_MI1310_SOC] = 32, + [SENSOR_MI1320] = 64, + [SENSOR_MI1320_SOC] = 128, + [SENSOR_OV7660] = 32, + [SENSOR_OV7670] = 64, + [SENSOR_PO1200] = 128, + [SENSOR_PO3130NC] = 128, + [SENSOR_POxxxx] = 128, }; if (sd->sensor != SENSOR_POxxxx) diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 4066ac8c45a..4a9e622e5e1 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -59,18 +59,21 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG}, }; -static int reg_w(struct sd *sd, __u16 index, __u16 value); +static void reg_w(struct sd *sd, u16 index, u16 value); /*-------------------------------------------------------------------------- Write 64-bit data to the fast serial bus registers. Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_write_fsb(struct sd *sd, u16* data) +static void w9968cf_write_fsb(struct sd *sd, u16* data) { struct usb_device *udev = sd->gspca_dev.dev; u16 value; int ret; + if (sd->gspca_dev.usb_err < 0) + return; + value = *data++; memcpy(sd->gspca_dev.usb_buf, data, 6); @@ -79,20 +82,21 @@ static int w9968cf_write_fsb(struct sd *sd, u16* data) value, 0x06, sd->gspca_dev.usb_buf, 6, 500); if (ret < 0) { err("Write FSB registers failed (%d)", ret); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } /*-------------------------------------------------------------------------- Write data to the serial bus control register. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_write_sb(struct sd *sd, u16 value) +static void w9968cf_write_sb(struct sd *sd, u16 value) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + /* We don't use reg_w here, as that would cause all writes when bitbanging i2c to be logged, making the logs impossible to read */ ret = usb_control_msg(sd->gspca_dev.dev, @@ -105,10 +109,8 @@ static int w9968cf_write_sb(struct sd *sd, u16 value) if (ret < 0) { err("Write SB reg [01] %04x failed", value); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } /*-------------------------------------------------------------------------- @@ -119,6 +121,9 @@ static int w9968cf_read_sb(struct sd *sd) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + /* We don't use reg_r here, as the w9968cf is special and has 16 bit registers instead of 8 bit */ ret = usb_control_msg(sd->gspca_dev.dev, @@ -126,11 +131,13 @@ static int w9968cf_read_sb(struct sd *sd) 1, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0] | (sd->gspca_dev.usb_buf[1] << 8); - else + } else { err("Read SB reg [01] failed"); + sd->gspca_dev.usb_err = ret; + } udelay(W9968CF_I2C_BUS_DELAY); @@ -142,22 +149,20 @@ static int w9968cf_read_sb(struct sd *sd) This function is called by w9968cf_start_transfer(). Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_upload_quantizationtables(struct sd *sd) +static void w9968cf_upload_quantizationtables(struct sd *sd) { u16 a, b; - int ret = 0, i, j; + int i, j; - ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ + reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ for (i = 0, j = 0; i < 32; i++, j += 2) { - a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); - b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); - ret += reg_w(sd, 0x40+i, a); - ret += reg_w(sd, 0x60+i, b); + a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); + b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8); + reg_w(sd, 0x40 + i, a); + reg_w(sd, 0x60 + i, b); } - ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ - - return ret; + reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ } /**************************************************************************** @@ -168,50 +173,39 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) * i2c_adap_read_byte() * ****************************************************************************/ -static int w9968cf_smbus_start(struct sd *sd) +static void w9968cf_smbus_start(struct sd *sd) { - int ret = 0; - - ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - - return ret; + w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ } -static int w9968cf_smbus_stop(struct sd *sd) +static void w9968cf_smbus_stop(struct sd *sd) { - int ret = 0; - - ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - - return ret; + w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ } -static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) +static void w9968cf_smbus_write_byte(struct sd *sd, u8 v) { u8 bit; - int ret = 0, sda; + int sda; for (bit = 0 ; bit < 8 ; bit++) { sda = (v & 0x80) ? 2 : 0; v <<= 1; /* SDE=1, SDA=sda, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x10 | sda); + w9968cf_write_sb(sd, 0x10 | sda); /* SDE=1, SDA=sda, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x11 | sda); + w9968cf_write_sb(sd, 0x11 | sda); /* SDE=1, SDA=sda, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x10 | sda); + w9968cf_write_sb(sd, 0x10 | sda); } - - return ret; } -static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) +static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v) { u8 bit; - int ret = 0; /* No need to ensure SDA is high as we are always called after read_ack which ends with SDA high */ @@ -219,51 +213,40 @@ static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) for (bit = 0 ; bit < 8 ; bit++) { *v <<= 1; /* SDE=1, SDA=1, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0013); + w9968cf_write_sb(sd, 0x0013); *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; /* SDE=1, SDA=1, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0012); + w9968cf_write_sb(sd, 0x0012); } - - return ret; } -static int w9968cf_smbus_write_nack(struct sd *sd) +static void w9968cf_smbus_write_nack(struct sd *sd) { - int ret = 0; - /* No need to ensure SDA is high as we are always called after read_byte which ends with SDA high */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - - return ret; + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ } -static int w9968cf_smbus_read_ack(struct sd *sd) +static void w9968cf_smbus_read_ack(struct sd *sd) { - int ret = 0, sda; + int sda; /* Ensure SDA is high before raising clock to avoid a spurious stop */ - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ sda = w9968cf_read_sb(sd); - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - if (sda < 0) - ret += sda; - else if (sda & 0x08) { + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + if (sda >= 0 && (sda & 0x08)) { PDEBUG(D_USBI, "Did not receive i2c ACK"); - ret += -1; + sd->gspca_dev.usb_err = -EIO; } - - return ret; } /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ -static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) +static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) { u16* data = (u16 *)sd->gspca_dev.usb_buf; - int ret = 0; data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; @@ -276,7 +259,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); data[0] |= (reg & 0x40) ? 0x0540 : 0x0; @@ -290,7 +273,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[2] |= (reg & 0x01) ? 0x5400 : 0x0; data[3] = 0x001d; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); data[0] |= (value & 0x40) ? 0x0540 : 0x0; @@ -304,14 +287,9 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[2] |= (value & 0x01) ? 0x5400 : 0x0; data[3] = 0xfe1d; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); - if (!ret) - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - else - PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); - - return ret; + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); } /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ @@ -321,28 +299,28 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) u8 value; /* Fast serial bus data control disable */ - ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ - - ret += w9968cf_smbus_start(sd); - ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_write_byte(sd, reg); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_stop(sd); - ret += w9968cf_smbus_start(sd); - ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_read_byte(sd, &value); + w9968cf_write_sb(sd, 0x0013); /* don't change ! */ + + w9968cf_smbus_start(sd); + w9968cf_smbus_write_byte(sd, sd->sensor_addr); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_write_byte(sd, reg); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_stop(sd); + w9968cf_smbus_start(sd); + w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_read_byte(sd, &value); /* signal we don't want to read anymore, the v4l1 driver used to send an ack here which is very wrong! (and then fixed the issues this gave by retrying reads) */ - ret += w9968cf_smbus_write_nack(sd); - ret += w9968cf_smbus_stop(sd); + w9968cf_smbus_write_nack(sd); + w9968cf_smbus_stop(sd); /* Fast serial bus data control re-enable */ - ret += w9968cf_write_sb(sd, 0x0030); + w9968cf_write_sb(sd, 0x0030); - if (!ret) { + if (sd->gspca_dev.usb_err >= 0) { ret = value; PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); } else @@ -351,79 +329,68 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) return ret; } - /*-------------------------------------------------------------------------- Turn on the LED on some webcams. A beep should be heard too. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_configure(struct sd *sd) +static void w9968cf_configure(struct sd *sd) { - int ret = 0; - - ret += reg_w(sd, 0x00, 0xff00); /* power-down */ - ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ - ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ - ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ - ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ - ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ - ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ - - if (ret) - PDEBUG(D_ERR, "Couldn't turn on the LED"); + reg_w(sd, 0x00, 0xff00); /* power-down */ + reg_w(sd, 0x00, 0xbf17); /* reset everything */ + reg_w(sd, 0x00, 0xbf10); /* normal operation */ + reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ + reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ + reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ + reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ sd->stopped = 1; - - return ret; } -static int w9968cf_init(struct sd *sd) +static void w9968cf_init(struct sd *sd) { - int ret = 0; unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), y0 = 0x0000, - u0 = y0 + hw_bufsize/2, - v0 = u0 + hw_bufsize/4, - y1 = v0 + hw_bufsize/4, - u1 = y1 + hw_bufsize/2, - v1 = u1 + hw_bufsize/4; - - ret += reg_w(sd, 0x00, 0xff00); /* power off */ - ret += reg_w(sd, 0x00, 0xbf10); /* power on */ - - ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */ - ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ - - ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ - ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ - ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ - ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ - ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ - ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ - - ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ - ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ - ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ - ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ - ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ - ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ - - ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ - ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ - - ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ - ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ - - ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ - ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ - ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ - ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ - - return ret; + u0 = y0 + hw_bufsize / 2, + v0 = u0 + hw_bufsize / 4, + y1 = v0 + hw_bufsize / 4, + u1 = y1 + hw_bufsize / 2, + v1 = u1 + hw_bufsize / 4; + + reg_w(sd, 0x00, 0xff00); /* power off */ + reg_w(sd, 0x00, 0xbf10); /* power on */ + + reg_w(sd, 0x03, 0x405d); /* DRAM timings */ + reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ + + reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ + reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ + reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ + reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ + reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ + reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ + + reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ + reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ + reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ + reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ + reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ + reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ + + reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ + reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ + + reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ + reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ + + reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ + reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ + reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ + reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ } -static int w9968cf_set_crop_window(struct sd *sd) +static void w9968cf_set_crop_window(struct sd *sd) { - int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, + int start_cropx, start_cropy, x, y, fw, fh, cw, ch, max_width, max_height; if (sd->sif) { @@ -456,8 +423,8 @@ static int w9968cf_set_crop_window(struct sd *sd) fw = SC(sd->gspca_dev.width) / max_width; fh = SC(sd->gspca_dev.height) / max_height; - cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh; - ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height; + cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh; + ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height; sd->sensor_width = max_width; sd->sensor_height = max_height; @@ -465,42 +432,40 @@ static int w9968cf_set_crop_window(struct sd *sd) x = (max_width - cw) / 2; y = (max_height - ch) / 2; - ret += reg_w(sd, 0x10, start_cropx + x); - ret += reg_w(sd, 0x11, start_cropy + y); - ret += reg_w(sd, 0x12, start_cropx + x + cw); - ret += reg_w(sd, 0x13, start_cropy + y + ch); - - return ret; + reg_w(sd, 0x10, start_cropx + x); + reg_w(sd, 0x11, start_cropy + y); + reg_w(sd, 0x12, start_cropx + x + cw); + reg_w(sd, 0x13, start_cropy + y + ch); } -static int w9968cf_mode_init_regs(struct sd *sd) +static void w9968cf_mode_init_regs(struct sd *sd) { - int ret = 0, val, vs_polarity, hs_polarity; + int val, vs_polarity, hs_polarity; - ret += w9968cf_set_crop_window(sd); + w9968cf_set_crop_window(sd); - ret += reg_w(sd, 0x14, sd->gspca_dev.width); - ret += reg_w(sd, 0x15, sd->gspca_dev.height); + reg_w(sd, 0x14, sd->gspca_dev.width); + reg_w(sd, 0x15, sd->gspca_dev.height); /* JPEG width & height */ - ret += reg_w(sd, 0x30, sd->gspca_dev.width); - ret += reg_w(sd, 0x31, sd->gspca_dev.height); + reg_w(sd, 0x30, sd->gspca_dev.width); + reg_w(sd, 0x31, sd->gspca_dev.height); /* Y & UV frame buffer strides (in WORD) */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { - ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2); - ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4); + reg_w(sd, 0x2c, sd->gspca_dev.width / 2); + reg_w(sd, 0x2d, sd->gspca_dev.width / 4); } else - ret += reg_w(sd, 0x2c, sd->gspca_dev.width); + reg_w(sd, 0x2c, sd->gspca_dev.width); - ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ - ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ + reg_w(sd, 0x00, 0xbf17); /* reset everything */ + reg_w(sd, 0x00, 0xbf10); /* normal operation */ /* Transfer size in WORDS (for UYVY format only) */ val = sd->gspca_dev.width * sd->gspca_dev.height; - ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ - ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ + reg_w(sd, 0x3d, val & 0xffff); /* low bits */ + reg_w(sd, 0x3e, val >> 16); /* high bits */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { @@ -508,7 +473,7 @@ static int w9968cf_mode_init_regs(struct sd *sd) jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, sd->gspca_dev.width, 0x22); /* JPEG 420 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); - ret += w9968cf_upload_quantizationtables(sd); + w9968cf_upload_quantizationtables(sd); } /* Video Capture Control Register */ @@ -540,19 +505,15 @@ static int w9968cf_mode_init_regs(struct sd *sd) val |= 0x8000; /* capt. enable */ - ret += reg_w(sd, 0x16, val); + reg_w(sd, 0x16, val); sd->gspca_dev.empty_packet = 0; - - return ret; } static void w9968cf_stop0(struct sd *sd) { - if (sd->gspca_dev.present) { - reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ - reg_w(sd, 0x16, 0x0000); /* stop video capture */ - } + reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ + reg_w(sd, 0x16, 0x0000); /* stop video capture */ } /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index 8715577bc2d..5b5039a0203 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c @@ -29,6 +29,7 @@ #define MODULE_NAME "xirlink-cit" +#include <linux/input.h> #include "gspca.h" MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); @@ -58,6 +59,7 @@ struct sd { #define CIT_MODEL4 4 #define CIT_IBM_NETCAM_PRO 5 u8 input_index; + u8 button_state; u8 stop_on_control_change; u8 sof_read; u8 sof_len; @@ -185,60 +187,60 @@ static const struct ctrl sd_ctrls[] = { static const struct v4l2_pix_format cif_yuv_mode[] = { {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2, + .sizeimage = 352 * 288 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format vga_yuv_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, + .sizeimage = 320 * 240 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2, + .sizeimage = 640 * 480 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format model0_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, + .sizeimage = 320 * 240 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format model2_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240, + .sizeimage = 320 * 240 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288, + .sizeimage = 352 * 288 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; @@ -804,7 +806,7 @@ static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index) return 0; } -static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index) +static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose) { struct usb_device *udev = gspca_dev->dev; __u8 *buf = gspca_dev->usb_buf; @@ -819,10 +821,8 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index) return res; } - PDEBUG(D_PROBE, - "Register %04x value: %02x %02x %02x %02x %02x %02x %02x %02x", - index, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + if (verbose) + PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]); return 0; } @@ -907,7 +907,7 @@ static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val) cit_send_x_00_05(gspca_dev, 0x0089); cit_send_x_00(gspca_dev, fkey); cit_send_00_04_06(gspca_dev); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 0); cit_send_FF_04_02(gspca_dev); } @@ -1074,12 +1074,12 @@ static int cit_init_model0(struct gspca_dev *gspca_dev) static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) { - cit_read_reg(gspca_dev, 0x128); + cit_read_reg(gspca_dev, 0x128, 1); cit_write_reg(gspca_dev, 0x0003, 0x0133); cit_write_reg(gspca_dev, 0x0000, 0x0117); cit_write_reg(gspca_dev, 0x0008, 0x0123); cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x0000, 0x0133); @@ -1098,7 +1098,7 @@ static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00ff, 0x0130); cit_write_reg(gspca_dev, 0xcd41, 0x0124); cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 1); cit_model3_Packet1(gspca_dev, 0x0000, 0x0000); cit_model3_Packet1(gspca_dev, 0x0000, 0x0001); @@ -1557,18 +1557,20 @@ static int cit_restart_stream(struct gspca_dev *gspca_dev) switch (sd->model) { case CIT_MODEL0: case CIT_MODEL1: - case CIT_MODEL3: - case CIT_IBM_NETCAM_PRO: cit_write_reg(gspca_dev, 0x0001, 0x0114); /* Fall through */ case CIT_MODEL2: case CIT_MODEL4: cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - /* This happens repeatedly while streaming with the ibm netcam - pro and the ibmcam driver did it for model3 after changing - settings, but it does not seem to have any effect. */ - /* cit_write_reg(gspca_dev, 0x0001, 0x0113); */ + break; + case CIT_MODEL3: + case CIT_IBM_NETCAM_PRO: + cit_write_reg(gspca_dev, 0x0001, 0x0114); + cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); + /* Clear button events from while we were not streaming */ + cit_write_reg(gspca_dev, 0x0001, 0x0113); break; } @@ -1680,23 +1682,23 @@ static int cit_start_model1(struct gspca_dev *gspca_dev) if (clock_div < 0) return clock_div; - cit_read_reg(gspca_dev, 0x0128); - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0128, 1); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ cit_write_reg(gspca_dev, 0x01, 0x0108); cit_write_reg(gspca_dev, 0x03, 0x0112); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x06, 0x0115); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x44, 0x0116); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x40, 0x0116); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x0e, 0x0115); cit_write_reg(gspca_dev, 0x19, 0x012c); @@ -1878,7 +1880,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) int clock_div = 0; cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */ - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x00bc, 0x012c); @@ -2070,10 +2072,10 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) /* HDG not in ibmcam driver, added to see if it helps with auto-detecting between model3 and ibm netcamera pro */ - cit_read_reg(gspca_dev, 0x128); + cit_read_reg(gspca_dev, 0x128, 1); cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x0000, 0x0123); @@ -2083,7 +2085,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0115); cit_write_reg(gspca_dev, 0x0003, 0x0115); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x000b, 0x0115); /* TESTME HDG not in ibmcam driver, added to see if it helps with @@ -2096,7 +2098,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00ff, 0x0130); cit_write_reg(gspca_dev, 0xcd41, 0x0124); cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 1); } cit_model3_Packet1(gspca_dev, 0x000a, 0x0040); @@ -2293,7 +2295,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) if (rca_input) { for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2]); + cit_read_reg(gspca_dev, rca_initdata[i][2], 0); else cit_write_reg(gspca_dev, rca_initdata[i][1], rca_initdata[i][2]); @@ -2712,7 +2714,7 @@ static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev) if (rca_input) { for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2]); + cit_read_reg(gspca_dev, rca_initdata[i][2], 0); else cit_write_reg(gspca_dev, rca_initdata[i][1], rca_initdata[i][2]); @@ -2769,16 +2771,55 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +static int sd_isoc_init(struct gspca_dev *gspca_dev) +{ + struct usb_host_interface *alt; + int max_packet_size; + + switch (gspca_dev->width) { + case 160: + max_packet_size = 450; + break; + case 176: + max_packet_size = 600; + break; + default: + max_packet_size = 1022; + break; + } + + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); + + return 0; +} + static int sd_isoc_nego(struct gspca_dev *gspca_dev) { - int ret, packet_size; + int ret, packet_size, min_packet_size; struct usb_host_interface *alt; + switch (gspca_dev->width) { + case 160: + min_packet_size = 200; + break; + case 176: + min_packet_size = 266; + break; + default: + min_packet_size = 400; + break; + } + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - packet_size -= 100; - if (packet_size < 300) + if (packet_size <= min_packet_size) return -EIO; + + packet_size -= 100; + if (packet_size < min_packet_size) + packet_size = min_packet_size; alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); @@ -2796,15 +2837,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_host_interface *alt; /* We cannot use gspca_dev->present here as that is not set when sd_init gets called and we get called from sd_init */ if (!gspca_dev->dev) return; - alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; - switch (sd->model) { case CIT_MODEL0: /* HDG windows does this, but it causes the cams autogain to @@ -2815,7 +2853,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) break; case CIT_MODEL1: cit_send_FF_04_02(gspca_dev); - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ break; case CIT_MODEL2: @@ -2834,9 +2872,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev) case CIT_MODEL3: cit_write_reg(gspca_dev, 0x0006, 0x012c); cit_model3_Packet1(gspca_dev, 0x0046, 0x0000); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0064, 0x0116); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x0003, 0x0115); cit_write_reg(gspca_dev, 0x0008, 0x0123); cit_write_reg(gspca_dev, 0x0000, 0x0117); @@ -2859,12 +2897,17 @@ static void sd_stop0(struct gspca_dev *gspca_dev) restarting the stream after this */ /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */ cit_write_reg(gspca_dev, 0x00c0, 0x0100); - - /* Start isoc bandwidth "negotiation" at max isoc bandwith - next stream start */ - alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(1022); break; } + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + /* If the last button state is pressed, release it now! */ + if (sd->button_state) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + sd->button_state = 0; + } +#endif } static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) @@ -3158,6 +3201,38 @@ static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) +static void cit_check_button(struct gspca_dev *gspca_dev) +{ + int new_button_state; + struct sd *sd = (struct sd *)gspca_dev; + + switch (sd->model) { + case CIT_MODEL3: + case CIT_IBM_NETCAM_PRO: + break; + default: /* TEST ME unknown if this works on other models too */ + return; + } + + /* Read the button state */ + cit_read_reg(gspca_dev, 0x0113, 0); + new_button_state = !gspca_dev->usb_buf[0]; + + /* Tell the cam we've seen the button press, notice that this + is a nop (iow the cam keeps reporting pressed) until the + button is actually released. */ + if (new_button_state) + cit_write_reg(gspca_dev, 0x01, 0x0113); + + if (sd->button_state != new_button_state) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, + new_button_state); + input_sync(gspca_dev->input_dev); + sd->button_state = new_button_state; + } +} +#endif /* sub-driver description */ static const struct sd_desc sd_desc = { @@ -3170,6 +3245,10 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .dq_callback = cit_check_button, + .other_input = 1, +#endif }; static const struct sd_desc sd_desc_isoc_nego = { @@ -3179,10 +3258,15 @@ static const struct sd_desc sd_desc_isoc_nego = { .config = sd_config, .init = sd_init, .start = sd_start, + .isoc_init = sd_isoc_init, .isoc_nego = sd_isoc_nego, .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .dq_callback = cit_check_button, + .other_input = 1, +#endif }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index c7e1970ca28..14b85d48316 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -35,16 +35,23 @@ static int force_sensor = -1; #define QUANT_VAL 1 /* quantization table */ #include "zc3xx-reg.h" +/* controls */ +enum e_ctrl { + BRIGHTNESS, + CONTRAST, + GAMMA, + AUTOGAIN, + LIGHTFREQ, + SHARPNESS, + NCTRLS /* number of controls */ +}; + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 brightness; - u8 contrast; - u8 gamma; - u8 autogain; - u8 lightfreq; - u8 sharpness; + struct gspca_ctrl ctrls[NCTRLS]; + u8 quality; /* image quality */ #define QUALITY_MIN 50 #define QUALITY_MAX 80 @@ -64,6 +71,7 @@ enum sensors { SENSOR_ADCM2700, SENSOR_CS2102, SENSOR_CS2102K, + SENSOR_GC0303, SENSOR_GC0305, SENSOR_HDCS2020b, SENSOR_HV7131B, @@ -79,26 +87,17 @@ enum sensors { SENSOR_PB0330, SENSOR_PO2030, SENSOR_TAS5130C, - SENSOR_TAS5130C_VF0250, SENSOR_MAX }; /* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); - -static const struct ctrl sd_ctrls[] = { - { +static void setcontrast(struct gspca_dev *gspca_dev); +static void setautogain(struct gspca_dev *gspca_dev); +static void setlightfreq(struct gspca_dev *gspca_dev); +static void setsharpness(struct gspca_dev *gspca_dev); + +static const struct ctrl sd_ctrls[NCTRLS] = { +[BRIGHTNESS] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -106,13 +105,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define BRIGHTNESS_DEF 128 - .default_value = BRIGHTNESS_DEF, + .default_value = 128, }, - .set = sd_setbrightness, - .get = sd_getbrightness, + .set_control = setcontrast }, - { +[CONTRAST] = { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -120,13 +117,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define CONTRAST_DEF 128 - .default_value = CONTRAST_DEF, + .default_value = 128, }, - .set = sd_setcontrast, - .get = sd_getcontrast, + .set_control = setcontrast }, - { +[GAMMA] = { { .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, @@ -136,10 +131,9 @@ static const struct ctrl sd_ctrls[] = { .step = 1, .default_value = 4, }, - .set = sd_setgamma, - .get = sd_getgamma, + .set_control = setcontrast }, - { +[AUTOGAIN] = { { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -147,14 +141,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define AUTOGAIN_DEF 1 - .default_value = AUTOGAIN_DEF, + .default_value = 1, }, - .set = sd_setautogain, - .get = sd_getautogain, + .set_control = setautogain }, -#define LIGHTFREQ_IDX 4 - { +[LIGHTFREQ] = { { .id = V4L2_CID_POWER_LINE_FREQUENCY, .type = V4L2_CTRL_TYPE_MENU, @@ -162,13 +153,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ .step = 1, -#define FREQ_DEF 0 - .default_value = FREQ_DEF, + .default_value = 0, }, - .set = sd_setfreq, - .get = sd_getfreq, + .set_control = setlightfreq }, - { +[SHARPNESS] = { { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -176,11 +165,9 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 3, .step = 1, -#define SHARPNESS_DEF 2 - .default_value = SHARPNESS_DEF, + .default_value = 2, }, - .set = sd_setsharpness, - .get = sd_getsharpness, + .set_control = setsharpness }, }; @@ -4499,7 +4486,7 @@ static const struct usb_action mt9v111_3_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, + {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, @@ -5406,7 +5393,7 @@ static const struct usb_action tas5130c_NoFlikerScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_InitialScale[] = { +static const struct usb_action gc0303_InitialScale[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ @@ -5473,7 +5460,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_Initial[] = { +static const struct usb_action gc0303_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ @@ -5538,7 +5525,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = { {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ {} }; -static const struct usb_action tas5130c_vf0250_50HZScale[] = { +static const struct usb_action gc0303_50HZScale[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ @@ -5562,7 +5549,7 @@ static const struct usb_action tas5130c_vf0250_50HZScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_50HZ[] = { +static const struct usb_action gc0303_50HZ[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ @@ -5586,7 +5573,7 @@ static const struct usb_action tas5130c_vf0250_50HZ[] = { {} }; -static const struct usb_action tas5130c_vf0250_60HZScale[] = { +static const struct usb_action gc0303_60HZScale[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ @@ -5610,7 +5597,7 @@ static const struct usb_action tas5130c_vf0250_60HZScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_60HZ[] = { +static const struct usb_action gc0303_60HZ[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ @@ -5634,7 +5621,7 @@ static const struct usb_action tas5130c_vf0250_60HZ[] = { {} }; -static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { +static const struct usb_action gc0303_NoFlikerScale[] = { {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ @@ -5656,7 +5643,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_NoFliker[] = { +static const struct usb_action gc0303_NoFliker[] = { {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ @@ -5833,12 +5820,13 @@ static void setmatrix(struct gspca_dev *gspca_dev) {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; static const u8 tas5130c_matrix[9] = {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; - static const u8 vf0250_matrix[9] = + static const u8 gc0303_matrix[9] = {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; static const u8 *matrix_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = adcm2700_matrix, [SENSOR_CS2102] = ov7620_matrix, [SENSOR_CS2102K] = NULL, + [SENSOR_GC0303] = gc0303_matrix, [SENSOR_GC0305] = gc0305_matrix, [SENSOR_HDCS2020b] = NULL, [SENSOR_HV7131B] = NULL, @@ -5854,7 +5842,6 @@ static void setmatrix(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = gc0305_matrix, [SENSOR_PO2030] = po2030_matrix, [SENSOR_TAS5130C] = tas5130c_matrix, - [SENSOR_TAS5130C_VF0250] = vf0250_matrix, }; matrix = matrix_tb[sd->sensor]; @@ -5875,7 +5862,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) {0x10, 0x1e} }; - sharpness = sd->sharpness; + sharpness = sd->ctrls[SHARPNESS].val; reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6); reg_r(gspca_dev, 0x01c8); reg_r(gspca_dev, 0x01c9); @@ -5910,10 +5897,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, }; - Tgamma = gamma_tb[sd->gamma - 1]; + Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1]; - contrast = ((int) sd->contrast - 128); /* -128 / 127 */ - brightness = ((int) sd->brightness - 128); /* -128 / 92 */ + contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */ + brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */ adj = 0; gp1 = gp2 = 0; for (i = 0; i < 16; i++) { @@ -5994,6 +5981,10 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {cs2102_NoFliker, cs2102_NoFlikerScale, NULL, NULL, /* currently disabled */ NULL, NULL}, + [SENSOR_GC0303] = + {gc0303_NoFliker, gc0303_NoFlikerScale, + gc0303_50HZ, gc0303_50HZScale, + gc0303_60HZ, gc0303_60HZScale}, [SENSOR_GC0305] = {gc0305_NoFliker, gc0305_NoFliker, gc0305_50HZ, gc0305_50HZ, @@ -6054,14 +6045,10 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {tas5130c_NoFliker, tas5130c_NoFlikerScale, tas5130c_50HZ, tas5130c_50HZScale, tas5130c_60HZ, tas5130c_60HZScale}, - [SENSOR_TAS5130C_VF0250] = - {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, - tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, - tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, }; - i = sd->lightfreq * 2; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + i = sd->ctrls[LIGHTFREQ].val * 2; + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; if (mode) i++; /* 320x240 */ zc3_freq = freq_tb[sd->sensor][i]; @@ -6070,14 +6057,14 @@ static void setlightfreq(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, zc3_freq); switch (sd->sensor) { case SENSOR_GC0305: - if (mode /* if 320x240 */ - && sd->lightfreq == 1) /* and 50Hz */ + if (mode /* if 320x240 */ + && sd->ctrls[LIGHTFREQ].val == 1) /* and 50Hz */ reg_w(gspca_dev, 0x85, 0x018d); /* win: 0x80, 0x018d */ break; case SENSOR_OV7620: - if (!mode) { /* if 640x480 */ - if (sd->lightfreq != 0) /* and 50 or 60 Hz */ + if (!mode) { /* if 640x480 */ + if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */ reg_w(gspca_dev, 0x40, 0x0002); else reg_w(gspca_dev, 0x44, 0x0002); @@ -6094,7 +6081,7 @@ static void setautogain(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 autoval; - if (sd->autogain) + if (sd->ctrls[AUTOGAIN].val) autoval = 0x42; else autoval = 0x02; @@ -6330,8 +6317,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) retword = i2c_read(gspca_dev, 0x00); if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword); - if (retword == 0x0011) /* VF0250 */ - return 0x0250; + if (retword == 0x0011) /* gc0303 */ + return 0x0303; if (retword == 0x0029) /* gc0305 */ send_unknown(gspca_dev, SENSOR_GC0305); return retword; @@ -6392,7 +6379,7 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_MC501CB: return -1; /* don't probe */ - case SENSOR_TAS5130C_VF0250: + case SENSOR_GC0303: /* may probe but with no write in reg 0x0010 */ return -1; /* don't probe */ case SENSOR_PAS106: @@ -6421,11 +6408,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* define some sensors from the vendor/product */ sd->sensor = id->driver_info; - sd->sharpness = SHARPNESS_DEF; - sd->brightness = BRIGHTNESS_DEF; - sd->contrast = CONTRAST_DEF; - sd->autogain = AUTOGAIN_DEF; - sd->lightfreq = FREQ_DEF; + gspca_dev->cam.ctrls = sd->ctrls; sd->quality = QUALITY_DEF; return 0; @@ -6441,6 +6424,7 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_ADCM2700] = 4, [SENSOR_CS2102] = 4, [SENSOR_CS2102K] = 5, + [SENSOR_GC0303] = 3, [SENSOR_GC0305] = 4, [SENSOR_HDCS2020b] = 4, [SENSOR_HV7131B] = 4, @@ -6456,12 +6440,12 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = 4, [SENSOR_PO2030] = 4, [SENSOR_TAS5130C] = 3, - [SENSOR_TAS5130C_VF0250] = 3, }; static const u8 mode_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = 2, [SENSOR_CS2102] = 1, [SENSOR_CS2102K] = 1, + [SENSOR_GC0303] = 1, [SENSOR_GC0305] = 1, [SENSOR_HDCS2020b] = 1, [SENSOR_HV7131B] = 1, @@ -6477,7 +6461,6 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = 1, [SENSOR_PO2030] = 1, [SENSOR_TAS5130C] = 1, - [SENSOR_TAS5130C_VF0250] = 1, }; sensor = zcxx_probeSensor(gspca_dev); @@ -6493,8 +6476,8 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MC501CB: PDEBUG(D_PROBE, "Sensor MC501CB"); break; - case SENSOR_TAS5130C_VF0250: - PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)"); + case SENSOR_GC0303: + PDEBUG(D_PROBE, "Sensor GC0303"); break; default: warn("Unknown sensor - set to TAS5130C"); @@ -6581,14 +6564,14 @@ static int sd_init(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Find Sensor GC0305"); sd->sensor = SENSOR_GC0305; break; - case 0x0250: - PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)"); - sd->sensor = SENSOR_TAS5130C_VF0250; + case 0x0303: + PDEBUG(D_PROBE, "Sensor GC0303"); + sd->sensor = SENSOR_GC0303; break; case 0x2030: PDEBUG(D_PROBE, "Find Sensor PO2030"); sd->sensor = SENSOR_PO2030; - sd->sharpness = 0; /* from win traces */ + sd->ctrls[SHARPNESS].def = 0; /* from win traces */ break; case 0x7620: PDEBUG(D_PROBE, "Find Sensor OV7620"); @@ -6629,11 +6612,12 @@ static int sd_init(struct gspca_dev *gspca_dev) cam->nmodes = ARRAY_SIZE(broken_vga_mode); break; } - sd->gamma = gamma[sd->sensor]; + + sd->ctrls[GAMMA].def = gamma[sd->sensor]; switch (sd->sensor) { case SENSOR_OV7630C: - gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); + gspca_dev->ctrl_dis = (1 << LIGHTFREQ); break; } @@ -6653,6 +6637,8 @@ static int sd_start(struct gspca_dev *gspca_dev) {cs2102_Initial, cs2102_InitialScale}, [SENSOR_CS2102K] = {cs2102K_Initial, cs2102K_InitialScale}, + [SENSOR_GC0303] = + {gc0303_Initial, gc0303_InitialScale}, [SENSOR_GC0305] = {gc0305_Initial, gc0305_InitialScale}, [SENSOR_HDCS2020b] = @@ -6683,8 +6669,6 @@ static int sd_start(struct gspca_dev *gspca_dev) {po2030_Initial, po2030_InitialScale}, [SENSOR_TAS5130C] = {tas5130c_Initial, tas5130c_InitialScale}, - [SENSOR_TAS5130C_VF0250] = - {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale}, }; /* create the JPEG header */ @@ -6709,7 +6693,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7620: case SENSOR_PO2030: case SENSOR_TAS5130C: - case SENSOR_TAS5130C_VF0250: + case SENSOR_GC0303: /* msleep(100); * ?? */ reg_r(gspca_dev, 0x0002); /* --> 0x40 */ reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ @@ -6843,114 +6827,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->brightness; - return 0; -} - -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->contrast = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->contrast; - return 0; -} - -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->autogain = val; - if (gspca_dev->streaming) - setautogain(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->autogain; - return 0; -} - -static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->gamma = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->gamma; - return 0; -} - -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->lightfreq = val; - if (gspca_dev->streaming) - setlightfreq(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->lightfreq; - return 0; -} - -static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->sharpness = val; - if (gspca_dev->streaming) - setsharpness(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->sharpness; - return 0; -} - static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { @@ -7045,8 +6921,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, - {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250}, - {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303}, + {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303}, {USB_DEVICE(0x0458, 0x7007)}, {USB_DEVICE(0x0458, 0x700c)}, {USB_DEVICE(0x0458, 0x700f)}, @@ -7066,8 +6942,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08af)}, {USB_DEVICE(0x046d, 0x08b9)}, {USB_DEVICE(0x046d, 0x08d7)}, - {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08d8)}, + {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08da)}, {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index b70d6afc9fe..f7d1ee55185 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -385,6 +385,11 @@ static int hdpvr_probe(struct usb_interface *interface, v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); goto error; } + + /* until i2c is working properly */ + retval = 0; /* hdpvr_register_i2c_ir(dev); */ + if (retval < 0) + v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n"); #endif /* CONFIG_I2C */ /* let the user know what node this device is now attached to */ diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c index 409de11096d..24966aa02a7 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -4,6 +4,9 @@ * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * + * IR device registration code is + * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. @@ -22,6 +25,56 @@ #define REQTYPE_I2C_WRITE 0xb0 #define REQTYPE_I2C_WRITE_STATT 0xd0 +#define Z8F0811_IR_TX_I2C_ADDR 0x70 +#define Z8F0811_IR_RX_I2C_ADDR 0x71 + +static const u8 ir_i2c_addrs[] = { + Z8F0811_IR_TX_I2C_ADDR, + Z8F0811_IR_RX_I2C_ADDR, +}; + +static const char * const ir_devicenames[] = { + "ir_tx_z8f0811_hdpvr", + "ir_rx_z8f0811_hdpvr", +}; + +static int hdpvr_new_i2c_ir(struct hdpvr_device *dev, struct i2c_adapter *adap, + const char *type, u8 addr) +{ + struct i2c_board_info info; + struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; + unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, type, I2C_NAME_SIZE); + + /* Our default information for ir-kbd-i2c.c to use */ + switch (addr) { + case Z8F0811_IR_RX_I2C_ADDR: + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = "HD PVR"; + info.platform_data = init_data; + break; + } + + return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? + -1 : 0; +} + +int hdpvr_register_i2c_ir(struct hdpvr_device *dev) +{ + int i; + int ret = 0; + + for (i = 0; i < ARRAY_SIZE(ir_i2c_addrs); i++) + ret += hdpvr_new_i2c_ir(dev, dev->i2c_adapter, + ir_devicenames[i], ir_i2c_addrs[i]); + + return ret; +} + static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, char *data, int len) { diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 5efc963f916..37f1e4c7675 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -16,6 +16,7 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> +#include <media/ir-kbd-i2c.h> #define HDPVR_MAJOR_VERSION 0 #define HDPVR_MINOR_VERSION 2 @@ -109,6 +110,9 @@ struct hdpvr_device { /* I2C lock */ struct mutex i2c_mutex; + /* For passing data to ir-kbd-i2c */ + struct IR_i2c_init_data ir_i2c_init_data; + /* usb control transfer buffer and lock */ struct mutex usbc_mutex; u8 *usbc_buf; @@ -306,6 +310,8 @@ int hdpvr_cancel_queue(struct hdpvr_device *dev); /* i2c adapter registration */ int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); +int hdpvr_register_i2c_ir(struct hdpvr_device *dev); + /*========================================================================*/ /* buffer management */ int hdpvr_free_buffers(struct hdpvr_device *dev); diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 7ae96367b3a..cdf8b191f71 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -37,15 +37,15 @@ static int hexium_num; #define HEXIUM_INPUTS 9 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = { - { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; #define HEXIUM_AUDIOS 0 diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index b72d0f0b831..6ad7e1c8b92 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -38,15 +38,15 @@ static int hexium_num; #define HEXIUM_INPUTS 9 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = { - { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; #define HEXIUM_AUDIOS 0 diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c index 27b5dfdfbb9..1a116911571 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/video/imx074.c @@ -467,7 +467,6 @@ static int imx074_remove(struct i2c_client *client) icd->ops = NULL; if (icl->free_bus) icl->free_bus(icl); - client->driver = NULL; kfree(priv); return 0; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ce4a7537590..c87b6bc4555 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -46,7 +46,7 @@ #include <linux/i2c.h> #include <linux/workqueue.h> -#include <media/ir-core.h> +#include <media/rc-core.h> #include <media/ir-kbd-i2c.h> /* ----------------------------------------------------------------------- */ @@ -252,7 +252,7 @@ static void ir_key_poll(struct IR_i2c *ir) } if (rc) - ir_keydown(ir->input, ir_key, 0); + rc_keydown(ir->rc, ir_key, 0); } static void ir_work(struct work_struct *work) @@ -269,22 +269,18 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { char *ir_codes = NULL; const char *name = NULL; - u64 ir_type = 0; + u64 rc_type = RC_TYPE_UNKNOWN; struct IR_i2c *ir; - struct input_dev *input_dev; + struct rc_dev *rc = NULL; struct i2c_adapter *adap = client->adapter; unsigned short addr = client->addr; int err; - ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) { - err = -ENOMEM; - goto err_out_free; - } + ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); + if (!ir) + return -ENOMEM; ir->c = client; - ir->input = input_dev; ir->polling_interval = DEFAULT_POLLING_INTERVAL; i2c_set_clientdata(client, ir); @@ -292,7 +288,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x64: name = "Pixelview"; ir->get_key = get_key_pixelview; - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_EMPTY; break; case 0x18: @@ -300,7 +296,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x1a: name = "Hauppauge"; ir->get_key = get_key_haup; - ir_type = IR_TYPE_RC5; + rc_type = RC_TYPE_RC5; if (hauppauge == 1) { ir_codes = RC_MAP_HAUPPAUGE_NEW; } else { @@ -310,19 +306,19 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x30: name = "KNC One"; ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_EMPTY; break; case 0x6b: name = "FusionHDTV"; ir->get_key = get_key_fusionhdtv; - ir_type = IR_TYPE_RC5; + rc_type = RC_TYPE_RC5; ir_codes = RC_MAP_FUSIONHDTV_MCE; break; case 0x40: name = "AVerMedia Cardbus remote"; ir->get_key = get_key_avermedia_cardbus; - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_AVERMEDIA_CARDBUS; break; } @@ -333,9 +329,11 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) client->dev.platform_data; ir_codes = init_data->ir_codes; + rc = init_data->rc_dev; + name = init_data->name; if (init_data->type) - ir_type = init_data->type; + rc_type = init_data->type; if (init_data->polling_interval) ir->polling_interval = init_data->polling_interval; @@ -366,8 +364,21 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } } + if (!rc) { + /* + * If platform_data doesn't specify rc_dev, initilize it + * internally + */ + rc = rc_allocate_device(); + if (!rc) { + err = -ENOMEM; + goto err_out_free; + } + } + ir->rc = rc; + /* Make sure we are all setup before going on */ - if (!name || !ir->get_key || !ir_type || !ir_codes) { + if (!name || !ir->get_key || !rc_type || !ir_codes) { dprintk(1, ": Unsupported device at address 0x%02x\n", addr); err = -ENODEV; @@ -382,18 +393,28 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_name(&adap->dev), dev_name(&client->dev)); - /* init + register input device */ - ir->ir_type = ir_type; - input_dev->id.bustype = BUS_I2C; - input_dev->name = ir->name; - input_dev->phys = ir->phys; + /* + * Initialize input_dev fields + * It doesn't make sense to allow overriding them via platform_data + */ + rc->input_id.bustype = BUS_I2C; + rc->input_phys = ir->phys; + rc->input_name = ir->name; + + /* + * Initialize the other fields of rc_dev + */ + rc->map_name = ir->ir_codes; + rc->allowed_protos = rc_type; + if (!rc->driver_name) + rc->driver_name = MODULE_NAME; - err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_free; printk(MODULE_NAME ": %s detected at %s [%s]\n", - ir->input->name, ir->input->phys, adap->name); + ir->name, ir->phys, adap->name); /* start polling via eventd */ INIT_DELAYED_WORK(&ir->work, ir_work); @@ -402,6 +423,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_out_free: + /* Only frees rc if it were allocated internally */ + rc_free_device(rc); kfree(ir); return err; } @@ -414,7 +437,7 @@ static int ir_remove(struct i2c_client *client) cancel_delayed_work_sync(&ir->work); /* unregister device */ - ir_input_unregister(ir->input); + rc_unregister_device(ir->rc); /* free memory */ kfree(ir); @@ -426,6 +449,7 @@ static const struct i2c_device_id ir_kbd_id[] = { { "ir_video", 0 }, /* IR device specific entries should be added here */ { "ir_rx_z8f0811_haup", 0 }, + { "ir_rx_z8f0811_hdpvr", 0 }, { } }; diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index be4af1fa557..89f65914cc8 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,9 +1,8 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" depends on VIDEO_V4L2 && PCI && I2C - depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT - depends on VIDEO_IR + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 87afbbee206..145e4749a69 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -405,7 +405,8 @@ static const struct ivtv_card ivtv_card_avc2410 = { .hw_audio_ctrl = IVTV_HW_MSP34XX, .hw_muxer = IVTV_HW_CS53L32A, .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A | - IVTV_HW_SAA7115 | IVTV_HW_TUNER, + IVTV_HW_SAA7115 | IVTV_HW_TUNER | + IVTV_HW_I2C_IR_RX_ADAPTEC, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, @@ -1313,7 +1314,6 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input) "Composite 3" }; - memset(input, 0, sizeof(*input)); if (index >= itv->nof_inputs) return -EINVAL; input->index = index; @@ -1331,7 +1331,6 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output) { const struct ivtv_card_output *card_output = itv->card->video_outputs + index; - memset(output, 0, sizeof(*output)); if (index >= itv->card->nof_outputs) return -EINVAL; output->index = index; diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 78eca992e1f..e6f5c02981f 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -111,6 +111,7 @@ #define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) #define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) #define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) +#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 21) #define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ IVTV_HW_Z8F0811_IR_TX_HAUP) @@ -120,7 +121,8 @@ #define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ IVTV_HW_I2C_IR_RX_HAUP_EXT | \ IVTV_HW_I2C_IR_RX_HAUP_INT | \ - IVTV_HW_Z8F0811_IR_RX_HAUP) + IVTV_HW_Z8F0811_IR_RX_HAUP | \ + IVTV_HW_I2C_IR_RX_ADAPTEC) #define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e421d15b0f5..39946420b30 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1029,8 +1029,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); if (!itv->enc_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " + "encoder memory\n"); + IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of " + "vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } @@ -1041,8 +1046,14 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); if (!itv->dec_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into " + "CX23415 decoder memory\n"); + IVTV_ERR("Each capture card with a CX23415 needs 8 MB " + "of vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc " + "/proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option " + "to set VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } @@ -1057,8 +1068,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->reg_mem = ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); if (!itv->reg_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " + "register space\n"); + IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of " + "vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_io; } diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index d727485da88..c57a58523ca 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -570,8 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c int elems = count / sizeof(struct v4l2_sliced_vbi_data); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems); - return elems * sizeof(struct v4l2_sliced_vbi_data); + return ivtv_write_vbi_from_user(itv, + (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); } mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 9e8039ac909..e103b8fc745 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -94,6 +94,7 @@ #define IVTV_HAUP_INT_IR_RX_I2C_ADDR 0x18 #define IVTV_Z8F0811_IR_TX_I2C_ADDR 0x70 #define IVTV_Z8F0811_IR_RX_I2C_ADDR 0x71 +#define IVTV_ADAPTEC_IR_ADDR 0x6b /* This array should match the IVTV_HW_ defines */ static const u8 hw_addrs[] = { @@ -118,6 +119,7 @@ static const u8 hw_addrs[] = { IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + IVTV_ADAPTEC_IR_ADDR, /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; /* This array should match the IVTV_HW_ defines */ @@ -143,8 +145,34 @@ static const char * const hw_devicenames[] = { "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + "ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; +static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char keybuf[4]; + + keybuf[0] = 0x00; + i2c_master_send(ir->c, keybuf, 1); + /* poll IR chip */ + if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { + return 0; + } + + /* key pressed ? */ + if (keybuf[2] == 0xff) + return 0; + + /* remove repeat bit */ + keybuf[2] &= 0x7f; + keybuf[3] |= 0x80; + + *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24; + *ir_raw = *ir_key; + + return 1; +} + static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) { struct i2c_board_info info; @@ -172,7 +200,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS; init_data->internal_get_key_func = IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; - init_data->type = IR_TYPE_OTHER; + init_data->type = RC_TYPE_OTHER; init_data->name = "AVerMedia AVerTV card"; break; case IVTV_HW_I2C_IR_RX_HAUP_EXT: @@ -180,15 +208,22 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) /* Default to old black remote */ init_data->ir_codes = RC_MAP_RC5_TV; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; init_data->name = itv->card_name; break; case IVTV_HW_Z8F0811_IR_RX_HAUP: /* Default to grey remote */ init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; + init_data->name = itv->card_name; + break; + case IVTV_HW_I2C_IR_RX_ADAPTEC: + init_data->get_key = get_key_adaptec; init_data->name = itv->card_name; + /* FIXME: The protocol and RC_MAP needs to be corrected */ + init_data->ir_codes = RC_MAP_EMPTY; + init_data->type = RC_TYPE_UNKNOWN; break; } @@ -218,8 +253,6 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) const unsigned short addr_list[] = { 0x1a, /* Hauppauge IR external - collides with WM8739 */ 0x18, /* Hauppauge IR internal */ - 0x71, /* Hauppauge IR (PVR150) */ - 0x6b, /* Adaptec IR */ I2C_CLIENT_END }; @@ -239,19 +272,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) return -1; if (hw == IVTV_HW_TUNER) { /* special tuner handling */ - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, NULL, type, - 0, itv->card_i2c->radio); + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, + itv->card_i2c->radio); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, NULL, type, - 0, itv->card_i2c->demod); + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, + itv->card_i2c->demod); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, NULL, type, - 0, itv->card_i2c->tv); + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, + itv->card_i2c->tv); if (sd) sd->grp_id = 1 << idx; return sd ? 0 : -1; @@ -267,17 +297,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) /* It's an I2C device other than an analog tuner or IR chip */ if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, NULL, type, 0, I2C_ADDRS(hw_addrs[idx])); + adap, type, 0, I2C_ADDRS(hw_addrs[idx])); } else if (hw == IVTV_HW_CX25840) { struct cx25840_platform_data pdata; pdata.pvr150_workaround = itv->pvr150_workaround; sd = v4l2_i2c_new_subdev_cfg(&itv->v4l2_dev, - adap, NULL, type, 0, &pdata, hw_addrs[idx], - NULL); + adap, type, 0, &pdata, hw_addrs[idx], NULL); } else { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, NULL, type, hw_addrs[idx], NULL); + adap, type, hw_addrs[idx], NULL); } if (sd) sd->grp_id = 1 << idx; diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index e1c347e5ebd..2dfa957b0fd 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -92,54 +92,97 @@ static int odd_parity(u8 c) return c & 1; } -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt) +static void ivtv_write_vbi_line(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *d, + struct vbi_cc *cc, int *found_cc) { struct vbi_info *vi = &itv->vbi; - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - int found_cc = 0; - size_t i; - - for (i = 0; i < cnt; i++) { - const struct v4l2_sliced_vbi_data *d = sliced + i; - if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { - if (d->field) { - cc.even[0] = d->data[0]; - cc.even[1] = d->data[1]; - } else { - cc.odd[0] = d->data[0]; - cc.odd[1] = d->data[1]; - } - found_cc = 1; + if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { + if (d->field) { + cc->even[0] = d->data[0]; + cc->even[1] = d->data[1]; + } else { + cc->odd[0] = d->data[0]; + cc->odd[1] = d->data[1]; } - else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { - struct vbi_vps vps; - - vps.data[0] = d->data[2]; - vps.data[1] = d->data[8]; - vps.data[2] = d->data[9]; - vps.data[3] = d->data[10]; - vps.data[4] = d->data[11]; - if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { - vi->vps_payload = vps; - set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); - } + *found_cc = 1; + } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { + struct vbi_vps vps; + + vps.data[0] = d->data[2]; + vps.data[1] = d->data[8]; + vps.data[2] = d->data[9]; + vps.data[3] = d->data[10]; + vps.data[4] = d->data[11]; + if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { + vi->vps_payload = vps; + set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); } - else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { - int wss = d->data[0] | d->data[1] << 8; + } else if (d->id == V4L2_SLICED_WSS_625 && + d->line == 23 && d->field == 0) { + int wss = d->data[0] | d->data[1] << 8; - if (vi->wss_payload != wss) { - vi->wss_payload = wss; - set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); - } + if (vi->wss_payload != wss) { + vi->wss_payload = wss; + set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); } } - if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { - vi->cc_payload[vi->cc_payload_idx++] = cc; +} + +static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc) +{ + struct vbi_info *vi = &itv->vbi; + + if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { + memcpy(&vi->cc_payload[vi->cc_payload_idx], cc, + sizeof(struct vbi_cc)); + vi->cc_payload_idx++; set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); } } +static void ivtv_write_vbi(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + + for (i = 0; i < cnt; i++) + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); +} + +ssize_t +ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + struct v4l2_sliced_vbi_data d; + ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data); + + for (i = 0; i < cnt; i++) { + if (copy_from_user(&d, sliced + i, + sizeof(struct v4l2_sliced_vbi_data))) { + ret = -EFAULT; + break; + } + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + } + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); + + return ret; +} + static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) { int line = 0; diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index 970567b9194..166dd0b75d0 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -20,7 +20,10 @@ #ifndef IVTV_VBI_H #define IVTV_VBI_H -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count); +ssize_t +ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t count); void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, u64 pts_stamp, int streamtype); int ivtv_used_line(struct ivtv *itv, int line, int field); diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 3b19f5b25a7..c179041d91f 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -524,7 +524,6 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) { struct m2mtest_q_data *q_data; struct videobuf_queue *vq; - int ret = 0; vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) @@ -534,12 +533,9 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) if (!q_data) return -EINVAL; - mutex_lock(&vq->vb_lock); - if (videobuf_queue_is_busy(vq)) { v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); - ret = -EBUSY; - goto out; + return -EBUSY; } q_data->fmt = find_format(f); @@ -553,9 +549,7 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) "Setting format for type %d, wxh: %dx%d, fmt: %d\n", f->type, q_data->width, q_data->height, q_data->fmt->fourcc); -out: - mutex_unlock(&vq->vb_lock); - return ret; + return 0; } static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, @@ -845,10 +839,12 @@ static void queue_init(void *priv, struct videobuf_queue *vq, enum v4l2_buf_type type) { struct m2mtest_ctx *ctx = priv; + struct m2mtest_dev *dev = ctx->dev; - videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev, - &ctx->dev->irqlock, type, V4L2_FIELD_NONE, - sizeof(struct m2mtest_buffer), priv, NULL); + videobuf_queue_vmalloc_init(vq, &m2mtest_qops, dev->v4l2_dev.dev, + &dev->irqlock, type, V4L2_FIELD_NONE, + sizeof(struct m2mtest_buffer), priv, + &dev->dev_mutex); } @@ -920,7 +916,7 @@ static const struct v4l2_file_operations m2mtest_fops = { .open = m2mtest_open, .release = m2mtest_release, .poll = m2mtest_poll, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = m2mtest_mmap, }; @@ -965,6 +961,7 @@ static int m2mtest_probe(struct platform_device *pdev) } *vfd = m2mtest_videodev; + vfd->lock = &dev->dev_mutex; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 2be23bccd3c..48d2c2419c1 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = { .open = meye_open, .release = meye_release, .mmap = meye_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .poll = meye_poll, }; @@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, msleep(1); mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); - if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, - video_nr) < 0) { - v4l2_err(v4l2_dev, "video_register_device failed\n"); - goto outvideoreg; - } - mutex_init(&meye.lock); init_waitqueue_head(&meye.proc_list); meye.brightness = 32 << 10; @@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev, sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0); sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); + if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, + video_nr) < 0) { + v4l2_err(v4l2_dev, "video_register_device failed\n"); + goto outvideoreg; + } + v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n", MEYE_DRIVER_VERSION); v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n", diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index fcb4cd94185..f7fc88d240e 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -798,7 +798,6 @@ static int mt9m001_remove(struct i2c_client *client) icd->ops = NULL; mt9m001_video_remove(icd); - client->driver = NULL; kfree(mt9m001); return 0; diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 525a16e7328..53fa2a7bf15 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -1092,7 +1092,6 @@ static int mt9m111_remove(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; - client->driver = NULL; kfree(mt9m111); return 0; diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 9bd44a816ea..7ce279c3751 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -896,7 +896,6 @@ static int mt9t031_remove(struct i2c_client *client) if (icd) icd->ops = NULL; - client->driver = NULL; kfree(mt9t031); return 0; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index b96171cc79f..6a784c87e5f 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -930,7 +930,6 @@ static int mt9v022_remove(struct i2c_client *client) icd->ops = NULL; mt9v022_video_remove(icd); - client->driver = NULL; kfree(mt9v022); return 0; diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 5e486a88ad7..bc0c23a1009 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -382,10 +382,9 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, struct mx1_camera_dev *pcdev = ici->priv; videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent, - &pcdev->lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_NONE, - sizeof(struct mx1_buffer), icd, NULL); + &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct mx1_buffer), icd, &icd->video_lock); } static int mclk_get_divisor(struct mx1_camera_dev *pcdev) diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 072bd2d1cfa..4eab1c62031 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -683,7 +683,8 @@ static void mx2_camera_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_NONE, sizeof(struct mx2_buffer), icd, NULL); + V4L2_FIELD_NONE, sizeof(struct mx2_buffer), + icd, &icd->video_lock); } #define MX2_BUS_FLAGS (SOCAM_DATAWIDTH_8 | \ @@ -807,8 +808,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd, if (common_flags & SOCAM_PCLK_SAMPLE_RISING) csicr1 |= CSICR1_REDGE; - if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) - csicr1 |= CSICR1_INV_PCLK; if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) csicr1 |= CSICR1_SOF_POL; if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH) diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index aa871c2936b..b9cb4a43695 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -443,7 +443,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, sizeof(struct mx3_camera_buffer), icd, - NULL); + &icd->video_lock); } /* First part of ipu_csi_init_interface() */ @@ -1186,13 +1186,12 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) goto egetres; } - mx3_cam = vmalloc(sizeof(*mx3_cam)); + mx3_cam = vzalloc(sizeof(*mx3_cam)); if (!mx3_cam) { dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); err = -ENOMEM; goto ealloc; } - memset(mx3_cam, 0, sizeof(*mx3_cam)); mx3_cam->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(mx3_cam->clk)) { diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 94ba698d0ad..e8846a09b02 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -59,10 +59,10 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); enum { TUNER, AUX1, AUX3, AUX3_YC }; static struct v4l2_input mxb_inputs[MXB_INPUTS] = { - { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; /* this array holds the information, which port of the saa7146 each @@ -185,17 +185,17 @@ static int mxb_probe(struct saa7146_dev *dev) } mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - NULL, "saa7111", I2C_SAA7111A, NULL); + "saa7111", I2C_SAA7111A, NULL); mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - NULL, "tea6420", I2C_TEA6420_1, NULL); + "tea6420", I2C_TEA6420_1, NULL); mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - NULL, "tea6420", I2C_TEA6420_2, NULL); + "tea6420", I2C_TEA6420_2, NULL); mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - NULL, "tea6415c", I2C_TEA6415C, NULL); + "tea6415c", I2C_TEA6415C, NULL); mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - NULL, "tda9840", I2C_TDA9840, NULL); + "tda9840", I2C_TDA9840, NULL); mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - NULL, "tuner", I2C_TUNER, NULL); + "tuner", I2C_TUNER, NULL); /* check if all devices are present */ if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c || diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 15f8793e325..83de97ad971 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -2230,7 +2230,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); - /* need to register for a VID_HARDWARE_* ID in videodev.h */ vfd->fops = &omap_vout_fops; vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; mutex_init(&vout->lock); diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index cbfd07f2d9d..0a2fb2bfdbf 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c @@ -1365,12 +1365,12 @@ static void omap1_cam_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct omap1_cam_buf), icd, NULL); + sizeof(struct omap1_cam_buf), icd, &icd->video_lock); else videobuf_queue_sg_init(q, &omap1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct omap1_cam_buf), icd, NULL); + sizeof(struct omap1_cam_buf), icd, &icd->video_lock); /* use videobuf mode (auto)selected with the module parameter */ pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; diff --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c new file mode 100644 index 00000000000..0cea0cf3667 --- /dev/null +++ b/drivers/media/video/ov2640.c @@ -0,0 +1,1205 @@ +/* + * ov2640 Camera Driver + * + * Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com> + * + * Based on ov772x, ov9640 drivers and previous non merged implementations. + * + * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2006, OmniVision + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/videodev2.h> +#include <media/v4l2-chip-ident.h> +#include <media/v4l2-subdev.h> +#include <media/soc_camera.h> +#include <media/soc_mediabus.h> + +#define VAL_SET(x, mask, rshift, lshift) \ + ((((x) >> rshift) & mask) << lshift) +/* + * DSP registers + * register offset for BANK_SEL == BANK_SEL_DSP + */ +#define R_BYPASS 0x05 /* Bypass DSP */ +#define R_BYPASS_DSP_BYPAS 0x01 /* Bypass DSP, sensor out directly */ +#define R_BYPASS_USE_DSP 0x00 /* Use the internal DSP */ +#define QS 0x44 /* Quantization Scale Factor */ +#define CTRLI 0x50 +#define CTRLI_LP_DP 0x80 +#define CTRLI_ROUND 0x40 +#define CTRLI_V_DIV_SET(x) VAL_SET(x, 0x3, 0, 3) +#define CTRLI_H_DIV_SET(x) VAL_SET(x, 0x3, 0, 0) +#define HSIZE 0x51 /* H_SIZE[7:0] (real/4) */ +#define HSIZE_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define VSIZE 0x52 /* V_SIZE[7:0] (real/4) */ +#define VSIZE_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define XOFFL 0x53 /* OFFSET_X[7:0] */ +#define XOFFL_SET(x) VAL_SET(x, 0xFF, 0, 0) +#define YOFFL 0x54 /* OFFSET_Y[7:0] */ +#define YOFFL_SET(x) VAL_SET(x, 0xFF, 0, 0) +#define VHYX 0x55 /* Offset and size completion */ +#define VHYX_VSIZE_SET(x) VAL_SET(x, 0x1, (8+2), 7) +#define VHYX_HSIZE_SET(x) VAL_SET(x, 0x1, (8+2), 3) +#define VHYX_YOFF_SET(x) VAL_SET(x, 0x3, 8, 4) +#define VHYX_XOFF_SET(x) VAL_SET(x, 0x3, 8, 0) +#define DPRP 0x56 +#define TEST 0x57 /* Horizontal size completion */ +#define TEST_HSIZE_SET(x) VAL_SET(x, 0x1, (9+2), 7) +#define ZMOW 0x5A /* Zoom: Out Width OUTW[7:0] (real/4) */ +#define ZMOW_OUTW_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define ZMOH 0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */ +#define ZMOH_OUTH_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define ZMHH 0x5C /* Zoom: Speed and H&W completion */ +#define ZMHH_ZSPEED_SET(x) VAL_SET(x, 0x0F, 0, 4) +#define ZMHH_OUTH_SET(x) VAL_SET(x, 0x1, (8+2), 2) +#define ZMHH_OUTW_SET(x) VAL_SET(x, 0x3, (8+2), 0) +#define BPADDR 0x7C /* SDE Indirect Register Access: Address */ +#define BPDATA 0x7D /* SDE Indirect Register Access: Data */ +#define CTRL2 0x86 /* DSP Module enable 2 */ +#define CTRL2_DCW_EN 0x20 +#define CTRL2_SDE_EN 0x10 +#define CTRL2_UV_ADJ_EN 0x08 +#define CTRL2_UV_AVG_EN 0x04 +#define CTRL2_CMX_EN 0x01 +#define CTRL3 0x87 /* DSP Module enable 3 */ +#define CTRL3_BPC_EN 0x80 +#define CTRL3_WPC_EN 0x40 +#define SIZEL 0x8C /* Image Size Completion */ +#define SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6) +#define SIZEL_HSIZE8_SET(x) VAL_SET(x, 0x7, 0, 3) +#define SIZEL_VSIZE8_SET(x) VAL_SET(x, 0x7, 0, 0) +#define HSIZE8 0xC0 /* Image Horizontal Size HSIZE[10:3] */ +#define HSIZE8_SET(x) VAL_SET(x, 0xFF, 3, 0) +#define VSIZE8 0xC1 /* Image Vertical Size VSIZE[10:3] */ +#define VSIZE8_SET(x) VAL_SET(x, 0xFF, 3, 0) +#define CTRL0 0xC2 /* DSP Module enable 0 */ +#define CTRL0_AEC_EN 0x80 +#define CTRL0_AEC_SEL 0x40 +#define CTRL0_STAT_SEL 0x20 +#define CTRL0_VFIRST 0x10 +#define CTRL0_YUV422 0x08 +#define CTRL0_YUV_EN 0x04 +#define CTRL0_RGB_EN 0x02 +#define CTRL0_RAW_EN 0x01 +#define CTRL1 0xC3 /* DSP Module enable 1 */ +#define CTRL1_CIP 0x80 +#define CTRL1_DMY 0x40 +#define CTRL1_RAW_GMA 0x20 +#define CTRL1_DG 0x10 +#define CTRL1_AWB 0x08 +#define CTRL1_AWB_GAIN 0x04 +#define CTRL1_LENC 0x02 +#define CTRL1_PRE 0x01 +#define R_DVP_SP 0xD3 /* DVP output speed control */ +#define R_DVP_SP_AUTO_MODE 0x80 +#define R_DVP_SP_DVP_MASK 0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0); + * = sysclk (48)/(2*[6:0]) (RAW);*/ +#define IMAGE_MODE 0xDA /* Image Output Format Select */ +#define IMAGE_MODE_Y8_DVP_EN 0x40 +#define IMAGE_MODE_JPEG_EN 0x10 +#define IMAGE_MODE_YUV422 0x00 +#define IMAGE_MODE_RAW10 0x04 /* (DVP) */ +#define IMAGE_MODE_RGB565 0x08 +#define IMAGE_MODE_HREF_VSYNC 0x02 /* HREF timing select in DVP JPEG output + * mode (0 for HREF is same as sensor) */ +#define IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP + * 1: Low byte first UYVY (C2[4] =0) + * VYUY (C2[4] =1) + * 0: High byte first YUYV (C2[4]=0) + * YVYU (C2[4] = 1) */ +#define RESET 0xE0 /* Reset */ +#define RESET_MICROC 0x40 +#define RESET_SCCB 0x20 +#define RESET_JPEG 0x10 +#define RESET_DVP 0x04 +#define RESET_IPU 0x02 +#define RESET_CIF 0x01 +#define REGED 0xED /* Register ED */ +#define REGED_CLK_OUT_DIS 0x10 +#define MS_SP 0xF0 /* SCCB Master Speed */ +#define SS_ID 0xF7 /* SCCB Slave ID */ +#define SS_CTRL 0xF8 /* SCCB Slave Control */ +#define SS_CTRL_ADD_AUTO_INC 0x20 +#define SS_CTRL_EN 0x08 +#define SS_CTRL_DELAY_CLK 0x04 +#define SS_CTRL_ACC_EN 0x02 +#define SS_CTRL_SEN_PASS_THR 0x01 +#define MC_BIST 0xF9 /* Microcontroller misc register */ +#define MC_BIST_RESET 0x80 /* Microcontroller Reset */ +#define MC_BIST_BOOT_ROM_SEL 0x40 +#define MC_BIST_12KB_SEL 0x20 +#define MC_BIST_12KB_MASK 0x30 +#define MC_BIST_512KB_SEL 0x08 +#define MC_BIST_512KB_MASK 0x0C +#define MC_BIST_BUSY_BIT_R 0x02 +#define MC_BIST_MC_RES_ONE_SH_W 0x02 +#define MC_BIST_LAUNCH 0x01 +#define BANK_SEL 0xFF /* Register Bank Select */ +#define BANK_SEL_DSP 0x00 +#define BANK_SEL_SENS 0x01 + +/* + * Sensor registers + * register offset for BANK_SEL == BANK_SEL_SENS + */ +#define GAIN 0x00 /* AGC - Gain control gain setting */ +#define COM1 0x03 /* Common control 1 */ +#define COM1_1_DUMMY_FR 0x40 +#define COM1_3_DUMMY_FR 0x80 +#define COM1_7_DUMMY_FR 0xC0 +#define COM1_VWIN_LSB_UXGA 0x0F +#define COM1_VWIN_LSB_SVGA 0x0A +#define COM1_VWIN_LSB_CIF 0x06 +#define REG04 0x04 /* Register 04 */ +#define REG04_DEF 0x20 /* Always set */ +#define REG04_HFLIP_IMG 0x80 /* Horizontal mirror image ON/OFF */ +#define REG04_VFLIP_IMG 0x40 /* Vertical flip image ON/OFF */ +#define REG04_VREF_EN 0x10 +#define REG04_HREF_EN 0x08 +#define REG04_AEC_SET(x) VAL_SET(x, 0x3, 0, 0) +#define REG08 0x08 /* Frame Exposure One-pin Control Pre-charge Row Num */ +#define COM2 0x09 /* Common control 2 */ +#define COM2_SOFT_SLEEP_MODE 0x10 /* Soft sleep mode */ + /* Output drive capability */ +#define COM2_OCAP_Nx_SET(N) (((N) - 1) & 0x03) /* N = [1x .. 4x] */ +#define PID 0x0A /* Product ID Number MSB */ +#define VER 0x0B /* Product ID Number LSB */ +#define COM3 0x0C /* Common control 3 */ +#define COM3_BAND_50H 0x04 /* 0 For Banding at 60H */ +#define COM3_BAND_AUTO 0x02 /* Auto Banding */ +#define COM3_SING_FR_SNAPSH 0x01 /* 0 For enable live video output after the + * snapshot sequence*/ +#define AEC 0x10 /* AEC[9:2] Exposure Value */ +#define CLKRC 0x11 /* Internal clock */ +#define CLKRC_EN 0x80 +#define CLKRC_DIV_SET(x) (((x) - 1) & 0x1F) /* CLK = XVCLK/(x) */ +#define COM7 0x12 /* Common control 7 */ +#define COM7_SRST 0x80 /* Initiates system reset. All registers are + * set to factory default values after which + * the chip resumes normal operation */ +#define COM7_RES_UXGA 0x00 /* Resolution selectors for UXGA */ +#define COM7_RES_SVGA 0x40 /* SVGA */ +#define COM7_RES_CIF 0x20 /* CIF */ +#define COM7_ZOOM_EN 0x04 /* Enable Zoom mode */ +#define COM7_COLOR_BAR_TEST 0x02 /* Enable Color Bar Test Pattern */ +#define COM8 0x13 /* Common control 8 */ +#define COM8_DEF 0xC0 /* Banding filter ON/OFF */ +#define COM8_BNDF_EN 0x20 /* Banding filter ON/OFF */ +#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */ +#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */ +#define COM9 0x14 /* Common control 9 + * Automatic gain ceiling - maximum AGC value [7:5]*/ +#define COM9_AGC_GAIN_2x 0x00 /* 000 : 2x */ +#define COM9_AGC_GAIN_4x 0x20 /* 001 : 4x */ +#define COM9_AGC_GAIN_8x 0x40 /* 010 : 8x */ +#define COM9_AGC_GAIN_16x 0x60 /* 011 : 16x */ +#define COM9_AGC_GAIN_32x 0x80 /* 100 : 32x */ +#define COM9_AGC_GAIN_64x 0xA0 /* 101 : 64x */ +#define COM9_AGC_GAIN_128x 0xC0 /* 110 : 128x */ +#define COM10 0x15 /* Common control 10 */ +#define COM10_PCLK_HREF 0x20 /* PCLK output qualified by HREF */ +#define COM10_PCLK_RISE 0x10 /* Data is updated at the rising edge of + * PCLK (user can latch data at the next + * falling edge of PCLK). + * 0 otherwise. */ +#define COM10_HREF_INV 0x08 /* Invert HREF polarity: + * HREF negative for valid data*/ +#define COM10_VSINC_INV 0x02 /* Invert VSYNC polarity */ +#define HSTART 0x17 /* Horizontal Window start MSB 8 bit */ +#define HEND 0x18 /* Horizontal Window end MSB 8 bit */ +#define VSTART 0x19 /* Vertical Window start MSB 8 bit */ +#define VEND 0x1A /* Vertical Window end MSB 8 bit */ +#define MIDH 0x1C /* Manufacturer ID byte - high */ +#define MIDL 0x1D /* Manufacturer ID byte - low */ +#define AEW 0x24 /* AGC/AEC - Stable operating region (upper limit) */ +#define AEB 0x25 /* AGC/AEC - Stable operating region (lower limit) */ +#define VV 0x26 /* AGC/AEC Fast mode operating region */ +#define VV_HIGH_TH_SET(x) VAL_SET(x, 0xF, 0, 4) +#define VV_LOW_TH_SET(x) VAL_SET(x, 0xF, 0, 0) +#define REG2A 0x2A /* Dummy pixel insert MSB */ +#define FRARL 0x2B /* Dummy pixel insert LSB */ +#define ADDVFL 0x2D /* LSB of insert dummy lines in Vertical direction */ +#define ADDVFH 0x2E /* MSB of insert dummy lines in Vertical direction */ +#define YAVG 0x2F /* Y/G Channel Average value */ +#define REG32 0x32 /* Common Control 32 */ +#define REG32_PCLK_DIV_2 0x80 /* PCLK freq divided by 2 */ +#define REG32_PCLK_DIV_4 0xC0 /* PCLK freq divided by 4 */ +#define ARCOM2 0x34 /* Zoom: Horizontal start point */ +#define REG45 0x45 /* Register 45 */ +#define FLL 0x46 /* Frame Length Adjustment LSBs */ +#define FLH 0x47 /* Frame Length Adjustment MSBs */ +#define COM19 0x48 /* Zoom: Vertical start point */ +#define ZOOMS 0x49 /* Zoom: Vertical start point */ +#define COM22 0x4B /* Flash light control */ +#define COM25 0x4E /* For Banding operations */ +#define BD50 0x4F /* 50Hz Banding AEC 8 LSBs */ +#define BD60 0x50 /* 60Hz Banding AEC 8 LSBs */ +#define REG5D 0x5D /* AVGsel[7:0], 16-zone average weight option */ +#define REG5E 0x5E /* AVGsel[15:8], 16-zone average weight option */ +#define REG5F 0x5F /* AVGsel[23:16], 16-zone average weight option */ +#define REG60 0x60 /* AVGsel[31:24], 16-zone average weight option */ +#define HISTO_LOW 0x61 /* Histogram Algorithm Low Level */ +#define HISTO_HIGH 0x62 /* Histogram Algorithm High Level */ + +/* + * ID + */ +#define MANUFACTURER_ID 0x7FA2 +#define PID_OV2640 0x2642 +#define VERSION(pid, ver) ((pid << 8) | (ver & 0xFF)) + +/* + * Struct + */ +struct regval_list { + u8 reg_num; + u8 value; +}; + +/* Supported resolutions */ +enum ov2640_width { + W_QCIF = 176, + W_QVGA = 320, + W_CIF = 352, + W_VGA = 640, + W_SVGA = 800, + W_XGA = 1024, + W_SXGA = 1280, + W_UXGA = 1600, +}; + +enum ov2640_height { + H_QCIF = 144, + H_QVGA = 240, + H_CIF = 288, + H_VGA = 480, + H_SVGA = 600, + H_XGA = 768, + H_SXGA = 1024, + H_UXGA = 1200, +}; + +struct ov2640_win_size { + char *name; + enum ov2640_width width; + enum ov2640_height height; + const struct regval_list *regs; +}; + + +struct ov2640_priv { + struct v4l2_subdev subdev; + struct ov2640_camera_info *info; + enum v4l2_mbus_pixelcode cfmt_code; + const struct ov2640_win_size *win; + int model; + u16 flag_vflip:1; + u16 flag_hflip:1; +}; + +/* + * Registers settings + */ + +#define ENDMARKER { 0xff, 0xff } + +static const struct regval_list ov2640_init_regs[] = { + { BANK_SEL, BANK_SEL_DSP }, + { 0x2c, 0xff }, + { 0x2e, 0xdf }, + { BANK_SEL, BANK_SEL_SENS }, + { 0x3c, 0x32 }, + { CLKRC, CLKRC_DIV_SET(1) }, + { COM2, COM2_OCAP_Nx_SET(3) }, + { REG04, REG04_DEF | REG04_HREF_EN }, + { COM8, COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN }, + { COM9, COM9_AGC_GAIN_8x | 0x08}, + { 0x2c, 0x0c }, + { 0x33, 0x78 }, + { 0x3a, 0x33 }, + { 0x3b, 0xfb }, + { 0x3e, 0x00 }, + { 0x43, 0x11 }, + { 0x16, 0x10 }, + { 0x39, 0x02 }, + { 0x35, 0x88 }, + { 0x22, 0x0a }, + { 0x37, 0x40 }, + { 0x23, 0x00 }, + { ARCOM2, 0xa0 }, + { 0x06, 0x02 }, + { 0x06, 0x88 }, + { 0x07, 0xc0 }, + { 0x0d, 0xb7 }, + { 0x0e, 0x01 }, + { 0x4c, 0x00 }, + { 0x4a, 0x81 }, + { 0x21, 0x99 }, + { AEW, 0x40 }, + { AEB, 0x38 }, + { VV, VV_HIGH_TH_SET(0x08) | VV_LOW_TH_SET(0x02) }, + { 0x5c, 0x00 }, + { 0x63, 0x00 }, + { FLL, 0x22 }, + { COM3, 0x38 | COM3_BAND_AUTO }, + { REG5D, 0x55 }, + { REG5E, 0x7d }, + { REG5F, 0x7d }, + { REG60, 0x55 }, + { HISTO_LOW, 0x70 }, + { HISTO_HIGH, 0x80 }, + { 0x7c, 0x05 }, + { 0x20, 0x80 }, + { 0x28, 0x30 }, + { 0x6c, 0x00 }, + { 0x6d, 0x80 }, + { 0x6e, 0x00 }, + { 0x70, 0x02 }, + { 0x71, 0x94 }, + { 0x73, 0xc1 }, + { 0x3d, 0x34 }, + { COM7, COM7_RES_UXGA | COM7_ZOOM_EN }, + { 0x5a, 0x57 }, + { BD50, 0xbb }, + { BD60, 0x9c }, + { BANK_SEL, BANK_SEL_DSP }, + { 0xe5, 0x7f }, + { MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL }, + { 0x41, 0x24 }, + { RESET, RESET_JPEG | RESET_DVP }, + { 0x76, 0xff }, + { 0x33, 0xa0 }, + { 0x42, 0x20 }, + { 0x43, 0x18 }, + { 0x4c, 0x00 }, + { CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 }, + { 0x88, 0x3f }, + { 0xd7, 0x03 }, + { 0xd9, 0x10 }, + { R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x2 }, + { 0xc8, 0x08 }, + { 0xc9, 0x80 }, + { BPADDR, 0x00 }, + { BPDATA, 0x00 }, + { BPADDR, 0x03 }, + { BPDATA, 0x48 }, + { BPDATA, 0x48 }, + { BPADDR, 0x08 }, + { BPDATA, 0x20 }, + { BPDATA, 0x10 }, + { BPDATA, 0x0e }, + { 0x90, 0x00 }, + { 0x91, 0x0e }, + { 0x91, 0x1a }, + { 0x91, 0x31 }, + { 0x91, 0x5a }, + { 0x91, 0x69 }, + { 0x91, 0x75 }, + { 0x91, 0x7e }, + { 0x91, 0x88 }, + { 0x91, 0x8f }, + { 0x91, 0x96 }, + { 0x91, 0xa3 }, + { 0x91, 0xaf }, + { 0x91, 0xc4 }, + { 0x91, 0xd7 }, + { 0x91, 0xe8 }, + { 0x91, 0x20 }, + { 0x92, 0x00 }, + { 0x93, 0x06 }, + { 0x93, 0xe3 }, + { 0x93, 0x03 }, + { 0x93, 0x03 }, + { 0x93, 0x00 }, + { 0x93, 0x02 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x96, 0x00 }, + { 0x97, 0x08 }, + { 0x97, 0x19 }, + { 0x97, 0x02 }, + { 0x97, 0x0c }, + { 0x97, 0x24 }, + { 0x97, 0x30 }, + { 0x97, 0x28 }, + { 0x97, 0x26 }, + { 0x97, 0x02 }, + { 0x97, 0x98 }, + { 0x97, 0x80 }, + { 0x97, 0x00 }, + { 0x97, 0x00 }, + { 0xa4, 0x00 }, + { 0xa8, 0x00 }, + { 0xc5, 0x11 }, + { 0xc6, 0x51 }, + { 0xbf, 0x80 }, + { 0xc7, 0x10 }, + { 0xb6, 0x66 }, + { 0xb8, 0xA5 }, + { 0xb7, 0x64 }, + { 0xb9, 0x7C }, + { 0xb3, 0xaf }, + { 0xb4, 0x97 }, + { 0xb5, 0xFF }, + { 0xb0, 0xC5 }, + { 0xb1, 0x94 }, + { 0xb2, 0x0f }, + { 0xc4, 0x5c }, + { 0xa6, 0x00 }, + { 0xa7, 0x20 }, + { 0xa7, 0xd8 }, + { 0xa7, 0x1b }, + { 0xa7, 0x31 }, + { 0xa7, 0x00 }, + { 0xa7, 0x18 }, + { 0xa7, 0x20 }, + { 0xa7, 0xd8 }, + { 0xa7, 0x19 }, + { 0xa7, 0x31 }, + { 0xa7, 0x00 }, + { 0xa7, 0x18 }, + { 0xa7, 0x20 }, + { 0xa7, 0xd8 }, + { 0xa7, 0x19 }, + { 0xa7, 0x31 }, + { 0xa7, 0x00 }, + { 0xa7, 0x18 }, + { 0x7f, 0x00 }, + { 0xe5, 0x1f }, + { 0xe1, 0x77 }, + { 0xdd, 0x7f }, + { CTRL0, CTRL0_YUV422 | CTRL0_YUV_EN | CTRL0_RGB_EN }, + ENDMARKER, +}; + +/* + * Register settings for window size + * The preamble, setup the internal DSP to input an UXGA (1600x1200) image. + * Then the different zooming configurations will setup the output image size. + */ +static const struct regval_list ov2640_size_change_preamble_regs[] = { + { BANK_SEL, BANK_SEL_DSP }, + { RESET, RESET_DVP }, + { HSIZE8, HSIZE8_SET(W_UXGA) }, + { VSIZE8, VSIZE8_SET(H_UXGA) }, + { CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN | + CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN }, + { HSIZE, HSIZE_SET(W_UXGA) }, + { VSIZE, VSIZE_SET(H_UXGA) }, + { XOFFL, XOFFL_SET(0) }, + { YOFFL, YOFFL_SET(0) }, + { VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) | + VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)}, + { TEST, TEST_HSIZE_SET(W_UXGA) }, + ENDMARKER, +}; + +#define PER_SIZE_REG_SEQ(x, y, v_div, h_div, pclk_div) \ + { CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) | \ + CTRLI_H_DIV_SET(h_div)}, \ + { ZMOW, ZMOW_OUTW_SET(x) }, \ + { ZMOH, ZMOH_OUTH_SET(y) }, \ + { ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y) }, \ + { R_DVP_SP, pclk_div }, \ + { RESET, 0x00} + +static const struct regval_list ov2640_qcif_regs[] = { + PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4), + ENDMARKER, +}; + +static const struct regval_list ov2640_qvga_regs[] = { + PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4), + ENDMARKER, +}; + +static const struct regval_list ov2640_cif_regs[] = { + PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8), + ENDMARKER, +}; + +static const struct regval_list ov2640_vga_regs[] = { + PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2), + ENDMARKER, +}; + +static const struct regval_list ov2640_svga_regs[] = { + PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2), + ENDMARKER, +}; + +static const struct regval_list ov2640_xga_regs[] = { + PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2), + { CTRLI, 0x00}, + ENDMARKER, +}; + +static const struct regval_list ov2640_sxga_regs[] = { + PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2), + { CTRLI, 0x00}, + { R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE }, + ENDMARKER, +}; + +static const struct regval_list ov2640_uxga_regs[] = { + PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0), + { CTRLI, 0x00}, + { R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE }, + ENDMARKER, +}; + +#define OV2640_SIZE(n, w, h, r) \ + {.name = n, .width = w , .height = h, .regs = r } + +static const struct ov2640_win_size ov2640_supported_win_sizes[] = { + OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs), + OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs), + OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs), + OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs), + OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs), + OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs), + OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs), + OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs), +}; + +/* + * Register settings for pixel formats + */ +static const struct regval_list ov2640_format_change_preamble_regs[] = { + { BANK_SEL, BANK_SEL_DSP }, + { R_BYPASS, R_BYPASS_USE_DSP }, + ENDMARKER, +}; + +static const struct regval_list ov2640_yuv422_regs[] = { + { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 }, + { 0xD7, 0x01 }, + { 0x33, 0xa0 }, + { 0xe1, 0x67 }, + { RESET, 0x00 }, + { R_BYPASS, R_BYPASS_USE_DSP }, + ENDMARKER, +}; + +static const struct regval_list ov2640_rgb565_regs[] = { + { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 }, + { 0xd7, 0x03 }, + { RESET, 0x00 }, + { R_BYPASS, R_BYPASS_USE_DSP }, + ENDMARKER, +}; + +static enum v4l2_mbus_pixelcode ov2640_codes[] = { + V4L2_MBUS_FMT_UYVY8_2X8, + V4L2_MBUS_FMT_RGB565_2X8_LE, +}; + +/* + * Supported controls + */ +static const struct v4l2_queryctrl ov2640_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + +/* + * General functions + */ +static struct ov2640_priv *to_ov2640(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct ov2640_priv, + subdev); +} + +static int ov2640_write_array(struct i2c_client *client, + const struct regval_list *vals) +{ + int ret; + + while ((vals->reg_num != 0xff) || (vals->value != 0xff)) { + ret = i2c_smbus_write_byte_data(client, + vals->reg_num, vals->value); + dev_vdbg(&client->dev, "array: 0x%02x, 0x%02x", + vals->reg_num, vals->value); + + if (ret < 0) + return ret; + vals++; + } + return 0; +} + +static int ov2640_mask_set(struct i2c_client *client, + u8 reg, u8 mask, u8 set) +{ + s32 val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) + return val; + + val &= ~mask; + val |= set & mask; + + dev_vdbg(&client->dev, "masks: 0x%02x, 0x%02x", reg, val); + + return i2c_smbus_write_byte_data(client, reg, val); +} + +static int ov2640_reset(struct i2c_client *client) +{ + int ret; + const struct regval_list reset_seq[] = { + {BANK_SEL, BANK_SEL_SENS}, + {COM7, COM7_SRST}, + ENDMARKER, + }; + + ret = ov2640_write_array(client, reset_seq); + if (ret) + goto err; + + msleep(5); +err: + dev_dbg(&client->dev, "%s: (ret %d)", __func__, ret); + return ret; +} + +/* + * soc_camera_ops functions + */ +static int ov2640_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + +static int ov2640_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + if (icl->set_bus_param) + return icl->set_bus_param(icl, width_flag); + + /* + * Without board specific bus width settings we support only the + * sensors native bus width witch are tested working + */ + if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8)) + return 0; + + return 0; +} + +static unsigned long ov2640_query_bus_param(struct soc_camera_device *icd) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH; + + if (icl->query_bus_param) + flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK; + else + flags |= SOCAM_DATAWIDTH_10; + + return soc_camera_apply_sensor_flags(icl, flags); +} + +static int ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + ctrl->value = priv->flag_vflip; + break; + case V4L2_CID_HFLIP: + ctrl->value = priv->flag_hflip; + break; + } + return 0; +} + +static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + int ret = 0; + u8 val; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + val = ctrl->value ? REG04_VFLIP_IMG : 0x00; + priv->flag_vflip = ctrl->value ? 1 : 0; + ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val); + break; + case V4L2_CID_HFLIP: + val = ctrl->value ? REG04_HFLIP_IMG : 0x00; + priv->flag_hflip = ctrl->value ? 1 : 0; + ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val); + break; + } + + return ret; +} + +static int ov2640_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + + id->ident = priv->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ov2640_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + reg->size = 1; + if (reg->reg > 0xff) + return -EINVAL; + + ret = i2c_smbus_read_byte_data(client, reg->reg); + if (ret < 0) + return ret; + + reg->val = ret; + + return 0; +} + +static int ov2640_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (reg->reg > 0xff || + reg->val > 0xff) + return -EINVAL; + + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); +} +#endif + +/* Select the nearest higher resolution for capture */ +static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height) +{ + int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1; + + for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) { + if (ov2640_supported_win_sizes[i].width >= *width && + ov2640_supported_win_sizes[i].height >= *height) { + *width = ov2640_supported_win_sizes[i].width; + *height = ov2640_supported_win_sizes[i].height; + return &ov2640_supported_win_sizes[i]; + } + } + + *width = ov2640_supported_win_sizes[default_size].width; + *height = ov2640_supported_win_sizes[default_size].height; + return &ov2640_supported_win_sizes[default_size]; +} + +static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height, + enum v4l2_mbus_pixelcode code) +{ + struct ov2640_priv *priv = to_ov2640(client); + const struct regval_list *selected_cfmt_regs; + int ret; + + /* select win */ + priv->win = ov2640_select_win(width, height); + + /* select format */ + priv->cfmt_code = 0; + switch (code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__); + selected_cfmt_regs = ov2640_rgb565_regs; + break; + default: + case V4L2_MBUS_FMT_UYVY8_2X8: + dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__); + selected_cfmt_regs = ov2640_yuv422_regs; + } + + /* reset hardware */ + ov2640_reset(client); + + /* initialize the sensor with default data */ + dev_dbg(&client->dev, "%s: Init default", __func__); + ret = ov2640_write_array(client, ov2640_init_regs); + if (ret < 0) + goto err; + + /* select preamble */ + dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name); + ret = ov2640_write_array(client, ov2640_size_change_preamble_regs); + if (ret < 0) + goto err; + + /* set size win */ + ret = ov2640_write_array(client, priv->win->regs); + if (ret < 0) + goto err; + + /* cfmt preamble */ + dev_dbg(&client->dev, "%s: Set cfmt", __func__); + ret = ov2640_write_array(client, ov2640_format_change_preamble_regs); + if (ret < 0) + goto err; + + /* set cfmt */ + ret = ov2640_write_array(client, selected_cfmt_regs); + if (ret < 0) + goto err; + + priv->cfmt_code = code; + *width = priv->win->width; + *height = priv->win->height; + + return 0; + +err: + dev_err(&client->dev, "%s: Error %d", __func__, ret); + ov2640_reset(client); + priv->win = NULL; + + return ret; +} + +static int ov2640_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + + if (!priv->win) { + u32 width = W_SVGA, height = H_SVGA; + int ret = ov2640_set_params(client, &width, &height, + V4L2_MBUS_FMT_UYVY8_2X8); + if (ret < 0) + return ret; + } + + mf->width = priv->win->width; + mf->height = priv->win->height; + mf->code = priv->cfmt_code; + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + case V4L2_MBUS_FMT_UYVY8_2X8: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } + mf->field = V4L2_FIELD_NONE; + + return 0; +} + +static int ov2640_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + case V4L2_MBUS_FMT_UYVY8_2X8: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } + + ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code); + + return ret; +} + +static int ov2640_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + const struct ov2640_win_size *win; + + /* + * select suitable win + */ + win = ov2640_select_win(&mf->width, &mf->height); + + mf->field = V4L2_FIELD_NONE; + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + case V4L2_MBUS_FMT_UYVY8_2X8: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } + + return 0; +} + +static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index >= ARRAY_SIZE(ov2640_codes)) + return -EINVAL; + + *code = ov2640_codes[index]; + return 0; +} + +static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = W_UXGA; + a->c.height = H_UXGA; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = W_UXGA; + a->bounds.height = H_UXGA; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ov2640_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) +{ + struct ov2640_priv *priv = to_ov2640(client); + u8 pid, ver, midh, midl; + const char *devname; + int ret; + + /* + * we must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. + */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) { + dev_err(&client->dev, "Parent missing or invalid!\n"); + ret = -ENODEV; + goto err; + } + + /* + * check and show product ID and manufacturer ID + */ + i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS); + pid = i2c_smbus_read_byte_data(client, PID); + ver = i2c_smbus_read_byte_data(client, VER); + midh = i2c_smbus_read_byte_data(client, MIDH); + midl = i2c_smbus_read_byte_data(client, MIDL); + + switch (VERSION(pid, ver)) { + case PID_OV2640: + devname = "ov2640"; + priv->model = V4L2_IDENT_OV2640; + break; + default: + dev_err(&client->dev, + "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; + goto err; + } + + dev_info(&client->dev, + "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", + devname, pid, ver, midh, midl); + + return 0; + +err: + return ret; +} + +static struct soc_camera_ops ov2640_ops = { + .set_bus_param = ov2640_set_bus_param, + .query_bus_param = ov2640_query_bus_param, + .controls = ov2640_controls, + .num_controls = ARRAY_SIZE(ov2640_controls), +}; + +static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { + .g_ctrl = ov2640_g_ctrl, + .s_ctrl = ov2640_s_ctrl, + .g_chip_ident = ov2640_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ov2640_g_register, + .s_register = ov2640_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = { + .s_stream = ov2640_s_stream, + .g_mbus_fmt = ov2640_g_fmt, + .s_mbus_fmt = ov2640_s_fmt, + .try_mbus_fmt = ov2640_try_fmt, + .cropcap = ov2640_cropcap, + .g_crop = ov2640_g_crop, + .enum_mbus_fmt = ov2640_enum_fmt, +}; + +static struct v4l2_subdev_ops ov2640_subdev_ops = { + .core = &ov2640_subdev_core_ops, + .video = &ov2640_subdev_video_ops, +}; + +/* + * i2c_driver functions + */ +static int ov2640_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct ov2640_priv *priv; + struct soc_camera_device *icd = client->dev.platform_data; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; + int ret; + + if (!icd) { + dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); + if (!icl) { + dev_err(&adapter->dev, + "OV2640: Missing platform_data for driver\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&adapter->dev, + "OV2640: I2C-Adapter doesn't support SMBUS\n"); + return -EIO; + } + + priv = kzalloc(sizeof(struct ov2640_priv), GFP_KERNEL); + if (!priv) { + dev_err(&adapter->dev, + "Failed to allocate memory for private data!\n"); + return -ENOMEM; + } + + priv->info = icl->priv; + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops); + + icd->ops = &ov2640_ops; + + ret = ov2640_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + kfree(priv); + } else { + dev_info(&adapter->dev, "OV2640 Probed\n"); + } + + return ret; +} + +static int ov2640_remove(struct i2c_client *client) +{ + struct ov2640_priv *priv = to_ov2640(client); + struct soc_camera_device *icd = client->dev.platform_data; + + icd->ops = NULL; + kfree(priv); + return 0; +} + +static const struct i2c_device_id ov2640_id[] = { + { "ov2640", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ov2640_id); + +static struct i2c_driver ov2640_i2c_driver = { + .driver = { + .name = "ov2640", + }, + .probe = ov2640_probe, + .remove = ov2640_remove, + .id_table = ov2640_id, +}; + +/* + * Module functions + */ +static int __init ov2640_module_init(void) +{ + return i2c_add_driver(&ov2640_i2c_driver); +} + +static void __exit ov2640_module_exit(void) +{ + i2c_del_driver(&ov2640_i2c_driver); +} + +module_init(ov2640_module_init); +module_exit(ov2640_module_exit); + +MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); +MODULE_AUTHOR("Alberto Panizzo"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index a84b770352f..48895ef863f 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -600,7 +600,7 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); if (!enable) { ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); @@ -645,8 +645,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -665,7 +664,7 @@ static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); int ret = 0; u8 val; @@ -715,8 +714,7 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov772x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); id->ident = priv->model; id->revision = 0; @@ -955,7 +953,7 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); if (!priv->win || !priv->cfmt) { u32 width = VGA_WIDTH, height = VGA_HEIGHT; @@ -978,7 +976,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); int ret = ov772x_set_params(client, &mf->width, &mf->height, mf->code); @@ -991,8 +989,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, static int ov772x_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); const struct ov772x_win_size *win; int i; diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 99e9e1d3c83..53d88a2ab92 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -31,6 +31,8 @@ #include "ov9640.h" +#define to_ov9640_sensor(sd) container_of(sd, struct ov9640_priv, subdev) + /* default register setup */ static const struct ov9640_reg ov9640_regs_dflt[] = { { OV9640_COM5, OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP }, @@ -308,9 +310,7 @@ static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd) /* Get status of additional camera capabilities */ static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), - struct ov9640_priv, subdev); + struct ov9640_priv *priv = to_ov9640_sensor(sd); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -327,8 +327,7 @@ static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), - struct ov9640_priv, subdev); + struct ov9640_priv *priv = to_ov9640_sensor(sd); int ret = 0; @@ -360,9 +359,7 @@ static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov9640_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), - struct ov9640_priv, subdev); + struct ov9640_priv *priv = to_ov9640_sensor(sd); id->ident = priv->model; id->revision = priv->revision; @@ -654,7 +651,8 @@ static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int ov9640_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct ov9640_priv *priv = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9640_priv *priv = to_ov9640_sensor(sd); u8 pid, ver, midh, midl; const char *devname; int ret = 0; @@ -791,7 +789,8 @@ static int ov9640_probe(struct i2c_client *client, static int ov9640_remove(struct i2c_client *client) { - struct ov9640_priv *priv = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9640_priv *priv = to_ov9640_sensor(sd); kfree(priv); return 0; diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 7129b50757d..7551907f8c2 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf, static const struct v4l2_file_operations pms_fops = { .owner = THIS_MODULE, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .read = pms_read, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 55ea914c7fc..7d5a7139a45 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -203,7 +203,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, *blen = 0; LOCK_TAKE(cptr->hdw->big_lock); do { if (cptr->info->type == pvr2_ctl_enum) { - const char **names; + const char * const *names; names = cptr->info->def.type_enum.value_names; if (pvr2_ctrl_range_check(cptr,val) == 0) { if (names[val]) { @@ -367,7 +367,7 @@ static const char *boolNames[] = { static int parse_token(const char *ptr,unsigned int len, int *valptr, - const char **names,unsigned int namecnt) + const char * const *names, unsigned int namecnt) { char buf[33]; unsigned int slen; @@ -559,7 +559,7 @@ int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr, *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false"); ret = 0; } else if (cptr->info->type == pvr2_ctl_enum) { - const char **names; + const char * const *names; names = cptr->info->def.type_enum.value_names; if ((val >= 0) && (val < cptr->info->def.type_enum.count)) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index cb4057bb07a..ac94a8bf883 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -115,7 +115,7 @@ struct pvr2_ctl_info { } type_int; struct { /* enumerated control */ unsigned int count; /* enum value count */ - const char **value_names; /* symbol names */ + const char * const *value_names; /* symbol names */ } type_enum; struct { /* bitmask control */ unsigned int valid_bits; /* bits in use */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index bef202752cc..66ad516bdfd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2088,16 +2088,14 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, " Setting up with specified i2c address 0x%x", mid, i2caddr[0]); sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, - NULL, fname, - i2caddr[0], NULL); + fname, i2caddr[0], NULL); } else { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" " Setting up with address probe list", mid); sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, - NULL, fname, - 0, i2caddr); + fname, 0, i2caddr); } if (!sd) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 3d7e5aab547..281806b2df6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -647,7 +647,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp, if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "device_register failed"); - kfree(class_dev); + put_device(class_dev); return; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index aaafa0398fd..58617fc656c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -852,8 +852,8 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) #endif default : - ret = v4l_compat_translate_ioctl(file, cmd, - arg, pvr2_v4l2_do_ioctl); + ret = -EINVAL; + break; } pvr2_hdw_commit_ctl(hdw); diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 6b8fbddc074..1593f8deb81 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -1386,11 +1386,16 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { ARG_DEF(int, qual) + if (pdev->iso_init) { + ret = -EBUSY; + break; + } + ARG_IN(qual) if (ARGR(qual) < 0 || ARGR(qual) > 3) ret = -EINVAL; else - ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); + ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); if (ret >= 0) pdev->vcompression = ARGR(qual); break; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index f3dc89da4c4..bd1519a4ecb 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -287,14 +287,13 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) /* create frame buffers, and make circular ring */ for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data == NULL) { - kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ + kbuf = vzalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ if (kbuf == NULL) { PWC_ERROR("Failed to allocate frame buffer %d.\n", i); return -ENOMEM; } PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf); pdev->fbuf[i].data = kbuf; - memset(kbuf, 0, PWC_FRAME_SIZE); } } @@ -899,10 +898,13 @@ int pwc_isoc_init(struct pwc_device *pdev) /* link */ for (i = 0; i < MAX_ISO_BUFS; i++) { ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); - if (ret) + if (ret) { PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); - else - PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); + pdev->iso_init = 1; + pwc_isoc_cleanup(pdev); + return ret; + } + PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); } /* All is done... */ @@ -958,7 +960,7 @@ void pwc_isoc_cleanup(struct pwc_device *pdev) /* Stop camera, but only if we are sure the camera is still there (unplug is signalled by EPIPE) */ - if (pdev->error_status && pdev->error_status != EPIPE) { + if (pdev->error_status != EPIPE) { PWC_DEBUG_OPEN("Setting alternate interface 0.\n"); usb_set_interface(pdev->udev, 0, 0); } @@ -967,36 +969,6 @@ void pwc_isoc_cleanup(struct pwc_device *pdev) PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); } -int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) -{ - int ret, start; - - /* Stop isoc stuff */ - pwc_isoc_cleanup(pdev); - /* Reset parameters */ - pwc_reset_buffers(pdev); - /* Try to set video mode... */ - start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); - if (ret) { - PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n"); - /* That failed... restore old mode (we know that worked) */ - start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - if (start) { - PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n"); - } - } - if (start == 0) - { - if (pwc_isoc_init(pdev) < 0) - { - PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); - ret = -EAGAIN; /* let's try again, who knows if it works a second time */ - } - } - pdev->drop_frames++; /* try to avoid garbage during switch */ - return ret; /* Return original error code */ -} - /********* * sysfs *********/ @@ -1176,7 +1148,7 @@ static int pwc_video_open(struct file *file) /* Set some defaults */ pdev->vsnapshot = 0; - /* Start iso pipe for video; first try the last used video size + /* Set video size, first try the last used video size (or the default one); if that fails try QCIF/10 or QSIF/10; it that fails too, give up. */ @@ -1203,15 +1175,6 @@ static int pwc_video_open(struct file *file) return i; } - i = pwc_isoc_init(pdev); - if (i) { - PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i); - pwc_isoc_cleanup(pdev); - pwc_free_buffers(pdev); - mutex_unlock(&pdev->modlock); - return i; - } - /* Initialize the webcam to sane value */ pwc_set_brightness(pdev, 0x7fff); pwc_set_agc(pdev, 1, 0); @@ -1326,6 +1289,11 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, goto err_out; } + /* Start the stream (if not already started) */ + rv = pwc_isoc_init(pdev); + if (rv) + goto err_out; + /* In case we're doing partial reads, we don't have to wait for a frame */ if (pdev->image_read_pos == 0) { /* Do wait queueing according to the (doc)book */ @@ -1395,6 +1363,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; + int ret; if (vdev == NULL) return -EFAULT; @@ -1402,6 +1371,13 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) if (pdev == NULL) return -EFAULT; + /* Start the stream (if not already started) */ + mutex_lock(&pdev->modlock); + ret = pwc_isoc_init(pdev); + mutex_unlock(&pdev->modlock); + if (ret) + return ret; + poll_wait(file, &pdev->frameq, wait); if (pdev->error_status) return POLLERR; diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 7061a03f5cf..8ca4d22b438 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -309,7 +309,10 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) pixelformat != V4L2_PIX_FMT_PWC2) return -EINVAL; - PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d " + if (pdev->iso_init) + return -EBUSY; + + PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " "compression=%d snapshot=%d format=%c%c%c%c\n", f->fmt.pix.width, f->fmt.pix.height, fps, compression, snapshot, @@ -318,14 +321,14 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) (pixelformat>>16)&255, (pixelformat>>24)&255); - ret = pwc_try_video_mode(pdev, + ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height, fps, compression, snapshot); - PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret); + PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); if (ret) return ret; @@ -359,23 +362,6 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* mmap() functions */ - case VIDIOCGMBUF: - { - /* Tell the user program how much memory is needed for a mmap() */ - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = pwc_mbufs * pdev->len_per_image; - vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */ - for (i = 0; i < pwc_mbufs; i++) - vm->offsets[i] = i * pdev->len_per_image; - break; - } -#endif - /* V4L2 Layer */ case VIDIOC_QUERYCAP: { @@ -882,9 +868,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_STREAMON: { - /* WARNING: pwc_try_video_mode() called pwc_isoc_init */ - pwc_isoc_init(pdev); - return 0; + return pwc_isoc_init(pdev); } case VIDIOC_STREAMOFF: diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 36a9c83b5f5..16bbc6df9b0 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -275,7 +275,6 @@ extern int pwc_trace; extern int pwc_mbufs; /** functions in pwc-if.c */ -int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); int pwc_handle_frame(struct pwc_device *pdev); void pwc_next_image(struct pwc_device *pdev); int pwc_isoc_init(struct pwc_device *pdev); diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index c143ed0a527..02686771740 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -852,7 +852,7 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, */ videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct pxa_buffer), icd, NULL); + sizeof(struct pxa_buffer), icd, &icd->video_lock); } static u32 mclk_get_divisor(struct platform_device *pdev, diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index d2fa2d43ff1..57e11b6f19f 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -1460,7 +1460,6 @@ static int rj54n1_remove(struct i2c_client *client) icd->ops = NULL; if (icl->free_bus) icl->free_bus(icl); - client->driver = NULL; kfree(rj54n1); return 0; diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index a845753665c..b63f8cafa67 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -268,7 +268,7 @@ struct s2255_dev { struct v4l2_device v4l2_dev; atomic_t num_channels; int frames; - struct mutex lock; + struct mutex lock; /* channels[].vdev.lock */ struct mutex open_lock; struct usb_device *udev; struct usb_interface *interface; @@ -780,20 +780,14 @@ static struct videobuf_queue_ops s2255_video_qops = { static int res_get(struct s2255_fh *fh) { - struct s2255_dev *dev = fh->dev; - /* is it free? */ struct s2255_channel *channel = fh->channel; - mutex_lock(&dev->lock); - if (channel->resources) { - /* no, someone else uses it */ - mutex_unlock(&dev->lock); - return 0; - } + /* is it free? */ + if (channel->resources) + return 0; /* no, someone else uses it */ /* it's free, grab it */ channel->resources = 1; fh->resources = 1; dprintk(1, "s2255: res: get\n"); - mutex_unlock(&dev->lock); return 1; } @@ -811,11 +805,8 @@ static int res_check(struct s2255_fh *fh) static void res_free(struct s2255_fh *fh) { struct s2255_channel *channel = fh->channel; - struct s2255_dev *dev = fh->dev; - mutex_lock(&dev->lock); channel->resources = 0; fh->resources = 0; - mutex_unlock(&dev->lock); dprintk(1, "res: put\n"); } @@ -1106,15 +1097,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) return rc; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidioc_cgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct s2255_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - /* write to the configuration pipe, synchronously */ static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf, int size) @@ -1218,7 +1200,6 @@ static int s2255_set_mode(struct s2255_channel *channel, __le32 *buffer; unsigned long chn_rev; struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); - mutex_lock(&dev->lock); chn_rev = G_chnmap[channel->idx]; dprintk(3, "%s channel: %d\n", __func__, channel->idx); /* if JPEG, set the quality */ @@ -1235,7 +1216,6 @@ static int s2255_set_mode(struct s2255_channel *channel, buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); - mutex_unlock(&dev->lock); return -ENOMEM; } /* set the mode */ @@ -1260,7 +1240,6 @@ static int s2255_set_mode(struct s2255_channel *channel, } /* clear the restart flag */ channel->mode.restart = 0; - mutex_unlock(&dev->lock); dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res); return res; } @@ -1271,13 +1250,11 @@ static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus) __le32 *buffer; u32 chn_rev; struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); - mutex_lock(&dev->lock); chn_rev = G_chnmap[channel->idx]; dprintk(4, "%s chan %d\n", __func__, channel->idx); buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); - mutex_unlock(&dev->lock); return -ENOMEM; } /* form the get vid status command */ @@ -1297,7 +1274,6 @@ static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus) } *pstatus = channel->vidstatus; dprintk(4, "%s, vid status %d\n", __func__, *pstatus); - mutex_unlock(&dev->lock); return res; } @@ -1816,7 +1792,8 @@ static int s2255_open(struct file *file) NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, - sizeof(struct s2255_buffer), fh, NULL); + sizeof(struct s2255_buffer), + fh, vdev->lock); return 0; } @@ -1899,7 +1876,7 @@ static const struct v4l2_file_operations s2255_fops_v4l = { .open = s2255_open, .release = s2255_release, .poll = s2255_poll, - .ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = s2255_mmap_v4l, }; @@ -1923,9 +1900,6 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidioc_cgmbuf, -#endif .vidioc_s_jpegcomp = vidioc_s_jpegcomp, .vidioc_g_jpegcomp = vidioc_g_jpegcomp, .vidioc_s_parm = vidioc_s_parm, @@ -1969,6 +1943,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) channel->vidq.dev = dev; /* register 4 video devices */ channel->vdev = template; + channel->vdev.lock = &dev->lock; channel->vdev.v4l2_dev = &dev->v4l2_dev; video_set_drvdata(&channel->vdev, channel); if (video_nr == -1) @@ -2675,7 +2650,9 @@ static void s2255_disconnect(struct usb_interface *interface) struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); int i; int channels = atomic_read(&dev->num_channels); + mutex_lock(&dev->lock); v4l2_device_disconnect(&dev->v4l2_dev); + mutex_unlock(&dev->lock); /*see comments in the uvc_driver.c usb disconnect function */ atomic_inc(&dev->num_channels); /* unregister each video device. */ diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index e8f13d3e2df..2f500809f53 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -44,7 +44,7 @@ static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc, return ERR_PTR(-ENOMEM); sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap, - MODULE_NAME, isp_info->board_info, NULL); + isp_info->board_info, NULL); if (!sd) { v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n"); return NULL; @@ -522,6 +522,7 @@ static int fimc_cap_streamon(struct file *file, void *priv, INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); fimc->vid_cap.active_buf_cnt = 0; fimc->vid_cap.frame_count = 0; + fimc->vid_cap.buf_index = fimc_hw_get_frame_index(fimc); set_bit(ST_CAPT_PEND, &fimc->state); ret = videobuf_streamon(&fimc->vid_cap.vbq); @@ -652,6 +653,50 @@ static int fimc_cap_s_ctrl(struct file *file, void *priv, return ret; } +static int fimc_cap_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *cr) +{ + struct fimc_frame *f; + struct fimc_ctx *ctx = fh; + struct fimc_dev *fimc = ctx->fimc_dev; + + if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + + f = &ctx->s_frame; + cr->bounds.left = 0; + cr->bounds.top = 0; + cr->bounds.width = f->o_width; + cr->bounds.height = f->o_height; + cr->defrect = cr->bounds; + + mutex_unlock(&fimc->lock); + return 0; +} + +static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) +{ + struct fimc_frame *f; + struct fimc_ctx *ctx = file->private_data; + struct fimc_dev *fimc = ctx->fimc_dev; + + + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + + f = &ctx->s_frame; + cr->c.left = f->offs_h; + cr->c.top = f->offs_v; + cr->c.width = f->width; + cr->c.height = f->height; + + mutex_unlock(&fimc->lock); + return 0; +} + static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) { @@ -716,9 +761,9 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { .vidioc_g_ctrl = fimc_vidioc_g_ctrl, .vidioc_s_ctrl = fimc_cap_s_ctrl, - .vidioc_g_crop = fimc_vidioc_g_crop, + .vidioc_g_crop = fimc_cap_g_crop, .vidioc_s_crop = fimc_cap_s_crop, - .vidioc_cropcap = fimc_vidioc_cropcap, + .vidioc_cropcap = fimc_cap_cropcap, .vidioc_enum_input = fimc_cap_enum_input, .vidioc_s_input = fimc_cap_s_input, @@ -785,7 +830,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc) videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops, vid_cap->v4l2_dev.dev, &fimc->irqlock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct fimc_vid_buffer), (void *)ctx); + sizeof(struct fimc_vid_buffer), (void *)ctx, NULL); ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret) { diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 2e7c547894b..817aa66627f 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -50,8 +50,8 @@ static struct fimc_fmt fimc_formats[] = { .planes_cnt = 1, .flags = FMT_FLAGS_M2M, }, { - .name = "XRGB-8-8-8-8, 24 bpp", - .fourcc = V4L2_PIX_FMT_RGB24, + .name = "XRGB-8-8-8-8, 32 bpp", + .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .color = S5P_FIMC_RGB888, .buff_cnt = 1, @@ -543,7 +543,7 @@ static void fimc_dma_run(void *priv) unsigned long flags; u32 ret; - if (WARN(!ctx, "null hardware context")) + if (WARN(!ctx, "null hardware context\n")) return; fimc = ctx->fimc_dev; @@ -983,6 +983,7 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv, { struct fimc_ctx *ctx = priv; struct v4l2_queryctrl *c; + int ret = -EINVAL; c = get_ctrl(qc->id); if (c) { @@ -990,10 +991,14 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv, return 0; } - if (ctx->state & FIMC_CTX_CAP) - return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd, + if (ctx->state & FIMC_CTX_CAP) { + if (mutex_lock_interruptible(&ctx->fimc_dev->lock)) + return -ERESTARTSYS; + ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd, core, queryctrl, qc); - return -EINVAL; + mutex_unlock(&ctx->fimc_dev->lock); + } + return ret; } int fimc_vidioc_g_ctrl(struct file *file, void *priv, @@ -1115,7 +1120,7 @@ static int fimc_m2m_s_ctrl(struct file *file, void *priv, return 0; } -int fimc_vidioc_cropcap(struct file *file, void *fh, +static int fimc_m2m_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cr) { struct fimc_frame *frame; @@ -1139,7 +1144,7 @@ int fimc_vidioc_cropcap(struct file *file, void *fh, return 0; } -int fimc_vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) +static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) { struct fimc_frame *frame; struct fimc_ctx *ctx = file->private_data; @@ -1167,22 +1172,22 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) struct fimc_frame *f; u32 min_size, halign; - f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? - &ctx->s_frame : &ctx->d_frame; - if (cr->c.top < 0 || cr->c.left < 0) { v4l2_err(&fimc->m2m.v4l2_dev, "doesn't support negative values for top & left\n"); return -EINVAL; } - f = ctx_get_frame(ctx, cr->type); - if (IS_ERR(f)) - return PTR_ERR(f); + if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame; + else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + ctx->state & FIMC_CTX_M2M) + f = &ctx->s_frame; + else + return -EINVAL; - min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - ? fimc->variant->min_inp_pixsize - : fimc->variant->min_out_pixsize; + min_size = (f == &ctx->s_frame) ? + fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; if (ctx->state & FIMC_CTX_M2M) { if (fimc->id == 1 && fimc->variant->pix_hoff) @@ -1233,6 +1238,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? &ctx->s_frame : &ctx->d_frame; + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + spin_lock_irqsave(&ctx->slock, flags); if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) { /* Check to see if scaling ratio is within supported range */ @@ -1241,9 +1249,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) else ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame); if (ret) { - spin_unlock_irqrestore(&ctx->slock, flags); v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); - return -EINVAL; + ret = -EINVAL; + goto scr_unlock; } } ctx->state |= FIMC_PARAMS; @@ -1253,7 +1261,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) f->width = cr->c.width; f->height = cr->c.height; +scr_unlock: spin_unlock_irqrestore(&ctx->slock, flags); + mutex_unlock(&fimc->lock); return 0; } @@ -1285,9 +1295,9 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { .vidioc_g_ctrl = fimc_vidioc_g_ctrl, .vidioc_s_ctrl = fimc_m2m_s_ctrl, - .vidioc_g_crop = fimc_vidioc_g_crop, + .vidioc_g_crop = fimc_m2m_g_crop, .vidioc_s_crop = fimc_m2m_s_crop, - .vidioc_cropcap = fimc_vidioc_cropcap + .vidioc_cropcap = fimc_m2m_cropcap }; @@ -1396,7 +1406,7 @@ static const struct v4l2_file_operations fimc_m2m_fops = { .open = fimc_m2m_open, .release = fimc_m2m_release, .poll = fimc_m2m_poll, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = fimc_m2m_mmap, }; @@ -1736,6 +1746,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = { .pix_hoff = 1, .has_inp_rot = 1, .has_out_rot = 1, + .has_cistatus2 = 1, .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 1, @@ -1745,6 +1756,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = { static struct samsung_fimc_variant fimc2_variant_s5pv310 = { .pix_hoff = 1, + .has_cistatus2 = 1, .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 1, diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 3e107851656..4f047d35f8a 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -13,13 +13,15 @@ /*#define DEBUG*/ +#include <linux/sched.h> #include <linux/types.h> +#include <linux/videodev2.h> #include <media/videobuf-core.h> #include <media/v4l2-device.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-mediabus.h> #include <media/s3c_fimc.h> -#include <linux/videodev2.h> + #include "regs-fimc.h" #define err(fmt, args...) \ @@ -369,6 +371,7 @@ struct fimc_pix_limit { * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes * @has_inp_rot: set if has input rotator * @has_out_rot: set if has output rotator + * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision * @pix_limit: pixel size constraints for the scaler * @min_inp_pixsize: minimum input pixel size * @min_out_pixsize: minimum output pixel size @@ -379,6 +382,7 @@ struct samsung_fimc_variant { unsigned int pix_hoff:1; unsigned int has_inp_rot:1; unsigned int has_out_rot:1; + unsigned int has_cistatus2:1; struct fimc_pix_limit *pix_limit; u16 min_inp_pixsize; u16 min_out_pixsize; @@ -554,11 +558,19 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, return frame; } +/* Return an index to the buffer actually being written. */ static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev) { - u32 reg = readl(dev->regs + S5P_CISTATUS); - return (reg & S5P_CISTATUS_FRAMECNT_MASK) >> - S5P_CISTATUS_FRAMECNT_SHIFT; + u32 reg; + + if (dev->variant->has_cistatus2) { + reg = readl(dev->regs + S5P_CISTATUS2) & 0x3F; + return reg > 0 ? --reg : reg; + } else { + reg = readl(dev->regs + S5P_CISTATUS); + return (reg & S5P_CISTATUS_FRAMECNT_MASK) >> + S5P_CISTATUS_FRAMECNT_SHIFT; + } } /* -----------------------------------------------------*/ @@ -594,10 +606,6 @@ int fimc_vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f); int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f); -int fimc_vidioc_g_crop(struct file *file, void *fh, - struct v4l2_crop *cr); -int fimc_vidioc_cropcap(struct file *file, void *fh, - struct v4l2_cropcap *cr); int fimc_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc); int fimc_vidioc_g_ctrl(struct file *file, void *priv, diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h index a57daedb5b5..57e33f84fcf 100644 --- a/drivers/media/video/s5p-fimc/regs-fimc.h +++ b/drivers/media/video/s5p-fimc/regs-fimc.h @@ -165,6 +165,9 @@ #define S5P_CISTATUS_VVALID_A (1 << 15) #define S5P_CISTATUS_VVALID_B (1 << 14) +/* Indexes to the last and the currently processed buffer. */ +#define S5P_CISTATUS2 0x68 + /* Image capture control */ #define S5P_CIIMGCPT 0xc0 #define S5P_CIIMGCPT_IMGCPTEN (1 << 31) diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 984c0feb2a4..99a2ac16f9e 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -31,7 +31,7 @@ #include <linux/wait.h> #include <asm/uaccess.h> -#include <media/rds.h> +#include <media/saa6588.h> #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> @@ -181,7 +181,7 @@ static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf) return 1; } -static void read_from_buf(struct saa6588 *s, struct rds_command *a) +static void read_from_buf(struct saa6588 *s, struct saa6588_command *a) { unsigned long flags; @@ -392,25 +392,25 @@ static void saa6588_configure(struct saa6588 *s) static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct saa6588 *s = to_saa6588(sd); - struct rds_command *a = arg; + struct saa6588_command *a = arg; switch (cmd) { /* --- open() for /dev/radio --- */ - case RDS_CMD_OPEN: + case SAA6588_CMD_OPEN: a->result = 0; /* return error if chip doesn't work ??? */ break; /* --- close() for /dev/radio --- */ - case RDS_CMD_CLOSE: + case SAA6588_CMD_CLOSE: s->data_available_for_read = 1; wake_up_interruptible(&s->read_queue); a->result = 0; break; /* --- read() for /dev/radio --- */ - case RDS_CMD_READ: + case SAA6588_CMD_READ: read_from_buf(s, a); break; /* --- poll() for /dev/radio --- */ - case RDS_CMD_POLL: + case SAA6588_CMD_POLL: a->result = 0; if (s->data_available_for_read) { a->result |= POLLIN | POLLRDNORM; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 301c62b88ca..f35459d1f42 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1348,8 +1348,17 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) int reg1e; *std = V4L2_STD_ALL; - if (state->ident != V4L2_IDENT_SAA7115) + if (state->ident != V4L2_IDENT_SAA7115) { + int reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); + + if (reg1f & 0x20) + *std = V4L2_STD_525_60; + else + *std = V4L2_STD_625_50; + return 0; + } + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); switch (reg1e & 0x03) { diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 3fe71be41a1..380f1b28cfc 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -26,7 +26,7 @@ config VIDEO_SAA7134_ALSA config VIDEO_SAA7134_RC bool "Philips SAA7134 Remote Controller support" - depends on VIDEO_IR + depends on RC_CORE depends on VIDEO_SAA7134 default y ---help--- diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 0911cb580e1..e7aa588c6c5 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5176,6 +5176,58 @@ struct saa7134_board saa7134_boards[] = { .amux = 2, }, }, + [SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = { + .name = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid", + .audio_clock = 0x00187de7, +#if 0 + /* + * FIXME: Analog mode doesn't work, if digital is enabled. The proper + * fix is to use tda8290 driver, but Kworld seems to use an + * unsupported version of tda8295. + */ + .tuner_type = TUNER_NXP_TDA18271, /* TUNER_PHILIPS_TDA8290 */ + .tuner_addr = 0x60, +#else + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, +#endif + .radio_type = UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x8e054000, + .mpeg = SAA7134_MPEG_DVB, + .ts_type = SAA7134_MPEG_TS_PARALLEL, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, +#if 0 /* FIXME */ + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x200, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x200, +#endif + } }, +#if 0 + .radio = { + .name = name_radio, + .vmux = 1, + .amux = LINE1, + .gpio = 0x100, + }, +#endif + .mute = { + .name = name_mute, + .vmux = 0, + .amux = TV, + }, + }, [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = { .name = "Avermedia AVerTV GO 007 FM Plus", .audio_clock = 0x00187de7, @@ -5486,6 +5538,37 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, } }, }, + [SAA7134_BOARD_VIDEOMATE_M1F] = { + /* Pavel Osnova <pvosnova@gmail.com> */ + .name = "Compro VideoMate Vista M1F", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .radio_type = TUNER_TEA5767, + .tuner_addr = ADDR_UNSET, + .radio_addr = 0x60, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, }; @@ -6615,6 +6698,12 @@ struct pci_device_id saa7134_pci_tbl[] = { }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x17de, + .subdevice = 0xb136, + .driver_data = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1461, /* Avermedia Technologies Inc */ .subdevice = 0xf31d, .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, @@ -6673,6 +6762,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x7090, .driver_data = SAA7134_BOARD_BEHOLD_A7, }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7135, + .subvendor = 0x185b, + .subdevice = 0xc900, + .driver_data = SAA7134_BOARD_VIDEOMATE_M1F, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -6831,6 +6926,23 @@ static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev, return 0; } +static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev, + enum tda18271_mode mode) +{ + /* toggle AGC switch through GPIO 27 */ + switch (mode) { + case TDA18271_ANALOG: + saa7134_set_gpio(dev, 27, 0); + break; + case TDA18271_DIGITAL: + saa7134_set_gpio(dev, 27, 1); + break; + default: + return -EINVAL; + } + return 0; +} + static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, int command, int arg) { @@ -6843,6 +6955,9 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, case SAA7134_BOARD_HAUPPAUGE_HVR1120: ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); break; + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); + break; default: break; } @@ -6863,6 +6978,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_AVERMEDIA_M733A: + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); break; @@ -6967,6 +7083,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: + case SAA7134_BOARD_VIDEOMATE_M1F: case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: @@ -7541,6 +7658,37 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name); break; } + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + { + struct i2c_msg msg = { .addr = 0x4b, .flags = 0 }; + int i; + static u8 buffer[][2] = { + {0x30, 0x31}, + {0xff, 0x00}, + {0x41, 0x03}, + {0x41, 0x1a}, + {0xff, 0x02}, + {0x34, 0x00}, + {0x45, 0x97}, + {0x45, 0xc1}, + }; + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); + + /* + * FIXME: identify what device is at addr 0x4b and what means + * this initialization + */ + for (i = 0; i < ARRAY_SIZE(buffer); i++) { + msg.buf = &buffer[i][0]; + msg.len = ARRAY_SIZE(buffer[0]); + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + printk(KERN_WARNING + "%s: Unable to enable tuner(%i).\n", + dev->name, i); + } + break; + } } /* switch() */ /* initialize tuner */ @@ -7551,22 +7699,22 @@ int saa7134_board_init2(struct saa7134_dev *dev) so we do not need to probe for a radio tuner device. */ if (dev->radio_type != UNSET) v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "tuner", + &dev->i2c_adap, "tuner", dev->radio_addr, NULL); if (has_demod) v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "tuner", + &dev->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == ADDR_UNSET) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "tuner", + &dev->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(type)); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "tuner", + &dev->i2c_adap, "tuner", dev->tuner_addr, NULL); } } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 2ceeac7ae34..6abeecff6da 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -997,7 +997,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (card_is_empress(dev)) { struct v4l2_subdev *sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "saa6752hs", + "saa6752hs", saa7134_boards[dev->board].empress_addr, NULL); if (sd) @@ -1008,7 +1008,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, struct v4l2_subdev *sd; sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, NULL, "saa6588", + &dev->i2c_adap, "saa6588", 0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr)); if (sd) { printk(KERN_INFO "%s: found RDS decoder\n", dev->name); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index beb95e21d10..3315a48a848 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -52,6 +52,7 @@ #include "tda18271.h" #include "lgdt3305.h" #include "tda8290.h" +#include "mb86a20s.h" #include "zl10353.h" @@ -228,6 +229,20 @@ static struct mt352_config avermedia_xc3028_mt352_dev = { .demod_init = mt352_avermedia_xc3028_init, }; +static struct tda18271_std_map mb86a20s_tda18271_std_map = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 7, .rfagc_top = 0x37, }, +}; + +static struct tda18271_config kworld_tda18271_config = { + .std_map = &mb86a20s_tda18271_std_map, + .gate = TDA18271_GATE_DIGITAL, +}; + +static const struct mb86a20s_config kworld_mb86a20s_config = { + .demod_address = 0x10, +}; + /* ================================================================== * tda1004x based DVB-T cards, helper functions */ @@ -608,6 +623,37 @@ static struct tda827x_config tda827x_cfg_2_sw42 = { /* ------------------------------------------------------------------ */ +static int __kworld_sbtvd_i2c_gate_ctrl(struct saa7134_dev *dev, int enable) +{ + unsigned char initmsg[] = {0x45, 0x97}; + unsigned char msg_enable[] = {0x45, 0xc1}; + unsigned char msg_disable[] = {0x45, 0x81}; + struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2}; + + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { + wprintk("could not access the I2C gate\n"); + return -EIO; + } + if (enable) + msg.buf = msg_enable; + else + msg.buf = msg_disable; + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { + wprintk("could not access the I2C gate\n"); + return -EIO; + } + msleep(20); + return 0; +} +static int kworld_sbtvd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct saa7134_dev *dev = fe->dvb->priv; + + return __kworld_sbtvd_i2c_gate_ctrl(dev, enable); +} + +/* ------------------------------------------------------------------ */ + static struct tda1004x_config tda827x_lifeview_config = { .demod_address = 0x08, .invert = 1, @@ -1613,6 +1659,29 @@ static int dvb_init(struct saa7134_dev *dev) &dtv1000s_tda18271_config); } break; + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + __kworld_sbtvd_i2c_gate_ctrl(dev, 0); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000); + msleep(20); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000); + msleep(20); + fe0->dvb.frontend = dvb_attach(mb86a20s_attach, + &kworld_mb86a20s_config, + &dev->i2c_adap); + __kworld_sbtvd_i2c_gate_ctrl(dev, 1); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap, + &kworld_tda18271_config); + /* + * Only after success, it can initialize the gate, otherwise + * an OOPS will hit, due to kfree(fe0->dvb.frontend) + */ + fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_i2c_gate_ctrl; + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 46d31dfca7a..dc646e65edb 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -22,7 +22,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> -#include <linux/input.h> #include <linux/slab.h> #include "saa7134-reg.h" @@ -42,41 +41,19 @@ static int pinnacle_remote; module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); -static int ir_rc5_remote_gap = 885; -module_param(ir_rc5_remote_gap, int, 0644); -static int ir_rc5_key_timeout = 115; -module_param(ir_rc5_key_timeout, int, 0644); - -static int repeat_delay = 500; -module_param(repeat_delay, int, 0644); -MODULE_PARM_DESC(repeat_delay, "delay before key repeat started"); -static int repeat_period = 33; -module_param(repeat_period, int, 0644); -MODULE_PARM_DESC(repeat_period, "repeat period between " - "keypresses when key is down"); - -static unsigned int disable_other_ir; -module_param(disable_other_ir, int, 0644); -MODULE_PARM_DESC(disable_other_ir, "disable full codes of " - "alternative remotes from other manufacturers"); - #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) -/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ -static int saa7134_rc5_irq(struct saa7134_dev *dev); -static int saa7134_nec_irq(struct saa7134_dev *dev); +/* Helper function for raw decoding at GPIO16 or GPIO18 */ static int saa7134_raw_decode_irq(struct saa7134_dev *dev); -static void nec_task(unsigned long data); -static void saa7134_nec_timer(unsigned long data); /* -------------------- GPIO generic keycode builder -------------------- */ static int build_key(struct saa7134_dev *dev) { - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; u32 gpio, data; /* here comes the additional handshake steps for some cards */ @@ -104,25 +81,25 @@ static int build_key(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: if (data == ir->mask_keycode) - ir_input_nokey(ir->dev, &ir->ir); + rc_keyup(ir->dev); else - ir_input_keydown(ir->dev, &ir->ir, data); + rc_keydown_notimeout(ir->dev, data, 0); return 0; } if (ir->polling) { if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data); + rc_keydown_notimeout(ir->dev, data, 0); } else { - ir_input_nokey(ir->dev, &ir->ir); + rc_keyup(ir->dev); } } else { /* IRQ driven mode - handle key press and release in one go */ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data); - ir_input_nokey(ir->dev, &ir->ir); + rc_keydown_notimeout(ir->dev, data, 0); + rc_keyup(ir->dev); } } @@ -300,22 +277,12 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) i2cdprintk("read error\n"); return -EIO; } - /* IR of this card normally decode signals NEC-standard from - * - Sven IHOO MT 5.1R remote. xxyye718 - * - Sven DVD HD-10xx remote. xxyyf708 - * - BBK ... - * - mayby others - * So, skip not our, if disable full codes mode. - */ - if (data[10] != 0x6b && data[11] != 0x86 && disable_other_ir) - return 0; - /* Wrong data decode fix */ if (data[9] != (unsigned char)(~data[8])) return 0; - *ir_key = data[9]; - *ir_raw = data[9]; + *ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0)); + *ir_key = *ir_raw; return 1; } @@ -400,7 +367,7 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) void saa7134_input_irq(struct saa7134_dev *dev) { - struct card_ir *ir; + struct saa7134_card_ir *ir; if (!dev || !dev->remote) return; @@ -409,12 +376,8 @@ void saa7134_input_irq(struct saa7134_dev *dev) if (!ir->running) return; - if (ir->nec_gpio) { - saa7134_nec_irq(dev); - } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { + if (!ir->polling && !ir->raw_decode) { build_key(dev); - } else if (ir->rc5_gpio) { - saa7134_rc5_irq(dev); } else if (ir->raw_decode) { saa7134_raw_decode_irq(dev); } @@ -423,7 +386,7 @@ void saa7134_input_irq(struct saa7134_dev *dev) static void saa7134_input_timer(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; build_key(dev); mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); @@ -432,57 +395,37 @@ static void saa7134_input_timer(unsigned long data) static void ir_raw_decode_timer_end(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; ir_raw_event_handle(dev->remote->dev); - ir->active = 0; + ir->active = false; } static int __saa7134_ir_start(void *priv) { struct saa7134_dev *dev = priv; - struct card_ir *ir; + struct saa7134_card_ir *ir; - if (!dev) + if (!dev || !dev->remote) return -EINVAL; ir = dev->remote; - if (!ir) - return -EINVAL; - if (ir->running) return 0; - ir->running = 1; + ir->running = true; + ir->active = false; + if (ir->polling) { setup_timer(&ir->timer, saa7134_input_timer, (unsigned long)dev); - ir->timer.expires = jiffies + HZ; + ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); - } else if (ir->rc5_gpio) { - /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = ir_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; - init_timer(&ir->timer_keyup); - ir->timer_keyup.function = ir_rc5_timer_keyup; - ir->timer_keyup.data = (unsigned long)ir; - ir->shift_by = 2; - ir->start = 0x2; - ir->addr = 0x17; - ir->rc5_key_timeout = ir_rc5_key_timeout; - ir->rc5_remote_gap = ir_rc5_remote_gap; - } else if (ir->nec_gpio) { - setup_timer(&ir->timer_keyup, saa7134_nec_timer, - (unsigned long)dev); - tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); } else if (ir->raw_decode) { /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = ir_raw_decode_timer_end; - ir->timer_end.data = (unsigned long)dev; - ir->active = 0; + setup_timer(&ir->timer, ir_raw_decode_timer_end, + (unsigned long)dev); } return 0; @@ -491,29 +434,20 @@ static int __saa7134_ir_start(void *priv) static void __saa7134_ir_stop(void *priv) { struct saa7134_dev *dev = priv; - struct card_ir *ir; + struct saa7134_card_ir *ir; - if (!dev) + if (!dev || !dev->remote) return; ir = dev->remote; - if (!ir) - return; - if (!ir->running) return; - if (dev->remote->polling) - del_timer_sync(&dev->remote->timer); - else if (ir->rc5_gpio) - del_timer_sync(&ir->timer_end); - else if (ir->nec_gpio) - tasklet_kill(&ir->tlet); - else if (ir->raw_decode) { - del_timer_sync(&ir->timer_end); - ir->active = 0; - } - ir->running = 0; + if (ir->polling || ir->raw_decode) + del_timer_sync(&ir->timer); + + ir->active = false; + ir->running = false; return; } @@ -532,71 +466,33 @@ void saa7134_ir_stop(struct saa7134_dev *dev) __saa7134_ir_stop(dev); } -static int saa7134_ir_open(void *priv) +static int saa7134_ir_open(struct rc_dev *rc) { - struct saa7134_dev *dev = priv; + struct saa7134_dev *dev = rc->priv; dev->remote->users++; return __saa7134_ir_start(dev); } -static void saa7134_ir_close(void *priv) +static void saa7134_ir_close(struct rc_dev *rc) { - struct saa7134_dev *dev = priv; + struct saa7134_dev *dev = rc->priv; dev->remote->users--; if (!dev->remote->users) __saa7134_ir_stop(dev); } - -static int saa7134_ir_change_protocol(void *priv, u64 ir_type) -{ - struct saa7134_dev *dev = priv; - struct card_ir *ir = dev->remote; - u32 nec_gpio, rc5_gpio; - - if (ir_type == IR_TYPE_RC5) { - dprintk("Changing protocol to RC5\n"); - nec_gpio = 0; - rc5_gpio = 1; - } else if (ir_type == IR_TYPE_NEC) { - dprintk("Changing protocol to NEC\n"); - nec_gpio = 1; - rc5_gpio = 0; - } else { - dprintk("IR protocol type %ud is not supported\n", - (unsigned)ir_type); - return -EINVAL; - } - - if (ir->running) { - saa7134_ir_stop(dev); - ir->nec_gpio = nec_gpio; - ir->rc5_gpio = rc5_gpio; - saa7134_ir_start(dev); - } else { - ir->nec_gpio = nec_gpio; - ir->rc5_gpio = rc5_gpio; - } - - return 0; -} - int saa7134_input_init1(struct saa7134_dev *dev) { - struct card_ir *ir; - struct input_dev *input_dev; + struct saa7134_card_ir *ir; + struct rc_dev *rc; char *ir_codes = NULL; u32 mask_keycode = 0; u32 mask_keydown = 0; u32 mask_keyup = 0; - int polling = 0; - int rc5_gpio = 0; - int nec_gpio = 0; - int raw_decode = 0; - int allow_protocol_change = 0; - u64 ir_type = IR_TYPE_OTHER; + unsigned polling = 0; + bool raw_decode = false; int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) @@ -661,14 +557,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_AVERMEDIA_M733A: ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; mask_keydown = 0x0040000; mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: @@ -775,7 +671,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: @@ -786,9 +682,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: ir_codes = RC_MAP_ENCORE_ENLTV_FM53; - mask_keydown = 0x0040000; - mask_keycode = 0x00007f; - nec_gpio = 1; + mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ + mask_keyup = 0x0040000; + mask_keycode = 0xffff; + raw_decode = true; break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = RC_MAP_ENCORE_ENLTV; @@ -824,6 +721,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x020000; polling = 50; /* ms */ break; + case SAA7134_BOARD_VIDEOMATE_M1F: + ir_codes = RC_MAP_VIDEOMATE_M1F; + mask_keycode = 0x0ff00; + mask_keyup = 0x040000; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", @@ -832,24 +734,20 @@ int saa7134_input_init1(struct saa7134_dev *dev) } ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) { + rc = rc_allocate_device(); + if (!ir || !rc) { err = -ENOMEM; goto err_out_free; } - ir->dev = input_dev; + ir->dev = rc; dev->remote = ir; - ir->running = 0; - /* init hardware-specific stuff */ ir->mask_keycode = mask_keycode; ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; ir->polling = polling; - ir->rc5_gpio = rc5_gpio; - ir->nec_gpio = nec_gpio; ir->raw_decode = raw_decode; /* init input device */ @@ -858,47 +756,35 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - - ir->props.priv = dev; - ir->props.open = saa7134_ir_open; - ir->props.close = saa7134_ir_close; - + rc->priv = dev; + rc->open = saa7134_ir_open; + rc->close = saa7134_ir_close; if (raw_decode) - ir->props.driver_type = RC_DRIVER_IR_RAW; - - if (!raw_decode && allow_protocol_change) { - ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.change_protocol = saa7134_ir_change_protocol; - } - - err = ir_input_init(input_dev, &ir->ir, ir_type); - if (err < 0) - goto err_out_free; + rc->driver_type = RC_DRIVER_IR_RAW; - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_PCI; + rc->input_id.version = 1; if (dev->pci->subsystem_vendor) { - input_dev->id.vendor = dev->pci->subsystem_vendor; - input_dev->id.product = dev->pci->subsystem_device; + rc->input_id.vendor = dev->pci->subsystem_vendor; + rc->input_id.product = dev->pci->subsystem_device; } else { - input_dev->id.vendor = dev->pci->vendor; - input_dev->id.product = dev->pci->device; + rc->input_id.vendor = dev->pci->vendor; + rc->input_id.product = dev->pci->device; } - input_dev->dev.parent = &dev->pci->dev; + rc->dev.parent = &dev->pci->dev; + rc->map_name = ir_codes; + rc->driver_name = MODULE_NAME; - err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_free; - /* the remote isn't as bouncy as a keyboard */ - ir->dev->rep[REP_DELAY] = repeat_delay; - ir->dev->rep[REP_PERIOD] = repeat_period; - return 0; err_out_free: + rc_free_device(rc); dev->remote = NULL; kfree(ir); return err; @@ -910,7 +796,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) return; saa7134_ir_stop(dev); - ir_input_unregister(dev->remote->dev); + rc_unregister_device(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; } @@ -918,14 +804,12 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { struct i2c_board_info info; - struct i2c_msg msg_msi = { .addr = 0x50, .flags = I2C_M_RD, .len = 0, .buf = NULL, }; - int rc; if (disable_ir) { @@ -972,7 +856,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) an existing device. Weird... REVISIT: might no longer be needed */ rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); - dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", + dprintk("probe 0x%02x @ %s: %s\n", msg_msi.addr, dev->i2c_adap.name, (1 == rc) ? "yes" : "no"); break; @@ -1000,7 +884,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; dev->init_data.ir_codes = RC_MAP_BEHOLD; - dev->init_data.type = IR_TYPE_NEC; + dev->init_data.type = RC_TYPE_NEC; info.addr = 0x2d; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: @@ -1025,8 +909,8 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) static int saa7134_raw_decode_irq(struct saa7134_dev *dev) { - struct card_ir *ir = dev->remote; - unsigned long timeout; + struct saa7134_card_ir *ir = dev->remote; + unsigned long timeout; int space; /* Generate initial event */ @@ -1035,7 +919,6 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); - /* * Wait 15 ms from the start of the first IR event before processing * the event. This time is enough for NEC protocol. May need adjustments @@ -1043,173 +926,9 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) */ if (!ir->active) { timeout = jiffies + jiffies_to_msecs(15); - mod_timer(&ir->timer_end, timeout); - ir->active = 1; + mod_timer(&ir->timer, timeout); + ir->active = true; } return 1; } - -static int saa7134_rc5_irq(struct saa7134_dev *dev) -{ - struct card_ir *ir = dev->remote; - struct timeval tv; - u32 gap; - unsigned long current_jiffies, timeout; - - /* get time of bit */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* active code => add bit */ - if (ir->active) { - /* only if in the code (otherwise spurious IRQ or timer - late) */ - if (ir->last_bit < 28) { - ir->last_bit = (gap - ir_rc5_remote_gap / 2) / - ir_rc5_remote_gap; - ir->code |= 1 << ir->last_bit; - } - /* starting new code */ - } else { - ir->active = 1; - ir->code = 0; - ir->base_time = tv; - ir->last_bit = 0; - - timeout = current_jiffies + (500 + 30 * HZ) / 1000; - mod_timer(&ir->timer_end, timeout); - } - - return 1; -} - -/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms - The first pulse (start) has 9 + 4.5 ms - */ - -static void saa7134_nec_timer(unsigned long data) -{ - struct saa7134_dev *dev = (struct saa7134_dev *) data; - struct card_ir *ir = dev->remote; - - dprintk("Cancel key repeat\n"); - - ir_input_nokey(ir->dev, &ir->ir); -} - -static void nec_task(unsigned long data) -{ - struct saa7134_dev *dev = (struct saa7134_dev *) data; - struct card_ir *ir; - struct timeval tv; - int count, pulse, oldpulse, gap; - u32 ircode = 0, not_code = 0; - int ngap = 0; - - if (!data) { - printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); - /* GPIO will be kept disabled */ - return; - } - - ir = dev->remote; - - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - - oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; - pulse = oldpulse; - - do_gettimeofday(&tv); - ir->base_time = tv; - - /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. - Unfortunately, using IRQ to decode pulse didn't work, since it uses - a pulse train of 38KHz. This means one pulse on each 52 us - */ - do { - /* Wait until the end of pulse/space or 5 ms */ - for (count = 0; count < 500; count++) { - udelay(10); - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) - & ir->mask_keydown; - if (pulse != oldpulse) - break; - } - - do_gettimeofday(&tv); - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - - if (!pulse) { - /* Bit 0 has 560 us, while bit 1 has 1120 us. - Do something only if bit == 1 - */ - if (ngap && (gap > 560 + 280)) { - unsigned int shift = ngap - 1; - - /* Address first, then command */ - if (shift < 8) { - shift += 8; - ircode |= 1 << shift; - } else if (shift < 16) { - not_code |= 1 << shift; - } else if (shift < 24) { - shift -= 16; - ircode |= 1 << shift; - } else { - shift -= 24; - not_code |= 1 << shift; - } - } - ngap++; - } - - - ir->base_time = tv; - - /* TIMEOUT - Long pulse */ - if (gap >= 5000) - break; - oldpulse = pulse; - } while (ngap < 32); - - if (ngap == 32) { - /* FIXME: should check if not_code == ~ircode */ - ir->code = ir_extract_bits(ircode, ir->mask_keycode); - - dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", - ir->code, ircode, not_code); - - ir_input_keydown(ir->dev, &ir->ir, ir->code); - } else - dprintk("Repeat last key\n"); - - /* Keep repeating the last key */ - mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); - - saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); -} - -static int saa7134_nec_irq(struct saa7134_dev *dev) -{ - struct card_ir *ir = dev->remote; - - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); - tasklet_schedule(&ir->tlet); - - return 1; -} diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 3e7d2fd1688..57e646bb48b 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -550,16 +550,16 @@ static int tvaudio_thread(void *data) } else if (0 != dev->last_carrier) { /* no carrier -- try last detected one as fallback */ carrier = dev->last_carrier; - dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " - "using %d.%03d MHz [last detected]\n", - dev->name, carrier/1000, carrier%1000); + dprintk("audio carrier scan failed, " + "using %d.%03d MHz [last detected]\n", + carrier/1000, carrier%1000); } else { /* no carrier + no fallback -- use default */ carrier = default_carrier; - dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " - "using %d.%03d MHz [default]\n", - dev->name, carrier/1000, carrier%1000); + dprintk("audio carrier scan failed, " + "using %d.%03d MHz [default]\n", + carrier/1000, carrier%1000); } tvaudio_setcarrier(dev,carrier,carrier); dev->automute = 0; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index f0b1573137f..776ba2dd7f9 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -30,7 +30,7 @@ #include "saa7134-reg.h" #include "saa7134.h" #include <media/v4l2-common.h> -#include <media/rds.h> +#include <media/saa6588.h> /* ------------------------------------------------------------------ */ @@ -1459,7 +1459,7 @@ static int video_release(struct file *file) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - struct rds_command cmd; + struct saa6588_command cmd; unsigned long flags; /* turn off overlay */ @@ -1494,7 +1494,7 @@ static int video_release(struct file *file) saa_call_all(dev, core, s_power, 0); if (fh->radio) - saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); + saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); /* free stuff */ videobuf_mmap_free(&fh->cap); @@ -1520,14 +1520,14 @@ static ssize_t radio_read(struct file *file, char __user *data, { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - struct rds_command cmd; + struct saa6588_command cmd; cmd.block_count = count/3; cmd.buffer = data; cmd.instance = file; cmd.result = -ENODEV; - saa_call_all(dev, core, ioctl, RDS_CMD_READ, &cmd); + saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd); return cmd.result; } @@ -1536,12 +1536,12 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - struct rds_command cmd; + struct saa6588_command cmd; cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - saa_call_all(dev, core, ioctl, RDS_CMD_POLL, &cmd); + saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd); return cmd.result; } @@ -1748,7 +1748,6 @@ static int saa7134_enum_input(struct file *file, void *priv, return -EINVAL; if (NULL == card_in(dev, i->index).name) return -EINVAL; - memset(i, 0, sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, card_in(dev, n).name); @@ -2211,14 +2210,6 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on) return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct saa7134_fh *fh = file->private_data; - return videobuf_cgmbuf(saa7134_queue(fh), mbuf, 8); -} -#endif - static int saa7134_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { @@ -2456,9 +2447,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_streamoff = saa7134_streamoff, .vidioc_g_tuner = saa7134_g_tuner, .vidioc_s_tuner = saa7134_s_tuner, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_crop = saa7134_g_crop, .vidioc_s_crop = saa7134_s_crop, .vidioc_g_fbuf = saa7134_g_fbuf, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d3b6a196e5d..5b0a347b0b8 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -37,7 +37,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> #include <media/tuner.h> -#include <media/ir-common.h> +#include <media/rc-core.h> #include <media/ir-kbd-i2c.h> #include <media/videobuf-dma-sg.h> #include <sound/core.h> @@ -119,6 +119,26 @@ struct saa7134_format { unsigned int uvswap:1; }; +struct saa7134_card_ir { + struct rc_dev *dev; + + char name[32]; + char phys[32]; + unsigned users; + + u32 polling; + u32 last_gpio; + u32 mask_keycode, mask_keydown, mask_keyup; + + bool running; + bool active; + + struct timer_list timer; + + /* IR core raw decoding */ + u32 raw_decode; +}; + /* ----------------------------------------------------------- */ /* card configuration */ @@ -305,6 +325,8 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_A7 179 #define SAA7134_BOARD_AVERMEDIA_M733A 180 #define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181 +#define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182 +#define SAA7134_BOARD_VIDEOMATE_M1F 183 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 @@ -529,7 +551,7 @@ struct saa7134_dev { /* infrared remote */ int has_remote; - struct card_ir *remote; + struct saa7134_card_ir *remote; /* pci i/o */ char name[32]; diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c index ad3bc415417..bd86d970f4c 100644 --- a/drivers/media/video/saa7164/saa7164-api.c +++ b/drivers/media/video/saa7164/saa7164-api.c @@ -40,9 +40,8 @@ int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i) ret = saa7164_cmd_send(dev, 0, GET_CUR, GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i); - if (ret != SAA_OK) { + if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad); @@ -63,14 +62,15 @@ int saa7164_api_collect_debug(struct saa7164_dev *dev) ret = saa7164_cmd_send(dev, 0, GET_CUR, GET_DEBUG_DATA_CONTROL, sizeof(d), &d); - if (ret != SAA_OK) { - printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } + if (ret != SAA_OK) + printk(KERN_ERR "%s() error, ret = 0x%x\n", + __func__, ret); if (d.dwResult != SAA_OK) break; - printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, d.ucDebugData); + printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, + d.ucDebugData); } return 0; @@ -86,9 +86,9 @@ int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level) /* Retrieve current state */ ret = saa7164_cmd_send(dev, 0, GET_CUR, SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl); - if (ret != SAA_OK) { + if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } + dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel); lvl.dwDebugLevel = level; @@ -96,9 +96,8 @@ int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level) /* set new state */ ret = saa7164_cmd_send(dev, 0, SET_CUR, SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl); - if (ret != SAA_OK) { + if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } return ret; } @@ -152,8 +151,10 @@ int saa7164_api_set_vbi_format(struct saa7164_port *port) dprintk(DBGLVL_API, "SET/COMMIT Verified\n"); dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint); - dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", rsp.bFormatIndex); - dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", rsp.bFrameIndex); + dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", + rsp.bFormatIndex); + dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", + rsp.bFrameIndex); } else printk(KERN_ERR "%s() compare failed\n", __func__); } @@ -210,14 +211,17 @@ int saa7164_api_set_encoder(struct saa7164_port *port) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); /* Establish video bitrates */ - if (port->encoder_params.bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + if (port->encoder_params.bitrate_mode == + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT; else vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK; vb.dwVideoBitRate = port->encoder_params.bitrate; vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak; ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, - EU_VIDEO_BIT_RATE_CONTROL, sizeof(struct tmComResEncVideoBitRate), &vb); + EU_VIDEO_BIT_RATE_CONTROL, + sizeof(struct tmComResEncVideoBitRate), + &vb); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -226,9 +230,12 @@ int saa7164_api_set_encoder(struct saa7164_port *port) ab.dwAudioBitRate = 384000; ab.dwAudioBitRatePeak = ab.dwAudioBitRate; ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, - EU_AUDIO_BIT_RATE_CONTROL, sizeof(struct tmComResEncAudioBitRate), &ab); + EU_AUDIO_BIT_RATE_CONTROL, + sizeof(struct tmComResEncAudioBitRate), + &ab); if (ret != SAA_OK) - printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); + printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, + ret); saa7164_api_set_aspect_ratio(port); saa7164_api_set_gop_size(port); @@ -244,7 +251,8 @@ int saa7164_api_get_encoder(struct saa7164_port *port) struct tmComResEncVideoInputAspectRatio ar; int ret; - dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, port->hwcfg.sourceid); + dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, + port->hwcfg.sourceid); port->encoder_profile = 0; port->video_format = 0; @@ -257,7 +265,8 @@ int saa7164_api_get_encoder(struct saa7164_port *port) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, - EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), &port->video_resolution); + EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), + &port->video_resolution); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -294,13 +303,20 @@ int saa7164_api_get_encoder(struct saa7164_port *port) dprintk(DBGLVL_ENC, "video_format = %d\n", port->video_format); dprintk(DBGLVL_ENC, "audio_format = %d\n", port->audio_format); dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution); - dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", v.ucVideoBitRateMode); - dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", v.dwVideoBitRate); - dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", v.dwVideoBitRatePeak); - dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", a.ucAudioBitRateMode); - dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", a.dwAudioBitRate); - dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", a.dwAudioBitRatePeak); - dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", ar.width, ar.height); + dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", + v.ucVideoBitRateMode); + dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", + v.dwVideoBitRate); + dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", + v.dwVideoBitRatePeak); + dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", + a.ucAudioBitRateMode); + dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", + a.dwAudioBitRate); + dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", + a.dwAudioBitRatePeak); + dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", + ar.width, ar.height); return ret; } @@ -439,7 +455,8 @@ int saa7164_api_set_videomux(struct saa7164_port *port) /* Audio Mux */ ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR, - SU_INPUT_SELECT_CONTROL, sizeof(u8), &inputs[port->mux_input - 1]); + SU_INPUT_SELECT_CONTROL, sizeof(u8), + &inputs[port->mux_input - 1]); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -492,7 +509,8 @@ int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level) if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v); + dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, + level, min, max, v); v = level; if (v < min) @@ -517,7 +535,8 @@ int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level) if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v); + dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, + level, min, max, v); return ret; } @@ -539,7 +558,8 @@ int saa7164_api_set_audio_std(struct saa7164_port *port) lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT; lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT; ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR, - AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), &lvl); + AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), + &lvl); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -555,7 +575,8 @@ int saa7164_api_set_audio_std(struct saa7164_port *port) ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR, TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio); if (ret != SAA_OK) - printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", __func__, ret); + printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", + __func__, ret); return ret; } @@ -575,7 +596,9 @@ int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect) ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR, TU_STANDARD_AUTO_CONTROL, sizeof(p), &p); if (ret != SAA_OK) - printk(KERN_ERR "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", __func__, ret); + printk(KERN_ERR + "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", + __func__, ret); return ret; } @@ -646,9 +669,9 @@ int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val) EXU_REGISTER_ACCESS_CONTROL, len, &buf); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); - - //saa7164_dumphex16(dev, buf, 16); - +#if 0 + saa7164_dumphex16(dev, buf, 16); +#endif return ret == SAA_OK ? 0 : -EIO; } @@ -696,7 +719,8 @@ int saa7164_api_configure_dif(struct saa7164_port *port, u32 std) } else { /* Unknown standard, assume DTV */ dprintk(DBGLVL_API, " Unknown (assuming DTV)\n"); - saa7164_api_set_dif(port, 0x00, 0x80); /* Undefined Video Standard */ + /* Undefinded Video Standard */ + saa7164_api_set_dif(port, 0x00, 0x80); agc_disable = 1; } @@ -933,7 +957,7 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) if (hdr->type != CS_INTERFACE) return SAA_ERR_NOT_SUPPORTED; - dprintk(DBGLVL_API, "@ 0x%x = \n", idx); + dprintk(DBGLVL_API, "@ 0x%x =\n", idx); switch (hdr->subtype) { case GENERAL_REQUEST: dprintk(DBGLVL_API, " GENERAL_REQUEST\n"); @@ -1085,7 +1109,8 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) vbiport = &dev->ports[SAA7164_PORT_VBI2]; memcpy(&vbiport->hwcfg, vcoutputtermhdr, sizeof(*vcoutputtermhdr)); - memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, sizeof(*vbifmt)); + memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, + sizeof(*vbifmt)); saa7164_api_configure_port_vbi(dev, vbiport); break; @@ -1134,7 +1159,9 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->tunerunit, tunerunithdr, sizeof(struct tmComResTunerDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d] tuner)\n", encport->nr); + dprintk(DBGLVL_API, + " (becomes dev->enc[%d] tuner)\n", + encport->nr); } break; case VC_SELECTOR_UNIT: @@ -1163,7 +1190,8 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->vidproc, pdh, sizeof(struct tmComResProcDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", + encport->nr); } break; case FEATURE_UNIT: @@ -1181,15 +1209,18 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->audfeat, afd, sizeof(struct tmComResAFeatureDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", + encport->nr); break; case ENCODER_UNIT: edh = (struct tmComResEncoderDescrHeader *)(buf + idx); dprintk(DBGLVL_API, " ENCODER_UNIT\n"); dprintk(DBGLVL_API, " subtype = 0x%x\n", edh->subtype); dprintk(DBGLVL_API, " unitid = 0x%x\n", edh->unitid); - dprintk(DBGLVL_API, " vsourceid = 0x%x\n", edh->vsourceid); - dprintk(DBGLVL_API, " asourceid = 0x%x\n", edh->asourceid); + dprintk(DBGLVL_API, " vsourceid = 0x%x\n", + edh->vsourceid); + dprintk(DBGLVL_API, " asourceid = 0x%x\n", + edh->asourceid); dprintk(DBGLVL_API, " iunit = 0x%x\n", edh->iunit); if (edh->iunit == edh->unitid) { if (currpath == 1) @@ -1198,7 +1229,9 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->encunit, edh, sizeof(struct tmComResEncoderDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, + " (becomes dev->enc[%d])\n", + encport->nr); } break; case EXTENSION_UNIT: @@ -1262,7 +1295,9 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->ifunit, exthdr, sizeof(struct tmComResExtDevDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, + " (becomes dev->enc[%d])\n", + encport->nr); } break; case PVC_INFRARED_UNIT: diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c index 7230912acc7..ddd25211c9e 100644 --- a/drivers/media/video/saa7164/saa7164-buffer.c +++ b/drivers/media/video/saa7164/saa7164-buffer.c @@ -24,46 +24,46 @@ #include "saa7164.h" /* The PCI address space for buffer handling looks like this: - - +-u32 wide-------------+ - | + - +-u64 wide------------------------------------+ - + + - +----------------------+ - | CurrentBufferPtr + Pointer to current PCI buffer >-+ - +----------------------+ | - | Unused + | - +----------------------+ | - | Pitch + = 188 (bytes) | - +----------------------+ | - | PCI buffer size + = pitch * number of lines (312) | - +----------------------+ | - |0| Buf0 Write Offset + | - +----------------------+ v - |1| Buf1 Write Offset + | - +----------------------+ | - |2| Buf2 Write Offset + | - +----------------------+ | - |3| Buf3 Write Offset + | - +----------------------+ | - ... More write offsets | - +---------------------------------------------+ | - +0| set of ptrs to PCI pagetables + | - +---------------------------------------------+ | - +1| set of ptrs to PCI pagetables + <--------+ - +---------------------------------------------+ - +2| set of ptrs to PCI pagetables + - +---------------------------------------------+ - +3| set of ptrs to PCI pagetables + >--+ - +---------------------------------------------+ | - ... More buffer pointers | +----------------+ - +->| pt[0] TS data | - | +----------------+ - | - | +----------------+ - +->| pt[1] TS data | - | +----------------+ - | etc + * + * +-u32 wide-------------+ + * | + + * +-u64 wide------------------------------------+ + * + + + * +----------------------+ + * | CurrentBufferPtr + Pointer to current PCI buffer >-+ + * +----------------------+ | + * | Unused + | + * +----------------------+ | + * | Pitch + = 188 (bytes) | + * +----------------------+ | + * | PCI buffer size + = pitch * number of lines (312) | + * +----------------------+ | + * |0| Buf0 Write Offset + | + * +----------------------+ v + * |1| Buf1 Write Offset + | + * +----------------------+ | + * |2| Buf2 Write Offset + | + * +----------------------+ | + * |3| Buf3 Write Offset + | + * +----------------------+ | + * ... More write offsets | + * +---------------------------------------------+ | + * +0| set of ptrs to PCI pagetables + | + * +---------------------------------------------+ | + * +1| set of ptrs to PCI pagetables + <--------+ + * +---------------------------------------------+ + * +2| set of ptrs to PCI pagetables + + * +---------------------------------------------+ + * +3| set of ptrs to PCI pagetables + >--+ + * +---------------------------------------------+ | + * ... More buffer pointers | +----------------+ + * +->| pt[0] TS data | + * | +----------------+ + * | + * | +----------------+ + * +->| pt[1] TS data | + * | +----------------+ + * | etc */ void saa7164_buffer_display(struct saa7164_buffer *buf) @@ -283,7 +283,8 @@ int saa7164_buffer_cfg_port(struct saa7164_port *port) return 0; } -struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, u32 len) +struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, + u32 len) { struct saa7164_user_buffer *buf; @@ -313,12 +314,9 @@ void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf) if (!buf) return; - if (buf->data) { - kfree(buf->data); - buf->data = 0; - } + kfree(buf->data); + buf->data = 0; - if (buf) - kfree(buf); + kfree(buf); } diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c index 30d5283da41..b2b0d97101d 100644 --- a/drivers/media/video/saa7164/saa7164-bus.c +++ b/drivers/media/video/saa7164/saa7164-bus.c @@ -43,7 +43,8 @@ int saa7164_bus_setup(struct saa7164_dev *dev) b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE; - b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64)); + b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) + + (2 * sizeof(u64)); b->m_dwSetReadPos = b->m_dwSetWritePos + (1 * sizeof(u32)); b->m_dwGetWritePos = b->m_dwSetWritePos + (2 * sizeof(u32)); @@ -105,7 +106,8 @@ void saa7164_bus_verify(struct saa7164_dev *dev) } } -void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, void *buf) +void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, + void *buf) { dprintk(DBGLVL_BUS, "Dumping msg structure:\n"); dprintk(DBGLVL_BUS, " .id = %d\n", m->id); @@ -129,7 +131,8 @@ void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, void * * SAA_OK The function executed successfully. * < 0 One or more members are not initialized. */ -int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf) +int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, + void *buf) { struct tmComResBusInfo *bus = &dev->bus; u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp; @@ -294,14 +297,15 @@ out: /* * Receive a command or a response from the bus. The implementation does not * know if it is a command or a response it simply dequeues the data, - * depending on the bus information given in the struct tmComResBusInfo structure. + * depending on the bus information given in the struct tmComResBusInfo + * structure. * * Return Value: * 0 The function executed successfully. * < 0 One or more members are not initialized. */ -int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf, - int peekonly) +int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, + void *buf, int peekonly) { struct tmComResBusInfo *bus = &dev->bus; u32 bytes_to_read, write_distance, curr_grp, curr_gwp, diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c index 4cb634e952a..69822a4e727 100644 --- a/drivers/media/video/saa7164/saa7164-cards.c +++ b/drivers/media/video/saa7164/saa7164-cards.c @@ -482,7 +482,7 @@ void saa7164_gpio_setup(struct saa7164_dev *dev) saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2); saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3); - msleep(10); + msleep(20); saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2); saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3); diff --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/video/saa7164/saa7164-cmd.c index 301a9e302f4..a97ae17b36c 100644 --- a/drivers/media/video/saa7164/saa7164-cmd.c +++ b/drivers/media/video/saa7164/saa7164-cmd.c @@ -122,8 +122,8 @@ int saa7164_irq_dequeue(struct saa7164_dev *dev) return ret; } - /* It's unlikely to have more than 4 or 5 pending messages, ensure we exit - * at some point regardles. + /* It's unlikely to have more than 4 or 5 pending messages, + * ensure we exit at some point regardless. */ } while (i++ < 32); @@ -186,7 +186,8 @@ int saa7164_cmd_dequeue(struct saa7164_dev *dev) return SAA_OK; } -int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf) +int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg, + void *buf) { struct tmComResBusInfo *bus = &dev->bus; u8 cmd_sent; @@ -292,7 +293,8 @@ int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno) * We typically are signalled in < 50ms but it can * take MUCH longer. */ - wait_event_timeout(*q, dev->cmds[seqno].signalled, (HZ * waitsecs)); + wait_event_timeout(*q, dev->cmds[seqno].signalled, + (HZ * waitsecs)); r = time_before(jiffies, stamp + (HZ * waitsecs)); if (r) ret = SAA_OK; diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index e1bac505146..d6bf3f82cc3 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c @@ -40,12 +40,12 @@ MODULE_AUTHOR("Steven Toth <stoth@kernellabs.com>"); MODULE_LICENSE("GPL"); /* - 1 Basic - 2 - 4 i2c - 8 api - 16 cmd - 32 bus + * 1 Basic + * 2 + * 4 i2c + * 8 api + * 16 cmd + * 32 bus */ unsigned int saa_debug; @@ -82,7 +82,8 @@ MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers"); unsigned int guard_checking = 1; module_param(guard_checking, int, 0644); -MODULE_PARM_DESC(guard_checking, "enable dma sanity checking for buffer overruns"); +MODULE_PARM_DESC(guard_checking, + "enable dma sanity checking for buffer overruns"); static unsigned int saa7164_devcount; @@ -123,7 +124,9 @@ static void saa7164_pack_verifier(struct saa7164_buffer *buf) if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) || (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) { printk(KERN_ERR "No pack at 0x%x\n", i); -// saa7164_dumphex16FF(buf->port->dev, (p + i), 32); +#if 0 + saa7164_dumphex16FF(buf->port->dev, (p + i), 32); +#endif } } } @@ -199,19 +202,16 @@ static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name) strcpy(hg->name, name); /* First 30ms x 1ms */ - for (i = 0; i < 30; i++) { + for (i = 0; i < 30; i++) hg->counter1[0 + i].val = i; - } /* 30 - 200ms x 10ms */ - for (i = 0; i < 18; i++) { + for (i = 0; i < 18; i++) hg->counter1[30 + i].val = 30 + (i * 10); - } /* 200 - 2000ms x 100ms */ - for (i = 0; i < 15; i++) { + for (i = 0; i < 15; i++) hg->counter1[48 + i].val = 200 + (i * 200); - } /* Catch all massive value (2secs) */ hg->counter1[55].val = 2000; @@ -315,7 +315,9 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) (*(p + buf->actual_size + 0x13) != 0xff)) { printk(KERN_ERR "%s() buf %p guard buffer breach\n", __func__, buf); -// saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64); +#if 0 + saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64); +#endif } } @@ -961,9 +963,7 @@ static int saa7164_port_init(struct saa7164_dev *dev, int portnr) /* We need a deferred interrupt handler for cmd handling */ INIT_WORK(&port->workenc, saa7164_work_enchandler); - } - else - if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) { + } else if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) { port->type = SAA7164_MPEG_VBI; /* We need a deferred interrupt handler for cmd handling */ @@ -1001,7 +1001,7 @@ static int saa7164_dev_setup(struct saa7164_dev *dev) atomic_inc(&dev->refcount); dev->nr = saa7164_devcount++; - sprintf(dev->name, "saa7164[%d]", dev->nr); + snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr); mutex_lock(&devlist); list_add_tail(&dev->devlist, &saa7164_devlist); @@ -1169,7 +1169,7 @@ static int saa7164_proc_open(struct inode *inode, struct file *filp) return single_open(filp, saa7164_proc_show, NULL); } -static struct file_operations saa7164_proc_fops = { +static const struct file_operations saa7164_proc_fops = { .open = saa7164_proc_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c index cbb53d0ee97..1838408cd5c 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/video/saa7164/saa7164-encoder.c @@ -125,16 +125,22 @@ static int saa7164_encoder_buffers_alloc(struct saa7164_port *port) dprintk(DBGLVL_ENC, "%s()\n", __func__); - if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { - dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", __func__); + if (port->encoder_params.stream_type == + V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { + dprintk(DBGLVL_ENC, + "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", + __func__); params->samplesperline = 128; params->numberoflines = 256; params->pitch = 128; params->numpagetables = 2 + ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); } else - if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { - dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", __func__); + if (port->encoder_params.stream_type == + V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { + dprintk(DBGLVL_ENC, + "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", + __func__); params->samplesperline = 188; params->numberoflines = 312; params->pitch = 188; @@ -826,7 +832,8 @@ static int fill_queryctrl(struct saa7164_encoder_params *params, return v4l2_ctrl_query_fill(c, 1, 255, 1, 15); case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); case V4L2_CID_MPEG_VIDEO_B_FRAMES: return v4l2_ctrl_query_fill(c, @@ -1113,7 +1120,9 @@ struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) if (crc_checking) { crc = crc32(0, ubuf->data, ubuf->actual_size); if (crc != ubuf->crc) { - printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, + printk(KERN_ERR + "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", + __func__, ubuf, ubuf->crc, crc); } } @@ -1201,9 +1210,8 @@ static ssize_t fops_read(struct file *file, char __user *buffer, buffer += cnt; ret += cnt; - if (ubuf->pos > ubuf->actual_size) { + if (ubuf->pos > ubuf->actual_size) printk(KERN_ERR "read() pos > actual, huh?\n"); - } if (ubuf->pos == ubuf->actual_size) { @@ -1227,16 +1235,16 @@ static ssize_t fops_read(struct file *file, char __user *buffer, } } err: - if (!ret && !ubuf) { + if (!ret && !ubuf) ret = -EAGAIN; - } return ret; } static unsigned int fops_poll(struct file *file, poll_table *wait) { - struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data; + struct saa7164_encoder_fh *fh = + (struct saa7164_encoder_fh *)file->private_data; struct saa7164_port *port = fh->port; struct saa7164_user_buffer *ubuf; unsigned int mask = 0; @@ -1249,9 +1257,8 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) saa7164_histogram_update(&port->poll_interval, port->last_poll_msecs_diff); - if (!video_is_registered(port->v4l_device)) { + if (!video_is_registered(port->v4l_device)) return -EIO; - } if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c index 484533c32bb..ebed6f786a2 100644 --- a/drivers/media/video/saa7164/saa7164-fw.c +++ b/drivers/media/video/saa7164/saa7164-fw.c @@ -178,7 +178,7 @@ int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize, goto out; } - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ if (timeout++ > 60) break; } @@ -235,7 +235,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) while (err_flags != SAA_DEVICE_IMAGE_BOOTING) { dprintk(DBGLVL_FW, "%s() err_flags = %x\n", __func__, err_flags); - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) { printk(KERN_ERR "%s() firmware corrupt\n", @@ -294,7 +294,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) while (err_flags != SAA_DEVICE_IMAGE_BOOTING) { dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n", __func__, err_flags); - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) { printk(KERN_ERR @@ -365,7 +365,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) first_timeout = SAA_DEVICE_TIMEOUT; while (first_timeout) { - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ version = saa7164_getcurrentfirmwareversion(dev); @@ -608,8 +608,6 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) ret = 0; out: - if (fw) - release_firmware(fw); - + release_firmware(fw); return ret; } diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c index b5167d33650..26148f76cba 100644 --- a/drivers/media/video/saa7164/saa7164-i2c.c +++ b/drivers/media/video/saa7164/saa7164-i2c.c @@ -23,7 +23,7 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> -#include <asm/io.h> +#include <linux/io.h> #include "saa7164.h" @@ -65,7 +65,7 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) } return num; - err: +err: return retval; } diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c index 323c7cdca37..8abbe6d661e 100644 --- a/drivers/media/video/saa7164/saa7164-vbi.c +++ b/drivers/media/video/saa7164/saa7164-vbi.c @@ -51,11 +51,15 @@ static void saa7164_vbi_configure(struct saa7164_port *port) /* Set up the DIF (enable it) for analog mode by default */ saa7164_api_initialize_dif(port); -// /* Configure the correct video standard */ -// saa7164_api_configure_dif(port, port->encodernorm.id); + /* Configure the correct video standard */ +#if 0 + saa7164_api_configure_dif(port, port->encodernorm.id); +#endif -// /* Ensure the audio decoder is correct configured */ -// saa7164_api_set_audio_std(port); +#if 0 + /* Ensure the audio decoder is correct configured */ + saa7164_api_set_audio_std(port); +#endif dprintk(DBGLVL_VBI, "%s() ends\n", __func__); } @@ -919,8 +923,10 @@ static int saa7164_vbi_start_streaming(struct saa7164_port *port) saa7164_vbi_buffers_alloc(port); /* Configure the encoder with any cache values */ -// saa7164_api_set_encoder(port); -// saa7164_api_get_encoder(port); +#if 0 + saa7164_api_set_encoder(port); + saa7164_api_get_encoder(port); +#endif /* Place the empty buffers on the hardware */ saa7164_buffer_cfg_port(port); @@ -1060,7 +1066,8 @@ struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port) if (crc_checking) { crc = crc32(0, ubuf->data, ubuf->actual_size); if (crc != ubuf->crc) { - printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, + printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", + __func__, ubuf, ubuf->crc, crc); } } @@ -1148,9 +1155,8 @@ static ssize_t fops_read(struct file *file, char __user *buffer, buffer += cnt; ret += cnt; - if (ubuf->pos > ubuf->actual_size) { + if (ubuf->pos > ubuf->actual_size) printk(KERN_ERR "read() pos > actual, huh?\n"); - } if (ubuf->pos == ubuf->actual_size) { @@ -1197,9 +1203,8 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) saa7164_histogram_update(&port->poll_interval, port->last_poll_msecs_diff); - if (!video_is_registered(port->v4l_device)) { + if (!video_is_registered(port->v4l_device)) return -EIO; - } if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { @@ -1257,10 +1262,14 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_log_status = vidioc_log_status, .vidioc_queryctrl = vidioc_queryctrl, -// .vidioc_g_chip_ident = saa7164_g_chip_ident, +#if 0 + .vidioc_g_chip_ident = saa7164_g_chip_ident, +#endif #ifdef CONFIG_VIDEO_ADV_DEBUG -// .vidioc_g_register = saa7164_g_register, -// .vidioc_s_register = saa7164_s_register, +#if 0 + .vidioc_g_register = saa7164_g_register, + .vidioc_s_register = saa7164_s_register, +#endif #endif .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt, diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h index 041ae8e20f6..16745d2fb34 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/video/saa7164/saa7164.h @@ -113,7 +113,8 @@ #define DBGLVL_THR 4096 #define DBGLVL_CPU 8192 -#define SAA7164_NORMS (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443) +#define SAA7164_NORMS \ + (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443) enum port_t { SAA7164_MPEG_UNDEFINED = 0, @@ -182,15 +183,11 @@ struct saa7164_subid { struct saa7164_encoder_fh { struct saa7164_port *port; -// u32 freq; -// u32 tuner_type; atomic_t v4l_reading; }; struct saa7164_vbi_fh { struct saa7164_port *port; -// u32 freq; -// u32 tuner_type; atomic_t v4l_reading; }; @@ -265,8 +262,6 @@ struct saa7164_ctrl { struct saa7164_tvnorm { char *name; v4l2_std_id id; -// u32 cxiformat; -// u32 cxoformat; }; struct saa7164_encoder_params { @@ -447,7 +442,7 @@ struct saa7164_dev { int nr; int hwrevision; u32 board; - char name[32]; + char name[16]; /* firmware status */ struct saa7164_fw_status fw_status; @@ -510,7 +505,8 @@ extern void saa7164_call_i2c_clients(struct saa7164_i2c *bus, /* saa7164-bus.c */ int saa7164_bus_setup(struct saa7164_dev *dev); void saa7164_bus_dump(struct saa7164_dev *dev); -int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf); +int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, + void *buf); int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf, int peekonly); @@ -552,7 +548,8 @@ int saa7164_api_get_videomux(struct saa7164_port *port); int saa7164_api_set_vbi_format(struct saa7164_port *port); int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level); int saa7164_api_collect_debug(struct saa7164_dev *dev); -int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i); +int saa7164_api_get_load_info(struct saa7164_dev *dev, + struct tmFwInfoStruct *i); /* ----------------------------------------------------------- */ /* saa7164-cards.c */ diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c deleted file mode 100644 index 41360d7c3e9..00000000000 --- a/drivers/media/video/se401.c +++ /dev/null @@ -1,1492 +0,0 @@ -/* - * Endpoints (formerly known as AOX) se401 USB Camera Driver - * - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * Still somewhat based on the Linux ov511 driver. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on - * their chipset available and supporting me while writing this driver. - * - Jeroen Vreeken - */ - -static const char version[] = "0.24"; - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/vmalloc.h> -#include <linux/slab.h> -#include <linux/pagemap.h> -#include <linux/usb.h> -#include "se401.h" - -static int flickerless; -static int video_nr = -1; - -static struct usb_device_id device_table[] = { - { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ - { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ - { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ - { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ - { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ - { } -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); -MODULE_DESCRIPTION("SE401 USB Camera Driver"); -MODULE_LICENSE("GPL"); -module_param(flickerless, int, 0); -MODULE_PARM_DESC(flickerless, - "Net frequency to adjust exposure time to (0/50/60)"); -module_param(video_nr, int, 0); - -static struct usb_driver se401_driver; - - -/********************************************************************** - * - * Memory management - * - **********************************************************************/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - - - -/**************************************************************************** - * - * se401 register read/write functions - * - ***************************************************************************/ - -static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, - unsigned short value, unsigned char *cp, int size) -{ - return usb_control_msg( - se401->dev, - set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), - req, - (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - 0, - cp, - size, - 1000 - ); -} - -static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, - unsigned short param) -{ - /* specs say that the selector (address) should go in the value field - and the param in index, but in the logs of the windows driver they do - this the other way around... - */ - return usb_control_msg( - se401->dev, - usb_sndctrlpipe(se401->dev, 0), - SE401_REQ_SET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - param, - selector, - NULL, - 0, - 1000 - ); -} - -static unsigned short se401_get_feature(struct usb_se401 *se401, - unsigned short selector) -{ - /* For 'set' the selecetor should be in index, not sure if the spec is - wrong here to.... - */ - unsigned char cp[2]; - usb_control_msg( - se401->dev, - usb_rcvctrlpipe(se401->dev, 0), - SE401_REQ_GET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - selector, - cp, - 2, - 1000 - ); - return cp[0]+cp[1]*256; -} - -/**************************************************************************** - * - * Camera control - * - ***************************************************************************/ - - -static int se401_send_pict(struct usb_se401 *se401) -{ - /* integration time low */ - se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); - /* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); - /* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); - /* reset level value */ - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - /* red color gain */ - se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); - /* green color gain */ - se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); - /* blue color gain */ - se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); - - return 0; -} - -static void se401_set_exposure(struct usb_se401 *se401, int brightness) -{ - int integration = brightness << 5; - - if (flickerless == 50) - integration = integration-integration % 106667; - if (flickerless == 60) - integration = integration-integration % 88889; - se401->brightness = integration >> 5; - se401->expose_h = (integration >> 16) & 0xff; - se401->expose_m = (integration >> 8) & 0xff; - se401->expose_l = integration & 0xff; -} - -static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) -{ - p->brightness = se401->brightness; - if (se401->enhance) - p->whiteness = 32768; - else - p->whiteness = 0; - - p->colour = 65535; - p->contrast = 65535; - p->hue = se401->rgain << 10; - p->palette = se401->palette; - p->depth = 3; /* rgb24 */ - return 0; -} - - -static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) -{ - if (p->palette != VIDEO_PALETTE_RGB24) - return 1; - se401->palette = p->palette; - if (p->hue != se401->hue) { - se401->rgain = p->hue >> 10; - se401->bgain = 0x40-(p->hue >> 10); - se401->hue = p->hue; - } - if (p->brightness != se401->brightness) - se401_set_exposure(se401, p->brightness); - - if (p->whiteness >= 32768) - se401->enhance = 1; - else - se401->enhance = 0; - se401_send_pict(se401); - se401_send_pict(se401); - return 0; -} - -/* - Hyundai have some really nice docs about this and other sensor related - stuff on their homepage: www.hei.co.kr -*/ -static void se401_auto_resetlevel(struct usb_se401 *se401) -{ - unsigned int ahrc, alrc; - int oldreset = se401->resetlevel; - - /* For some reason this normally read-only register doesn't get reset - to zero after reading them just once... - */ - se401_get_feature(se401, HV7131_REG_HIREFNOH); - se401_get_feature(se401, HV7131_REG_HIREFNOL); - se401_get_feature(se401, HV7131_REG_LOREFNOH); - se401_get_feature(se401, HV7131_REG_LOREFNOL); - ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + - se401_get_feature(se401, HV7131_REG_HIREFNOL); - alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + - se401_get_feature(se401, HV7131_REG_LOREFNOL); - - /* Not an exact science, but it seems to work pretty well... */ - if (alrc > 10) { - while (alrc >= 10 && se401->resetlevel < 63) { - se401->resetlevel++; - alrc /= 2; - } - } else if (ahrc > 20) { - while (ahrc >= 20 && se401->resetlevel > 0) { - se401->resetlevel--; - ahrc /= 2; - } - } - if (se401->resetlevel != oldreset) - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - - return; -} - -/* irq handler for snapshot button */ -static void se401_button_irq(struct urb *urb) -{ - struct usb_se401 *se401 = urb->context; - int status; - - if (!se401->dev) { - dev_info(&urb->dev->dev, "device vapourished\n"); - return; - } - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", - __func__, urb->status); - goto exit; - } - - if (urb->actual_length >= 2) - if (se401->button) - se401->buttonpressed = 1; -exit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("%s - usb_submit_urb failed with result %d", - __func__, status); -} - -static void se401_video_irq(struct urb *urb) -{ - struct usb_se401 *se401 = urb->context; - int length = urb->actual_length; - - /* ohoh... */ - if (!se401->streaming) - return; - - if (!se401->dev) { - dev_info(&urb->dev->dev, "device vapourished\n"); - return; - } - - /* 0 sized packets happen if we are to fast, but sometimes the camera - keeps sending them forever... - */ - if (length && !urb->status) { - se401->nullpackets = 0; - switch (se401->scratch[se401->scratch_next].state) { - case BUFFER_READY: - case BUFFER_BUSY: - se401->dropped++; - break; - case BUFFER_UNUSED: - memcpy(se401->scratch[se401->scratch_next].data, - (unsigned char *)urb->transfer_buffer, length); - se401->scratch[se401->scratch_next].state - = BUFFER_READY; - se401->scratch[se401->scratch_next].offset - = se401->bayeroffset; - se401->scratch[se401->scratch_next].length = length; - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); - se401->scratch_overflow = 0; - se401->scratch_next++; - if (se401->scratch_next >= SE401_NUMSCRATCH) - se401->scratch_next = 0; - break; - } - se401->bayeroffset += length; - if (se401->bayeroffset >= se401->cheight * se401->cwidth) - se401->bayeroffset = 0; - } else { - se401->nullpackets++; - if (se401->nullpackets > SE401_MAX_NULLPACKETS) - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); - } - - /* Resubmit urb for new data */ - urb->status = 0; - urb->dev = se401->dev; - if (usb_submit_urb(urb, GFP_KERNEL)) - dev_info(&urb->dev->dev, "urb burned down\n"); - return; -} - -static void se401_send_size(struct usb_se401 *se401, int width, int height) -{ - int i = 0; - int mode = 0x03; /* No compression */ - int sendheight = height; - int sendwidth = width; - - /* JangGu compression can only be used with the camera supported sizes, - but bayer seems to work with any size that fits on the sensor. - We check if we can use compression with the current size with either - 4 or 16 times subcapturing, if not we use uncompressed bayer data - but this will result in cutouts of the maximum size.... - */ - while (i < se401->sizes && !(se401->width[i] == width && - se401->height[i] == height)) - i++; - while (i < se401->sizes) { - if (se401->width[i] == width * 2 && - se401->height[i] == height * 2) { - sendheight = se401->height[i]; - sendwidth = se401->width[i]; - mode = 0x40; - } - if (se401->width[i] == width * 4 && - se401->height[i] == height * 4) { - sendheight = se401->height[i]; - sendwidth = se401->width[i]; - mode = 0x42; - } - i++; - } - - se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); - se401_set_feature(se401, SE401_OPERATINGMODE, mode); - - if (mode == 0x03) - se401->format = FMT_BAYER; - else - se401->format = FMT_JANGGU; -} - -/* - In this function se401_send_pict is called several times, - for some reason (depending on the state of the sensor and the phase of - the moon :) doing this only in either place doesn't always work... -*/ -static int se401_start_stream(struct usb_se401 *se401) -{ - struct urb *urb; - int err = 0, i; - se401->streaming = 1; - - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* Set picture settings */ - /* windowed + pix intg */ - se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); - se401_send_pict(se401); - - se401_send_size(se401, se401->cwidth, se401->cheight); - - se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, - 0, NULL, 0); - - /* Do some memory allocation */ - for (i = 0; i < SE401_NUMFRAMES; i++) { - se401->frame[i].data = se401->fbuf + i * se401->maxframesize; - se401->frame[i].curpix = 0; - } - for (i = 0; i < SE401_NUMSBUF; i++) { - se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - if (!se401->sbuf[i].data) { - for (i = i - 1; i >= 0; i--) { - kfree(se401->sbuf[i].data); - se401->sbuf[i].data = NULL; - } - return -ENOMEM; - } - } - - se401->bayeroffset = 0; - se401->scratch_next = 0; - se401->scratch_use = 0; - se401->scratch_overflow = 0; - for (i = 0; i < SE401_NUMSCRATCH; i++) { - se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - if (!se401->scratch[i].data) { - for (i = i - 1; i >= 0; i--) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - goto nomem_sbuf; - } - se401->scratch[i].state = BUFFER_UNUSED; - } - - for (i = 0; i < SE401_NUMSBUF; i++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - for (i = i - 1; i >= 0; i--) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - } - goto nomem_scratch; - } - - usb_fill_bulk_urb(urb, se401->dev, - usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), - se401->sbuf[i].data, SE401_PACKETSIZE, - se401_video_irq, - se401); - - se401->urb[i] = urb; - - err = usb_submit_urb(se401->urb[i], GFP_KERNEL); - if (err) - err("urb burned down"); - } - - se401->framecount = 0; - - return 0; - - nomem_scratch: - for (i = 0; i < SE401_NUMSCRATCH; i++) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - nomem_sbuf: - for (i = 0; i < SE401_NUMSBUF; i++) { - kfree(se401->sbuf[i].data); - se401->sbuf[i].data = NULL; - } - return -ENOMEM; -} - -static int se401_stop_stream(struct usb_se401 *se401) -{ - int i; - - if (!se401->streaming || !se401->dev) - return 1; - - se401->streaming = 0; - - se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); - - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - - for (i = 0; i < SE401_NUMSBUF; i++) - if (se401->urb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - for (i = 0; i < SE401_NUMSCRATCH; i++) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - - return 0; -} - -static int se401_set_size(struct usb_se401 *se401, int width, int height) -{ - int wasstreaming = se401->streaming; - /* Check to see if we need to change */ - if (se401->cwidth == width && se401->cheight == height) - return 0; - - /* Check for a valid mode */ - if (!width || !height) - return 1; - if ((width & 1) || (height & 1)) - return 1; - if (width > se401->width[se401->sizes-1]) - return 1; - if (height > se401->height[se401->sizes-1]) - return 1; - - /* Stop a current stream and start it again at the new size */ - if (wasstreaming) - se401_stop_stream(se401); - se401->cwidth = width; - se401->cheight = height; - if (wasstreaming) - se401_start_stream(se401); - return 0; -} - - -/**************************************************************************** - * - * Video Decoding - * - ***************************************************************************/ - -/* - This shouldn't really be done in a v4l driver.... - But it does make the image look a lot more usable. - Basically it lifts the dark pixels more than the light pixels. -*/ -static inline void enhance_picture(unsigned char *frame, int len) -{ - while (len--) { - *frame = (((*frame^255)*(*frame^255))/255)^255; - frame++; - } -} - -static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) -{ - struct se401_frame *frame = &se401->frame[se401->curframe]; - int linelength = se401->cwidth * 3; - - if (frame->curlinepix >= linelength) { - frame->curlinepix = 0; - frame->curline += linelength; - } - - /* First three are absolute, all others relative. - * Format is rgb from right to left (mirrorred image), - * we flip it to get bgr from left to right. */ - if (frame->curlinepix < 3) - *(frame->curline-frame->curlinepix) = 1 + data * 4; - else - *(frame->curline-frame->curlinepix) = - *(frame->curline-frame->curlinepix + 3) + data * 4; - frame->curlinepix++; -} - -static inline void decode_JangGu_vlc(struct usb_se401 *se401, - unsigned char *data, int bit_exp, int packetlength) -{ - int pos = 0; - int vlc_cod = 0; - int vlc_size = 0; - int vlc_data = 0; - int bit_cur; - int bit; - data += 4; - while (pos < packetlength) { - bit_cur = 8; - while (bit_cur && bit_exp) { - bit = ((*data) >> (bit_cur-1))&1; - if (!vlc_cod) { - if (bit) { - vlc_size++; - } else { - if (!vlc_size) - decode_JangGu_integrate(se401, 0); - else { - vlc_cod = 2; - vlc_data = 0; - } - } - } else { - if (vlc_cod == 2) { - if (!bit) - vlc_data = -(1 << vlc_size) + 1; - vlc_cod--; - } - vlc_size--; - vlc_data += bit << vlc_size; - if (!vlc_size) { - decode_JangGu_integrate(se401, vlc_data); - vlc_cod = 0; - } - } - bit_cur--; - bit_exp--; - } - pos++; - data++; - } -} - -static inline void decode_JangGu(struct usb_se401 *se401, - struct se401_scratch *buffer) -{ - unsigned char *data = buffer->data; - int len = buffer->length; - int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size; - int datapos = 0; - - /* New image? */ - if (!se401->frame[se401->curframe].curpix) { - se401->frame[se401->curframe].curlinepix = 0; - se401->frame[se401->curframe].curline = - se401->frame[se401->curframe].data+ - se401->cwidth * 3 - 1; - if (se401->frame[se401->curframe].grabstate == FRAME_READY) - se401->frame[se401->curframe].grabstate = FRAME_GRABBING; - se401->vlcdatapos = 0; - } - while (datapos < len) { - size = 1024 - se401->vlcdatapos; - if (size+datapos > len) - size = len-datapos; - memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); - se401->vlcdatapos += size; - packetlength = 0; - if (se401->vlcdatapos >= 4) { - bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); - pix_exp = se401->vlcdata[1] + - ((se401->vlcdata[0] & 0x3f) << 8); - frameinfo = se401->vlcdata[0] & 0xc0; - packetlength = ((bit_exp + 47) >> 4) << 1; - if (packetlength > 1024) { - se401->vlcdatapos = 0; - datapos = len; - packetlength = 0; - se401->error++; - se401->frame[se401->curframe].curpix = 0; - } - } - if (packetlength && se401->vlcdatapos >= packetlength) { - decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, - packetlength); - se401->frame[se401->curframe].curpix += pix_exp * 3; - datapos += size-(se401->vlcdatapos-packetlength); - se401->vlcdatapos = 0; - if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) { - if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) { - if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) { - se401->frame[se401->curframe].grabstate = FRAME_DONE; - se401->framecount++; - se401->readcount++; - } - if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) - se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); - } else - se401->error++; - se401->frame[se401->curframe].curpix = 0; - datapos = len; - } - } else - datapos += size; - } -} - -static inline void decode_bayer(struct usb_se401 *se401, - struct se401_scratch *buffer) -{ - unsigned char *data = buffer->data; - int len = buffer->length; - int offset = buffer->offset; - int datasize = se401->cwidth * se401->cheight; - struct se401_frame *frame = &se401->frame[se401->curframe]; - unsigned char *framedata = frame->data, *curline, *nextline; - int width = se401->cwidth; - int blineoffset = 0, bline; - int linelength = width * 3, i; - - - if (frame->curpix == 0) { - if (frame->grabstate == FRAME_READY) - frame->grabstate = FRAME_GRABBING; - - frame->curline = framedata + linelength; - frame->curlinepix = 0; - } - - if (offset != frame->curpix) { - /* Regard frame as lost :( */ - frame->curpix = 0; - se401->error++; - return; - } - - /* Check if we have to much data */ - if (frame->curpix + len > datasize) - len = datasize-frame->curpix; - - if (se401->cheight % 4) - blineoffset = 1; - bline = frame->curpix / se401->cwidth+blineoffset; - - curline = frame->curline; - nextline = curline + linelength; - if (nextline >= framedata+datasize * 3) - nextline = curline; - while (len) { - if (frame->curlinepix >= width) { - frame->curlinepix -= width; - bline = frame->curpix / width + blineoffset; - curline += linelength*2; - nextline += linelength*2; - if (curline >= framedata+datasize * 3) { - frame->curlinepix++; - curline -= 3; - nextline -= 3; - len--; - data++; - frame->curpix++; - } - if (nextline >= framedata+datasize*3) - nextline = curline; - } - if (bline & 1) { - if (frame->curlinepix & 1) { - *(curline + 2) = *data; - *(curline - 1) = *data; - *(nextline + 2) = *data; - *(nextline - 1) = *data; - } else { - *(curline + 1) = - (*(curline + 1) + *data) / 2; - *(curline-2) = - (*(curline - 2) + *data) / 2; - *(nextline + 1) = *data; - *(nextline - 2) = *data; - } - } else { - if (frame->curlinepix & 1) { - *(curline + 1) = - (*(curline + 1) + *data) / 2; - *(curline - 2) = - (*(curline - 2) + *data) / 2; - *(nextline + 1) = *data; - *(nextline - 2) = *data; - } else { - *curline = *data; - *(curline - 3) = *data; - *nextline = *data; - *(nextline - 3) = *data; - } - } - frame->curlinepix++; - curline -= 3; - nextline -= 3; - len--; - data++; - frame->curpix++; - } - frame->curline = curline; - - if (frame->curpix >= datasize) { - /* Fix the top line */ - framedata += linelength; - for (i = 0; i < linelength; i++) { - framedata--; - *framedata = *(framedata + linelength); - } - /* Fix the left side (green is already present) */ - for (i = 0; i < se401->cheight; i++) { - *framedata = *(framedata + 3); - *(framedata + 1) = *(framedata + 4); - *(framedata + 2) = *(framedata + 5); - framedata += linelength; - } - frame->curpix = 0; - frame->grabstate = FRAME_DONE; - se401->framecount++; - se401->readcount++; - if (se401->frame[(se401->curframe + 1) & - (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { - se401->curframe = (se401->curframe+1) & - (SE401_NUMFRAMES-1); - } - } -} - -static int se401_newframe(struct usb_se401 *se401, int framenr) -{ - DECLARE_WAITQUEUE(wait, current); - int errors = 0; - - while (se401->streaming && - (se401->frame[framenr].grabstate == FRAME_READY || - se401->frame[framenr].grabstate == FRAME_GRABBING)) { - if (!se401->frame[framenr].curpix) - errors++; - - wait_interruptible( - se401->scratch[se401->scratch_use].state != BUFFER_READY, - &se401->wq, &wait); - if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - se401->nullpackets = 0; - dev_info(&se401->dev->dev, - "too many null length packets, restarting capture\n"); - se401_stop_stream(se401); - se401_start_stream(se401); - } else { - if (se401->scratch[se401->scratch_use].state != - BUFFER_READY) { - se401->frame[framenr].grabstate = FRAME_ERROR; - return -EIO; - } - se401->scratch[se401->scratch_use].state = BUFFER_BUSY; - if (se401->format == FMT_JANGGU) - decode_JangGu(se401, - &se401->scratch[se401->scratch_use]); - else - decode_bayer(se401, - &se401->scratch[se401->scratch_use]); - - se401->scratch[se401->scratch_use].state = - BUFFER_UNUSED; - se401->scratch_use++; - if (se401->scratch_use >= SE401_NUMSCRATCH) - se401->scratch_use = 0; - if (errors > SE401_MAX_ERRORS) { - errors = 0; - dev_info(&se401->dev->dev, - "too many errors, restarting capture\n"); - se401_stop_stream(se401); - se401_start_stream(se401); - } - } - } - - if (se401->frame[framenr].grabstate == FRAME_DONE) - if (se401->enhance) - enhance_picture(se401->frame[framenr].data, - se401->cheight * se401->cwidth * 3); - return 0; -} - -static void usb_se401_remove_disconnected(struct usb_se401 *se401) -{ - int i; - - se401->dev = NULL; - - for (i = 0; i < SE401_NUMSBUF; i++) - if (se401->urb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - - for (i = 0; i < SE401_NUMSCRATCH; i++) - kfree(se401->scratch[i].data); - - if (se401->inturb) { - usb_kill_urb(se401->inturb); - usb_free_urb(se401->inturb); - } - dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); - - /* Free the memory */ - kfree(se401->width); - kfree(se401->height); - kfree(se401); -} - - - -/**************************************************************************** - * - * Video4Linux - * - ***************************************************************************/ - - -static int se401_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int err = 0; - - mutex_lock(&se401->lock); - if (se401->user) { - mutex_unlock(&se401->lock); - return -EBUSY; - } - se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); - if (se401->fbuf) - file->private_data = dev; - else - err = -ENOMEM; - se401->user = !err; - mutex_unlock(&se401->lock); - - return err; -} - -static int se401_close(struct file *file) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int i; - - rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); - if (se401->removed) { - dev_info(&se401->dev->dev, "device unregistered\n"); - usb_se401_remove_disconnected(se401); - } else { - for (i = 0; i < SE401_NUMFRAMES; i++) - se401->frame[i].grabstate = FRAME_UNUSED; - if (se401->streaming) - se401_stop_stream(se401); - se401->user = 0; - } - file->private_data = NULL; - return 0; -} - -static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)vdev; - - if (!se401->dev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, se401->camera_name); - b->type = VID_TYPE_CAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = se401->width[se401->sizes-1]; - b->maxheight = se401->height[se401->sizes-1]; - b->minwidth = se401->width[0]; - b->minheight = se401->height[0]; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - - se401_get_pict(se401, p); - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - - if (se401_set_pict(se401, p)) - return -EINVAL; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (se401_set_size(se401, vw->width, vw->height)) - return -EINVAL; - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; /* FIXME */ - vw->y = 0; - vw->chromakey = 0; - vw->flags = 0; - vw->clipcount = 0; - vw->width = se401->cwidth; - vw->height = se401->cheight; - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = SE401_NUMFRAMES * se401->maxframesize; - vm->frames = SE401_NUMFRAMES; - for (i = 0; i < SE401_NUMFRAMES; i++) - vm->offsets[i] = se401->maxframesize * i; - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (vm->format != VIDEO_PALETTE_RGB24) - return -EINVAL; - if (vm->frame >= SE401_NUMFRAMES) - return -EINVAL; - if (se401->frame[vm->frame].grabstate != FRAME_UNUSED) - return -EBUSY; - - /* Is this according to the v4l spec??? */ - if (se401_set_size(se401, vm->width, vm->height)) - return -EINVAL; - se401->frame[vm->frame].grabstate = FRAME_READY; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount == 0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount % 20 == 1) - se401_auto_resetlevel(se401); - - return 0; - } - case VIDIOCSYNC: - { - int *frame = arg; - int ret = 0; - - if (*frame < 0 || *frame >= SE401_NUMFRAMES) - return -EINVAL; - - ret = se401_newframe(se401, *frame); - se401->frame[*frame].grabstate = FRAME_UNUSED; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCGTUNER: - case VIDIOCSTUNER: - return -EINVAL; - case VIDIOCGFREQ: - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -static long se401_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, se401_do_ioctl); -} - -static ssize_t se401_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int realcount = count, ret = 0; - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - - - if (se401->dev == NULL) - return -EIO; - if (realcount > se401->cwidth*se401->cheight*3) - realcount = se401->cwidth*se401->cheight*3; - - /* Shouldn't happen: */ - if (se401->frame[0].grabstate == FRAME_GRABBING) - return -EBUSY; - se401->frame[0].grabstate = FRAME_READY; - se401->frame[1].grabstate = FRAME_UNUSED; - se401->curframe = 0; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount == 0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20 == 1) - se401_auto_resetlevel(se401); - - ret = se401_newframe(se401, 0); - - se401->frame[0].grabstate = FRAME_UNUSED; - if (ret) - return ret; - if (copy_to_user(buf, se401->frame[0].data, realcount)) - return -EFAULT; - - return realcount; -} - -static int se401_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - mutex_lock(&se401->lock); - - if (se401->dev == NULL) { - mutex_unlock(&se401->lock); - return -EIO; - } - if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) - & ~(PAGE_SIZE - 1))) { - mutex_unlock(&se401->lock); - return -EINVAL; - } - pos = (unsigned long)se401->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&se401->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - mutex_unlock(&se401->lock); - - return 0; -} - -static const struct v4l2_file_operations se401_fops = { - .owner = THIS_MODULE, - .open = se401_open, - .release = se401_close, - .read = se401_read, - .mmap = se401_mmap, - .ioctl = se401_ioctl, -}; -static struct video_device se401_template = { - .name = "se401 USB camera", - .fops = &se401_fops, - .release = video_device_release_empty, -}; - - - -/***************************/ -static int se401_init(struct usb_se401 *se401, int button) -{ - int i = 0, rc; - unsigned char cp[0x40]; - char temp[200]; - int slen; - - /* led on */ - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* get camera descriptor */ - rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, - cp, sizeof(cp)); - if (cp[1] != 0x41) { - err("Wrong descriptor type"); - return 1; - } - slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]); - - se401->sizes = cp[4] + cp[5] * 256; - se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->width) - return 1; - se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->height) { - kfree(se401->width); - return 1; - } - for (i = 0; i < se401->sizes; i++) { - se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256; - se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256; - } - slen += snprintf(temp + slen, 200 - slen, " Sizes:"); - for (i = 0; i < se401->sizes; i++) { - slen += snprintf(temp + slen, 200 - slen, - " %dx%d", se401->width[i], se401->height[i]); - } - dev_info(&se401->dev->dev, "%s\n", temp); - se401->maxframesize = se401->width[se401->sizes-1] * - se401->height[se401->sizes - 1] * 3; - - rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); - se401->cwidth = cp[0]+cp[1]*256; - rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); - se401->cheight = cp[0]+cp[1]*256; - - if (!(cp[2] & SE401_FORMAT_BAYER)) { - err("Bayer format not supported!"); - return 1; - } - /* set output mode (BAYER) */ - se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, - SE401_FORMAT_BAYER, NULL, 0); - - rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); - se401->brightness = cp[0]+cp[1]*256; - /* some default values */ - se401->resetlevel = 0x2d; - se401->rgain = 0x20; - se401->ggain = 0x20; - se401->bgain = 0x20; - se401_set_exposure(se401, 20000); - se401->palette = VIDEO_PALETTE_RGB24; - se401->enhance = 1; - se401->dropped = 0; - se401->error = 0; - se401->framecount = 0; - se401->readcount = 0; - - /* Start interrupt transfers for snapshot button */ - if (button) { - se401->inturb = usb_alloc_urb(0, GFP_KERNEL); - if (!se401->inturb) { - dev_info(&se401->dev->dev, - "Allocation of inturb failed\n"); - return 1; - } - usb_fill_int_urb(se401->inturb, se401->dev, - usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), - &se401->button, sizeof(se401->button), - se401_button_irq, - se401, - 8 - ); - if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { - dev_info(&se401->dev->dev, "int urb burned down\n"); - return 1; - } - } else - se401->inturb = NULL; - - /* Flash the led */ - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - - return 0; -} - -static int se401_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor *interface; - struct usb_se401 *se401; - char *camera_name = NULL; - int button = 1; - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - interface = &intf->cur_altsetting->desc; - - /* Is it an se401? */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && - le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { - camera_name = "Endpoints/Aox SE401"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && - le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { - camera_name = "Philips PCVC665K"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { - camera_name = "Kensington VideoCAM 67014"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { - camera_name = "Kensington VideoCAM 6701(5/7)"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { - camera_name = "Kensington VideoCAM 67016"; - button = 0; - } else - return -ENODEV; - - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0x00) - return -ENODEV; - if (interface->bInterfaceSubClass != 0x00) - return -ENODEV; - - /* We found one */ - dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); - - se401 = kzalloc(sizeof(*se401), GFP_KERNEL); - if (se401 == NULL) { - err("couldn't kmalloc se401 struct"); - return -ENOMEM; - } - - se401->dev = dev; - se401->iface = interface->bInterfaceNumber; - se401->camera_name = camera_name; - - dev_info(&intf->dev, "firmware version: %02x\n", - le16_to_cpu(dev->descriptor.bcdDevice) & 255); - - if (se401_init(se401, button)) { - kfree(se401); - return -EIO; - } - - memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); - memcpy(se401->vdev.name, se401->camera_name, - strlen(se401->camera_name)); - init_waitqueue_head(&se401->wq); - mutex_init(&se401->lock); - wmb(); - - if (video_register_device(&se401->vdev, - VFL_TYPE_GRABBER, video_nr) < 0) { - kfree(se401); - err("video_register_device failed"); - return -EIO; - } - dev_info(&intf->dev, "registered new video device: %s\n", - video_device_node_name(&se401->vdev)); - - usb_set_intfdata(intf, se401); - return 0; -} - -static void se401_disconnect(struct usb_interface *intf) -{ - struct usb_se401 *se401 = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (se401) { - video_unregister_device(&se401->vdev); - if (!se401->user) - usb_se401_remove_disconnected(se401); - else { - se401->frame[0].grabstate = FRAME_ERROR; - se401->frame[0].grabstate = FRAME_ERROR; - - se401->streaming = 0; - - wake_up_interruptible(&se401->wq); - se401->removed = 1; - } - } -} - -static struct usb_driver se401_driver = { - .name = "se401", - .id_table = device_table, - .probe = se401_probe, - .disconnect = se401_disconnect, -}; - - - -/**************************************************************************** - * - * Module routines - * - ***************************************************************************/ - -static int __init usb_se401_init(void) -{ - printk(KERN_INFO "SE401 usb camera driver version %s registering\n", - version); - if (flickerless) - if (flickerless != 50 && flickerless != 60) { - printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); - return -1; - } - return usb_register(&se401_driver); -} - -static void __exit usb_se401_exit(void) -{ - usb_deregister(&se401_driver); - printk(KERN_INFO "SE401 driver deregistered\frame"); -} - -module_init(usb_se401_init); -module_exit(usb_se401_exit); diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h deleted file mode 100644 index bf7d2e9765b..00000000000 --- a/drivers/media/video/se401.h +++ /dev/null @@ -1,236 +0,0 @@ - -#ifndef __LINUX_se401_H -#define __LINUX_se401_H - -#include <linux/uaccess.h> -#include <linux/videodev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <linux/mutex.h> - -#define se401_DEBUG /* Turn on debug messages */ - -#ifdef se401_DEBUG -# define PDEBUG(level, fmt, args...) \ -if (debug >= level) \ - info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) -#else -# define PDEBUG(level, fmt, args...) do {} while (0) -#endif - -/* An almost drop-in replacement for sleep_on_interruptible */ -#define wait_interruptible(test, queue, wait) \ -{ \ - add_wait_queue(queue, wait); \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (test) \ - schedule(); \ - remove_wait_queue(queue, wait); \ - set_current_state(TASK_RUNNING); \ - if (signal_pending(current)) \ - break; \ -} - -#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 -#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 -#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 -#define SE401_REQ_CAPTURE_FRAME 0x43 -#define SE401_REQ_GET_BRT 0x44 -#define SE401_REQ_SET_BRT 0x45 -#define SE401_REQ_GET_WIDTH 0x4c -#define SE401_REQ_SET_WIDTH 0x4d -#define SE401_REQ_GET_HEIGHT 0x4e -#define SE401_REQ_SET_HEIGHT 0x4f -#define SE401_REQ_GET_OUTPUT_MODE 0x50 -#define SE401_REQ_SET_OUTPUT_MODE 0x51 -#define SE401_REQ_GET_EXT_FEATURE 0x52 -#define SE401_REQ_SET_EXT_FEATURE 0x53 -#define SE401_REQ_CAMERA_POWER 0x56 -#define SE401_REQ_LED_CONTROL 0x57 -#define SE401_REQ_BIOS 0xff - -#define SE401_BIOS_READ 0x07 - -#define SE401_FORMAT_BAYER 0x40 - -/* Hyundai hv7131b registers - 7121 and 7141 should be the same (haven't really checked...) */ -/* Mode registers: */ -#define HV7131_REG_MODE_A 0x00 -#define HV7131_REG_MODE_B 0x01 -#define HV7131_REG_MODE_C 0x02 -/* Frame registers: */ -#define HV7131_REG_FRSU 0x10 -#define HV7131_REG_FRSL 0x11 -#define HV7131_REG_FCSU 0x12 -#define HV7131_REG_FCSL 0x13 -#define HV7131_REG_FWHU 0x14 -#define HV7131_REG_FWHL 0x15 -#define HV7131_REG_FWWU 0x16 -#define HV7131_REG_FWWL 0x17 -/* Timing registers: */ -#define HV7131_REG_THBU 0x20 -#define HV7131_REG_THBL 0x21 -#define HV7131_REG_TVBU 0x22 -#define HV7131_REG_TVBL 0x23 -#define HV7131_REG_TITU 0x25 -#define HV7131_REG_TITM 0x26 -#define HV7131_REG_TITL 0x27 -#define HV7131_REG_TMCD 0x28 -/* Adjust Registers: */ -#define HV7131_REG_ARLV 0x30 -#define HV7131_REG_ARCG 0x31 -#define HV7131_REG_AGCG 0x32 -#define HV7131_REG_ABCG 0x33 -#define HV7131_REG_APBV 0x34 -#define HV7131_REG_ASLP 0x54 -/* Offset Registers: */ -#define HV7131_REG_OFSR 0x50 -#define HV7131_REG_OFSG 0x51 -#define HV7131_REG_OFSB 0x52 -/* REset level statistics registers: */ -#define HV7131_REG_LOREFNOH 0x57 -#define HV7131_REG_LOREFNOL 0x58 -#define HV7131_REG_HIREFNOH 0x59 -#define HV7131_REG_HIREFNOL 0x5a - -/* se401 registers */ -#define SE401_OPERATINGMODE 0x2000 - - -/* size of usb transfers */ -#define SE401_PACKETSIZE 4096 -/* number of queued bulk transfers to use, should be about 8 */ -#define SE401_NUMSBUF 1 -/* read the usb specs for this one :) */ -#define SE401_VIDEO_ENDPOINT 1 -#define SE401_BUTTON_ENDPOINT 2 -/* number of frames supported by the v4l part */ -#define SE401_NUMFRAMES 2 -/* scratch buffers for passing data to the decoders */ -#define SE401_NUMSCRATCH 32 -/* maximum amount of data in a JangGu packet */ -#define SE401_VLCDATALEN 1024 -/* number of nul sized packets to receive before kicking the camera */ -#define SE401_MAX_NULLPACKETS 4000 -/* number of decoding errors before kicking the camera */ -#define SE401_MAX_ERRORS 200 - -struct usb_device; - -struct se401_sbuf { - unsigned char *data; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -enum { - FMT_BAYER, - FMT_JANGGU, -}; - -enum { - BUFFER_UNUSED, - BUFFER_READY, - BUFFER_BUSY, - BUFFER_DONE, -}; - -struct se401_scratch { - unsigned char *data; - volatile int state; - int offset; - int length; -}; - -struct se401_frame { - unsigned char *data; /* Frame buffer */ - - volatile int grabstate; /* State of grabbing */ - - unsigned char *curline; - int curlinepix; - int curpix; -}; - -struct usb_se401 { - struct video_device vdev; - - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - - char *camera_name; - - int change; - int brightness; - int hue; - int rgain; - int ggain; - int bgain; - int expose_h; - int expose_m; - int expose_l; - int resetlevel; - - int enhance; - - int format; - int sizes; - int *width; - int *height; - int cwidth; /* current width */ - int cheight; /* current height */ - int palette; - int maxframesize; - int cframesize; /* current framesize */ - - struct mutex lock; - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - - int streaming; /* Are we streaming video? */ - - char *fbuf; /* Videodev buffer area */ - - struct urb *urb[SE401_NUMSBUF]; - struct urb *inturb; - - int button; - int buttonpressed; - - int curframe; /* Current receiving frame */ - struct se401_frame frame[SE401_NUMFRAMES]; - int readcount; - int framecount; - int error; - int dropped; - - int scratch_next; - int scratch_use; - int scratch_overflow; - struct se401_scratch scratch[SE401_NUMSCRATCH]; - - /* Decoder specific data: */ - unsigned char vlcdata[SE401_VLCDATALEN]; - int vlcdatapos; - int bayeroffset; - - struct se401_sbuf sbuf[SE401_NUMSBUF]; - - wait_queue_head_t wq; /* Processes waiting */ - - int nullpackets; -}; - - - -#endif - diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 5c209afb0ac..954222bc345 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1786,7 +1786,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->field, sizeof(struct sh_mobile_ceu_buffer), - icd, NULL); + icd, &icd->video_lock); } static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, @@ -1980,7 +1980,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) * we complete the completion. */ - if (!csi2->driver || !csi2->driver->owner) { + if (!csi2->driver) { complete(&wait.completion); /* Either too late, or probing failed */ bus_unregister_notifier(&platform_bus_type, &wait.notifier); diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c index 0f4906136b8..07cf0c6c7c1 100644 --- a/drivers/media/video/sh_vou.c +++ b/drivers/media/video/sh_vou.c @@ -75,6 +75,7 @@ struct sh_vou_device { int pix_idx; struct videobuf_buffer *active; enum sh_vou_status status; + struct mutex fop_lock; }; struct sh_vou_file { @@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb) vb->state = VIDEOBUF_NEEDS_INIT; } -/* Locking: caller holds vq->vb_lock mutex */ +/* Locking: caller holds fop_lock mutex */ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { @@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, return 0; } -/* Locking: caller holds vq->vb_lock mutex */ +/* Locking: caller holds fop_lock mutex */ static int sh_vou_buf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) @@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq, return 0; } -/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */ +/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */ static void sh_vou_buf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file) V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_FIELD_NONE, sizeof(struct videobuf_buffer), vdev, - NULL); + &vou_dev->fop_lock); return 0; } @@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = { .owner = THIS_MODULE, .open = sh_vou_open, .release = sh_vou_release, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = sh_vou_mmap, .poll = sh_vou_poll, }; @@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) INIT_LIST_HEAD(&vou_dev->queue); spin_lock_init(&vou_dev->lock); + mutex_init(&vou_dev->fop_lock); atomic_set(&vou_dev->use_count, 0); vou_dev->pdata = vou_pdata; vou_dev->status = SH_VOU_IDLE; @@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) vdev->tvnorms |= V4L2_STD_PAL; vdev->v4l2_dev = &vou_dev->v4l2_dev; vdev->release = video_device_release; + vdev->lock = &vou_dev->fop_lock; vou_dev->vdev = vdev; video_set_drvdata(vdev, vou_dev); @@ -1406,7 +1409,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) goto ereset; subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap, - NULL, vou_pdata->board_info, NULL); + vou_pdata->board_info, NULL); if (!subdev) { ret = -ENOMEM; goto ei2cnd; diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 28e19daadec..84984f64b23 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -2189,6 +2189,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); i.type = V4L2_INPUT_TYPE_CAMERA; + i.capabilities = V4L2_IN_CAP_STD; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; @@ -3238,7 +3239,7 @@ static const struct v4l2_file_operations sn9c102_fops = { .owner = THIS_MODULE, .open = sn9c102_open, .release = sn9c102_release, - .ioctl = sn9c102_ioctl, + .unlocked_ioctl = sn9c102_ioctl, .read = sn9c102_read, .poll = sn9c102_poll, .mmap = sn9c102_mmap, diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index ccfa59c5455..41064c7b5ef 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -43,9 +43,7 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ @@ -56,8 +54,8 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 43848a751d1..a66811b4371 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -24,6 +24,7 @@ #include <linux/mutex.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/pm_runtime.h> #include <linux/vmalloc.h> @@ -43,6 +44,51 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ +static int soc_camera_power_set(struct soc_camera_device *icd, + struct soc_camera_link *icl, + int power_on) +{ + int ret; + + if (power_on) { + ret = regulator_bulk_enable(icl->num_regulators, + icl->regulators); + if (ret < 0) { + dev_err(&icd->dev, "Cannot enable regulators\n"); + return ret; + } + + if (icl->power) + ret = icl->power(icd->pdev, power_on); + if (ret < 0) { + dev_err(&icd->dev, + "Platform failed to power-on the camera.\n"); + + regulator_bulk_disable(icl->num_regulators, + icl->regulators); + return ret; + } + } else { + ret = 0; + if (icl->power) + ret = icl->power(icd->pdev, 0); + if (ret < 0) { + dev_err(&icd->dev, + "Platform failed to power-off the camera.\n"); + return ret; + } + + ret = regulator_bulk_disable(icl->num_regulators, + icl->regulators); + if (ret < 0) { + dev_err(&icd->dev, "Cannot disable regulators\n"); + return ret; + } + } + + return 0; +} + const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { @@ -352,12 +398,6 @@ static int soc_camera_open(struct file *file) return -EINVAL; } - /* - * Protect against icd->ops->remove() until we module_get() both - * drivers. - */ - mutex_lock(&icd->video_lock); - icd->use_count++; /* Now we really have to activate the camera */ @@ -375,11 +415,9 @@ static int soc_camera_open(struct file *file) }, }; - if (icl->power) { - ret = icl->power(icd->pdev, 1); - if (ret < 0) - goto epower; - } + ret = soc_camera_power_set(icd, icl, 1); + if (ret < 0) + goto epower; /* The camera could have been already on, try to reset */ if (icl->reset) @@ -405,15 +443,13 @@ static int soc_camera_open(struct file *file) ret = soc_camera_set_fmt(icd, &f); if (ret < 0) goto esfmt; + + ici->ops->init_videobuf(&icd->vb_vidq, icd); } file->private_data = icd; dev_dbg(&icd->dev, "camera device open\n"); - ici->ops->init_videobuf(&icd->vb_vidq, icd); - - mutex_unlock(&icd->video_lock); - return 0; /* @@ -425,11 +461,9 @@ esfmt: eresume: ici->ops->remove(icd); eiciadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: icd->use_count--; - mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); return ret; @@ -440,7 +474,6 @@ static int soc_camera_close(struct file *file) struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - mutex_lock(&icd->video_lock); icd->use_count--; if (!icd->use_count) { struct soc_camera_link *icl = to_soc_camera_link(icd); @@ -450,15 +483,12 @@ static int soc_camera_close(struct file *file) ici->ops->remove(icd); - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); } if (icd->streamer == file) icd->streamer = NULL; - mutex_unlock(&icd->video_lock); - module_put(ici->ops->owner); dev_dbg(&icd->dev, "camera device close\n"); @@ -517,7 +547,7 @@ static struct v4l2_file_operations soc_camera_fops = { .owner = THIS_MODULE, .open = soc_camera_open, .release = soc_camera_close, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .read = soc_camera_read, .mmap = soc_camera_mmap, .poll = soc_camera_poll, @@ -534,12 +564,9 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, if (icd->streamer && icd->streamer != file) return -EBUSY; - mutex_lock(&icd->vb_vidq.vb_lock); - if (icd->vb_vidq.bufs[0]) { dev_err(&icd->dev, "S_FMT denied: queue initialised\n"); - ret = -EBUSY; - goto unlock; + return -EBUSY; } ret = soc_camera_set_fmt(icd, f); @@ -547,9 +574,6 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, if (!ret && !icd->streamer) icd->streamer = file; -unlock: - mutex_unlock(&icd->vb_vidq.vb_lock); - return ret; } @@ -622,15 +646,11 @@ static int soc_camera_streamon(struct file *file, void *priv, if (icd->streamer != file) return -EBUSY; - mutex_lock(&icd->video_lock); - v4l2_subdev_call(sd, video, s_stream, 1); /* This calls buf_queue from host driver's videobuf_queue_ops */ ret = videobuf_streamon(&icd->vb_vidq); - mutex_unlock(&icd->video_lock); - return ret; } @@ -648,8 +668,6 @@ static int soc_camera_streamoff(struct file *file, void *priv, if (icd->streamer != file) return -EBUSY; - mutex_lock(&icd->video_lock); - /* * This calls buf_release from host driver's videobuf_queue_ops for all * remaining buffers. When the last buffer is freed, stop capture @@ -658,8 +676,6 @@ static int soc_camera_streamoff(struct file *file, void *priv, v4l2_subdev_call(sd, video, s_stream, 0); - mutex_unlock(&icd->video_lock); - return 0; } @@ -748,9 +764,7 @@ static int soc_camera_g_crop(struct file *file, void *fh, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; - mutex_lock(&icd->vb_vidq.vb_lock); ret = ici->ops->get_crop(icd, a); - mutex_unlock(&icd->vb_vidq.vb_lock); return ret; } @@ -775,9 +789,6 @@ static int soc_camera_s_crop(struct file *file, void *fh, dev_dbg(&icd->dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, rect->left, rect->top); - /* Cropping is allowed during a running capture, guard consistency */ - mutex_lock(&icd->vb_vidq.vb_lock); - /* If get_crop fails, we'll let host and / or client drivers decide */ ret = ici->ops->get_crop(icd, ¤t_crop); @@ -795,8 +806,6 @@ static int soc_camera_s_crop(struct file *file, void *fh, ret = ici->ops->set_crop(icd, a); } - mutex_unlock(&icd->vb_vidq.vb_lock); - return ret; } @@ -896,7 +905,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, icl->board_info->platform_data = icd; subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, - NULL, icl->board_info, NULL); + icl->board_info, NULL); if (!subdev) goto ei2cnd; @@ -941,14 +950,14 @@ static int soc_camera_probe(struct device *dev) dev_info(dev, "Probing %s\n", dev_name(dev)); - if (icl->power) { - ret = icl->power(icd->pdev, 1); - if (ret < 0) { - dev_err(dev, - "Platform failed to power-on the camera.\n"); - goto epower; - } - } + ret = regulator_bulk_get(icd->pdev, icl->num_regulators, + icl->regulators); + if (ret < 0) + goto ereg; + + ret = soc_camera_power_set(icd, icl, 1); + if (ret < 0) + goto epower; /* The camera could have been already on, try to reset */ if (icl->reset) @@ -998,7 +1007,13 @@ static int soc_camera_probe(struct device *dev) icd->field = V4L2_FIELD_ANY; - /* ..._video_start() will create a device node, so we have to protect */ + icd->vdev->lock = &icd->video_lock; + + /* + * ..._video_start() will create a device node, video_register_device() + * itself is protected against concurrent open() calls, but we also have + * to protect our data. + */ mutex_lock(&icd->video_lock); ret = soc_camera_video_start(icd); @@ -1021,8 +1036,7 @@ static int soc_camera_probe(struct device *dev) ici->ops->remove(icd); - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); mutex_unlock(&icd->video_lock); @@ -1044,9 +1058,10 @@ eadddev: evdc: ici->ops->remove(icd); eadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: + regulator_bulk_free(icl->num_regulators, icl->regulators); +ereg: return ret; } @@ -1063,10 +1078,8 @@ static int soc_camera_remove(struct device *dev) BUG_ON(!dev->parent); if (vdev) { - mutex_lock(&icd->video_lock); video_unregister_device(vdev); icd->vdev = NULL; - mutex_unlock(&icd->video_lock); } if (icl->board_info) { @@ -1081,6 +1094,8 @@ static int soc_camera_remove(struct device *dev) } soc_camera_free_user_formats(icd); + regulator_bulk_free(icl->num_regulators, icl->regulators); + return 0; } diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c index c9dc67aba98..864696b7a00 100644 --- a/drivers/media/video/sr030pc30.c +++ b/drivers/media/video/sr030pc30.c @@ -735,7 +735,7 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on) const struct sr030pc30_platform_data *pdata = info->pdata; int ret; - if (WARN(pdata == NULL, "No platform data!")) + if (WARN(pdata == NULL, "No platform data!\n")) return -ENOMEM; /* diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index b5afe5f841c..d1a2cefbf55 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -230,120 +230,6 @@ static int stk_initialise(struct stk_camera *dev) return -1; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - -/* sysfs functions */ -/*FIXME cleanup this */ - -static ssize_t show_brightness(struct device *class, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - return sprintf(buf, "%X\n", dev->vsettings.brightness); -} - -static ssize_t store_brightness(struct device *class, - struct device_attribute *attr, const char *buf, size_t count) -{ - char *endp; - unsigned long value; - int ret; - - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - value = simple_strtoul(buf, &endp, 16); - - dev->vsettings.brightness = (int) value; - - ret = stk_sensor_set_brightness(dev, value >> 8); - if (ret) - return ret; - else - return count; -} - -static ssize_t show_hflip(struct device *class, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - return sprintf(buf, "%d\n", dev->vsettings.hflip); -} - -static ssize_t store_hflip(struct device *class, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - if (strncmp(buf, "1", 1) == 0) - dev->vsettings.hflip = 1; - else if (strncmp(buf, "0", 1) == 0) - dev->vsettings.hflip = 0; - else - return -EINVAL; - - return strlen(buf); -} - -static ssize_t show_vflip(struct device *class, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - return sprintf(buf, "%d\n", dev->vsettings.vflip); -} - -static ssize_t store_vflip(struct device *class, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - if (strncmp(buf, "1", 1) == 0) - dev->vsettings.vflip = 1; - else if (strncmp(buf, "0", 1) == 0) - dev->vsettings.vflip = 0; - else - return -EINVAL; - - return strlen(buf); -} - -static DEVICE_ATTR(brightness, S_IRUGO | S_IWUGO, - show_brightness, store_brightness); -static DEVICE_ATTR(hflip, S_IRUGO | S_IWUGO, show_hflip, store_hflip); -static DEVICE_ATTR(vflip, S_IRUGO | S_IWUGO, show_vflip, store_vflip); - -static int stk_create_sysfs_files(struct video_device *vdev) -{ - int ret; - - ret = device_create_file(&vdev->dev, &dev_attr_brightness); - ret += device_create_file(&vdev->dev, &dev_attr_hflip); - ret += device_create_file(&vdev->dev, &dev_attr_vflip); - if (ret) - STK_WARNING("Could not create sysfs files\n"); - return ret; -} - -static void stk_remove_sysfs_files(struct video_device *vdev) -{ - device_remove_file(&vdev->dev, &dev_attr_brightness); - device_remove_file(&vdev->dev, &dev_attr_hflip); - device_remove_file(&vdev->dev, &dev_attr_vflip); -} - -#else -#define stk_create_sysfs_files(a) -#define stk_remove_sysfs_files(a) -#endif - /* *********************************************** */ /* * This function is called as an URB transfert is complete (Isochronous pipe). @@ -878,7 +764,24 @@ static struct v4l2_queryctrl stk_controls[] = { .step = 0x0100, .default_value = 0x6000, }, - /*TODO: get more controls to work */ + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Horizontal Flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vertical Flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, }; static int stk_vidioc_queryctrl(struct file *filp, @@ -906,6 +809,12 @@ static int stk_vidioc_g_ctrl(struct file *filp, case V4L2_CID_BRIGHTNESS: c->value = dev->vsettings.brightness; break; + case V4L2_CID_HFLIP: + c->value = dev->vsettings.hflip; + break; + case V4L2_CID_VFLIP: + c->value = dev->vsettings.vflip; + break; default: return -EINVAL; } @@ -920,6 +829,12 @@ static int stk_vidioc_s_ctrl(struct file *filp, case V4L2_CID_BRIGHTNESS: dev->vsettings.brightness = c->value; return stk_sensor_set_brightness(dev, c->value >> 8); + case V4L2_CID_HFLIP: + dev->vsettings.hflip = c->value; + return 0; + case V4L2_CID_VFLIP: + dev->vsettings.vflip = c->value; + return 0; default: return -EINVAL; } @@ -1394,8 +1309,6 @@ static int stk_camera_probe(struct usb_interface *interface, goto error; } - stk_create_sysfs_files(&dev->vdev); - return 0; error: @@ -1411,7 +1324,6 @@ static void stk_camera_disconnect(struct usb_interface *interface) unset_present(dev); wake_up_interruptible(&dev->wait_frame); - stk_remove_sysfs_files(&dev->vdev); STK_INFO("Syntek USB2.0 Camera release resources device %s\n", video_device_node_name(&dev->vdev)); diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 3e99cea8e4d..19621ed523e 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -148,7 +148,7 @@ static int tea6415c_probe(struct i2c_client *client, /* let's see whether this adapter can support what we need */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) - return 0; + return -EIO; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c new file mode 100644 index 00000000000..fc611ebeb82 --- /dev/null +++ b/drivers/media/video/timblogiw.c @@ -0,0 +1,893 @@ +/* + * timblogiw.c timberdale FPGA LogiWin Video In driver + * Copyright (c) 2009-2010 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * Timberdale FPGA LogiWin Video In + */ + +#include <linux/version.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/dmaengine.h> +#include <linux/scatterlist.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/i2c.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-device.h> +#include <media/videobuf-dma-contig.h> +#include <media/timb_video.h> + +#define DRIVER_NAME "timb-video" + +#define TIMBLOGIWIN_NAME "Timberdale Video-In" +#define TIMBLOGIW_VERSION_CODE 0x04 + +#define TIMBLOGIW_LINES_PER_DESC 44 +#define TIMBLOGIW_MAX_VIDEO_MEM 16 + +#define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name) + + +struct timblogiw { + struct video_device video_dev; + struct v4l2_device v4l2_dev; /* mutual exclusion */ + struct mutex lock; + struct device *dev; + struct timb_video_platform_data pdata; + struct v4l2_subdev *sd_enc; /* encoder */ + bool opened; +}; + +struct timblogiw_tvnorm { + v4l2_std_id std; + u16 width; + u16 height; + u8 fps; +}; + +struct timblogiw_fh { + struct videobuf_queue vb_vidq; + struct timblogiw_tvnorm const *cur_norm; + struct list_head capture; + struct dma_chan *chan; + spinlock_t queue_lock; /* mutual exclusion */ + unsigned int frame_count; +}; + +struct timblogiw_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + struct scatterlist sg[16]; + dma_cookie_t cookie; + struct timblogiw_fh *fh; +}; + +const struct timblogiw_tvnorm timblogiw_tvnorms[] = { + { + .std = V4L2_STD_PAL, + .width = 720, + .height = 576, + .fps = 25 + }, + { + .std = V4L2_STD_NTSC, + .width = 720, + .height = 480, + .fps = 30 + } +}; + +static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm) +{ + return norm->width * 2; +} + + +static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm) +{ + return norm->height * timblogiw_bytes_per_line(norm); +} + +static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std) +{ + int i; + for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) + if (timblogiw_tvnorms[i].std & std) + return timblogiw_tvnorms + i; + + /* default to first element */ + return timblogiw_tvnorms; +} + +static void timblogiw_dma_cb(void *data) +{ + struct timblogiw_buffer *buf = data; + struct timblogiw_fh *fh = buf->fh; + struct videobuf_buffer *vb = &buf->vb; + + spin_lock(&fh->queue_lock); + + /* mark the transfer done */ + buf->cookie = -1; + + fh->frame_count++; + + if (vb->state != VIDEOBUF_ERROR) { + list_del(&vb->queue); + do_gettimeofday(&vb->ts); + vb->field_count = fh->frame_count * 2; + vb->state = VIDEOBUF_DONE; + + wake_up(&vb->done); + } + + if (!list_empty(&fh->capture)) { + vb = list_entry(fh->capture.next, struct videobuf_buffer, + queue); + vb->state = VIDEOBUF_ACTIVE; + } + + spin_unlock(&fh->queue_lock); +} + +static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param) +{ + return chan->chan_id == (uintptr_t)filter_param; +} + +/* IOCTL functions */ + +static int timblogiw_g_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + mutex_lock(&lw->lock); + + format->fmt.pix.width = fh->cur_norm->width; + format->fmt.pix.height = fh->cur_norm->height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm); + format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm); + format->fmt.pix.field = V4L2_FIELD_NONE; + + mutex_unlock(&lw->lock); + + return 0; +} + +static int timblogiw_try_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_pix_format *pix = &format->fmt.pix; + + dev_dbg(&vdev->dev, + "%s - width=%d, height=%d, pixelformat=%d, field=%d\n" + "bytes per line %d, size image: %d, colorspace: %d\n", + __func__, + pix->width, pix->height, pix->pixelformat, pix->field, + pix->bytesperline, pix->sizeimage, pix->colorspace); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (pix->field != V4L2_FIELD_NONE) + return -EINVAL; + + if (pix->pixelformat != V4L2_PIX_FMT_UYVY) + return -EINVAL; + + return 0; +} + +static int timblogiw_s_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + struct v4l2_pix_format *pix = &format->fmt.pix; + int err; + + mutex_lock(&lw->lock); + + err = timblogiw_try_fmt(file, priv, format); + if (err) + goto out; + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + dev_err(&vdev->dev, "%s queue busy\n", __func__); + err = -EBUSY; + goto out; + } + + pix->width = fh->cur_norm->width; + pix->height = fh->cur_norm->height; + +out: + mutex_unlock(&lw->lock); + return err; +} + +static int timblogiw_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + memset(cap, 0, sizeof(*cap)); + strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); + strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); + strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info)); + cap->version = TIMBLOGIW_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + + return 0; +} + +static int timblogiw_enum_fmt(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index); + + if (fmt->index != 0) + return -EINVAL; + memset(fmt, 0, sizeof(*fmt)); + fmt->index = 0; + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strncpy(fmt->description, "4:2:2, packed, YUYV", + sizeof(fmt->description)-1); + fmt->pixelformat = V4L2_PIX_FMT_UYVY; + + return 0; +} + +static int timblogiw_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct timblogiw_fh *fh = priv; + struct v4l2_captureparm *cp = &sp->parm.capture; + + cp->capability = V4L2_CAP_TIMEPERFRAME; + cp->timeperframe.numerator = 1; + cp->timeperframe.denominator = fh->cur_norm->fps; + + return 0; +} + +static int timblogiw_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_reqbufs(&fh->vb_vidq, rb); +} + +static int timblogiw_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_querybuf(&fh->vb_vidq, b); +} + +static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_qbuf(&fh->vb_vidq, b); +} + +static int timblogiw_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); +} + +static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + *std = fh->cur_norm->std; + return 0; +} + +static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + int err = 0; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + mutex_lock(&lw->lock); + + if (TIMBLOGIW_HAS_DECODER(lw)) + err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std); + + if (!err) + fh->cur_norm = timblogiw_get_norm(*std); + + mutex_unlock(&lw->lock); + + return err; +} + +static int timblogiw_enuminput(struct file *file, void *priv, + struct v4l2_input *inp) +{ + struct video_device *vdev = video_devdata(file); + int i; + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + if (inp->index != 0) + return -EINVAL; + + inp->index = 0; + + strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1); + inp->type = V4L2_INPUT_TYPE_CAMERA; + + inp->std = 0; + for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) + inp->std |= timblogiw_tvnorms[i].std; + + return 0; +} + +static int timblogiw_g_input(struct file *file, void *priv, + unsigned int *input) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + *input = 0; + + return 0; +} + +static int timblogiw_s_input(struct file *file, void *priv, unsigned int input) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + if (input != 0) + return -EINVAL; + return 0; +} + +static int timblogiw_streamon(struct file *file, void *priv, unsigned int type) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_dbg(&vdev->dev, "%s - No capture device\n", __func__); + return -EINVAL; + } + + fh->frame_count = 0; + return videobuf_streamon(&fh->vb_vidq); +} + +static int timblogiw_streamoff(struct file *file, void *priv, + unsigned int type) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + return videobuf_streamoff(&fh->vb_vidq); +} + +static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (TIMBLOGIW_HAS_DECODER(lw)) + return v4l2_subdev_call(lw->sd_enc, video, querystd, std); + else { + *std = fh->cur_norm->std; + return 0; + } +} + +static int timblogiw_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__, + fsize->index, fsize->pixel_format); + + if ((fsize->index != 0) || + (fsize->pixel_format != V4L2_PIX_FMT_UYVY)) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fh->cur_norm->width; + fsize->discrete.height = fh->cur_norm->height; + + return 0; +} + +/* Video buffer functions */ + +static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct timblogiw_fh *fh = vq->priv_data; + + *size = timblogiw_frame_size(fh->cur_norm); + + if (!*count) + *count = 32; + + while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024) + (*count)--; + + return 0; +} + +static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + unsigned int data_size = timblogiw_frame_size(fh->cur_norm); + int err = 0; + + if (vb->baddr && vb->bsize < data_size) + /* User provided buffer, but it is too small */ + return -ENOMEM; + + vb->size = data_size; + vb->width = fh->cur_norm->width; + vb->height = fh->cur_norm->height; + vb->field = field; + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + int i; + unsigned int size; + unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * + timblogiw_bytes_per_line(fh->cur_norm); + dma_addr_t addr; + + sg_init_table(buf->sg, ARRAY_SIZE(buf->sg)); + + err = videobuf_iolock(vq, vb, NULL); + if (err) + goto err; + + addr = videobuf_to_dma_contig(vb); + for (i = 0, size = 0; size < data_size; i++) { + sg_dma_address(buf->sg + i) = addr + size; + size += bytes_per_desc; + sg_dma_len(buf->sg + i) = (size > data_size) ? + (bytes_per_desc - (size - data_size)) : + bytes_per_desc; + } + + vb->state = VIDEOBUF_PREPARED; + buf->cookie = -1; + buf->fh = fh; + } + + return 0; + +err: + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; + return err; +} + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + struct dma_async_tx_descriptor *desc; + int sg_elems; + int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * + timblogiw_bytes_per_line(fh->cur_norm); + + sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc; + sg_elems += + (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0; + + if (list_empty(&fh->capture)) + vb->state = VIDEOBUF_ACTIVE; + else + vb->state = VIDEOBUF_QUEUED; + + list_add_tail(&vb->queue, &fh->capture); + + spin_unlock_irq(&fh->queue_lock); + + desc = fh->chan->device->device_prep_slave_sg(fh->chan, + buf->sg, sg_elems, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); + if (!desc) { + spin_lock_irq(&fh->queue_lock); + list_del_init(&vb->queue); + vb->state = VIDEOBUF_PREPARED; + return; + } + + desc->callback_param = buf; + desc->callback = timblogiw_dma_cb; + + buf->cookie = desc->tx_submit(desc); + + spin_lock_irq(&fh->queue_lock); +} + +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + + videobuf_waiton(vq, vb, 0, 0); + if (buf->cookie >= 0) + dma_sync_wait(fh->chan, buf->cookie); + + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static struct videobuf_queue_ops timblogiw_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/* Device Operations functions */ + +static int timblogiw_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh; + v4l2_std_id std; + dma_cap_mask_t mask; + int err = 0; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + mutex_lock(&lw->lock); + if (lw->opened) { + err = -EBUSY; + goto out; + } + + if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) { + struct i2c_adapter *adapt; + + /* find the video decoder */ + adapt = i2c_get_adapter(lw->pdata.i2c_adapter); + if (!adapt) { + dev_err(&vdev->dev, "No I2C bus #%d\n", + lw->pdata.i2c_adapter); + err = -ENODEV; + goto out; + } + + /* now find the encoder */ + lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt, + lw->pdata.encoder.info, NULL); + + i2c_put_adapter(adapt); + + if (!lw->sd_enc) { + dev_err(&vdev->dev, "Failed to get encoder: %s\n", + lw->pdata.encoder.module_name); + err = -ENODEV; + goto out; + } + } + + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (!fh) { + err = -ENOMEM; + goto out; + } + + fh->cur_norm = timblogiw_tvnorms; + timblogiw_querystd(file, fh, &std); + fh->cur_norm = timblogiw_get_norm(std); + + INIT_LIST_HEAD(&fh->capture); + spin_lock_init(&fh->queue_lock); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + /* find the DMA channel */ + fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn, + (void *)(uintptr_t)lw->pdata.dma_channel); + if (!fh->chan) { + dev_err(&vdev->dev, "Failed to get DMA channel\n"); + kfree(fh); + err = -ENODEV; + goto out; + } + + file->private_data = fh; + videobuf_queue_dma_contig_init(&fh->vb_vidq, + &timblogiw_video_qops, lw->dev, &fh->queue_lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + sizeof(struct timblogiw_buffer), fh, NULL); + + lw->opened = true; +out: + mutex_unlock(&lw->lock); + + return err; +} + +static int timblogiw_close(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + dma_release_channel(fh->chan); + + kfree(fh); + + mutex_lock(&lw->lock); + lw->opened = false; + mutex_unlock(&lw->lock); + return 0; +} + +static ssize_t timblogiw_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, + file->f_flags & O_NONBLOCK); +} + +static unsigned int timblogiw_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_poll_stream(file, &fh->vb_vidq, wait); +} + +static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_mmap_mapper(&fh->vb_vidq, vma); +} + +/* Platform device functions */ + +static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = { + .vidioc_querycap = timblogiw_querycap, + .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt, + .vidioc_g_fmt_vid_cap = timblogiw_g_fmt, + .vidioc_try_fmt_vid_cap = timblogiw_try_fmt, + .vidioc_s_fmt_vid_cap = timblogiw_s_fmt, + .vidioc_g_parm = timblogiw_g_parm, + .vidioc_reqbufs = timblogiw_reqbufs, + .vidioc_querybuf = timblogiw_querybuf, + .vidioc_qbuf = timblogiw_qbuf, + .vidioc_dqbuf = timblogiw_dqbuf, + .vidioc_g_std = timblogiw_g_std, + .vidioc_s_std = timblogiw_s_std, + .vidioc_enum_input = timblogiw_enuminput, + .vidioc_g_input = timblogiw_g_input, + .vidioc_s_input = timblogiw_s_input, + .vidioc_streamon = timblogiw_streamon, + .vidioc_streamoff = timblogiw_streamoff, + .vidioc_querystd = timblogiw_querystd, + .vidioc_enum_framesizes = timblogiw_enum_framesizes, +}; + +static __devinitconst struct v4l2_file_operations timblogiw_fops = { + .owner = THIS_MODULE, + .open = timblogiw_open, + .release = timblogiw_close, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = timblogiw_mmap, + .read = timblogiw_read, + .poll = timblogiw_poll, +}; + +static __devinitconst struct video_device timblogiw_template = { + .name = TIMBLOGIWIN_NAME, + .fops = &timblogiw_fops, + .ioctl_ops = &timblogiw_ioctl_ops, + .release = video_device_release_empty, + .minor = -1, + .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC +}; + +static int __devinit timblogiw_probe(struct platform_device *pdev) +{ + int err; + struct timblogiw *lw = NULL; + struct timb_video_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data\n"); + err = -EINVAL; + goto err; + } + + if (!pdata->encoder.module_name) + dev_info(&pdev->dev, "Running without decoder\n"); + + lw = kzalloc(sizeof(*lw), GFP_KERNEL); + if (!lw) { + err = -ENOMEM; + goto err; + } + + if (pdev->dev.parent) + lw->dev = pdev->dev.parent; + else + lw->dev = &pdev->dev; + + memcpy(&lw->pdata, pdata, sizeof(lw->pdata)); + + mutex_init(&lw->lock); + + lw->video_dev = timblogiw_template; + + strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name)); + err = v4l2_device_register(NULL, &lw->v4l2_dev); + if (err) + goto err_register; + + lw->video_dev.v4l2_dev = &lw->v4l2_dev; + + platform_set_drvdata(pdev, lw); + video_set_drvdata(&lw->video_dev, lw); + + err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0); + if (err) { + dev_err(&pdev->dev, "Error reg video: %d\n", err); + goto err_request; + } + + + return 0; + +err_request: + platform_set_drvdata(pdev, NULL); + v4l2_device_unregister(&lw->v4l2_dev); +err_register: + kfree(lw); +err: + dev_err(&pdev->dev, "Failed to register: %d\n", err); + + return err; +} + +static int __devexit timblogiw_remove(struct platform_device *pdev) +{ + struct timblogiw *lw = platform_get_drvdata(pdev); + + video_unregister_device(&lw->video_dev); + + v4l2_device_unregister(&lw->v4l2_dev); + + kfree(lw); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver timblogiw_platform_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = timblogiw_probe, + .remove = __devexit_p(timblogiw_remove), +}; + +/* Module functions */ + +static int __init timblogiw_init(void) +{ + return platform_driver_register(&timblogiw_platform_driver); +} + +static void __exit timblogiw_exit(void) +{ + platform_driver_unregister(&timblogiw_platform_driver); +} + +module_init(timblogiw_init); +module_exit(timblogiw_exit); + +MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); +MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRIVER_NAME); diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig index 1686ebfa695..645d915267e 100644 --- a/drivers/media/video/tlg2300/Kconfig +++ b/drivers/media/video/tlg2300/Kconfig @@ -1,9 +1,9 @@ config VIDEO_TLG2300 tristate "Telegent TLG2300 USB video capture support" - depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE + depends on VIDEO_DEV && I2C && SND && DVB_CORE select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on RC_CORE select VIDEOBUF_VMALLOC select SND_PCM select VIDEOBUF_DVB diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index c91424c0c13..99c81a9a4f4 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c @@ -452,7 +452,8 @@ static int poseidon_probe(struct usb_interface *interface, device_init_wakeup(&udev->dev, 1); #ifdef CONFIG_PM - pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY; + pm_runtime_set_autosuspend_delay(&pd->udev->dev, + 1000 * PM_SUSPEND_DELAY); usb_enable_autosuspend(pd->udev); if (in_hibernation(pd)) { diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig deleted file mode 100644 index dfa7fc68a65..00000000000 --- a/drivers/media/video/usbvideo/Kconfig +++ /dev/null @@ -1,45 +0,0 @@ -config VIDEO_USBVIDEO - tristate - -config USB_VICAM - tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on VIDEO_V4L1 && EXPERIMENTAL - select VIDEO_USBVIDEO - ---help--- - Say Y here if you have 3com homeconnect camera (vicam). - - To compile this driver as a module, choose M here: the - module will be called vicam. - -config USB_IBMCAM - tristate "USB IBM (Xirlink) C-it Camera support (DEPRECATED)" - depends on VIDEO_V4L1 - select VIDEO_USBVIDEO - ---help--- - This driver is DEPRECATED please use the gspca xirlink_cit module - instead. - - Say Y here if you want to connect a IBM "C-It" camera, also known as - "Xirlink PC Camera" to your computer's USB port. - - To compile this driver as a module, choose M here: the - module will be called ibmcam. - - This camera has several configuration options which - can be specified when you load the module. Read - <file:Documentation/video4linux/ibmcam.txt> to learn more. - -config USB_KONICAWC - tristate "USB Konica Webcam support (DEPRECATED)" - depends on VIDEO_V4L1 - select VIDEO_USBVIDEO - ---help--- - This driver is DEPRECATED (and known to crash) please use the - gspca konica module instead. - - Say Y here if you want support for webcams based on a Konica - chipset. This is known to work with the Intel YC76 webcam. - - To compile this driver as a module, choose M here: the - module will be called konicawc. - diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile deleted file mode 100644 index bb52eb8dc2f..00000000000 --- a/drivers/media/video/usbvideo/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o -obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o -obj-$(CONFIG_USB_KONICAWC) += konicawc.o -obj-$(CONFIG_USB_VICAM) += vicam.o diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c deleted file mode 100644 index b0854966178..00000000000 --- a/drivers/media/video/usbvideo/ibmcam.c +++ /dev/null @@ -1,3977 +0,0 @@ -/* - * USB IBM C-It Video Camera driver - * - * Supports Xirlink C-It Video Camera, IBM PC Camera, - * IBM NetCamera and Veo Stingray. - * - * This driver is based on earlier work of: - * - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Randy Dunlap - * - * 5/24/00 Removed optional (and unnecessary) locking of the driver while - * the device remains plugged in. Corrected race conditions in ibmcam_open - * and ibmcam_probe() routines using this as a guideline: - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> - -#include "usbvideo.h" - -#define IBMCAM_VENDOR_ID 0x0545 -#define IBMCAM_PRODUCT_ID 0x8080 -#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */ -#define VEO_800C_PRODUCT_ID 0x800C /* Veo Stingray, repackaged Model 2 */ -#define VEO_800D_PRODUCT_ID 0x800D /* Veo Stingray, repackaged Model 4 */ - -#define MAX_IBMCAM 4 /* How many devices we allow to connect */ -#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */ - -/* Header signatures */ - -/* Model 1 header: 00 FF 00 xx */ -#define HDRSIG_MODEL1_128x96 0x06 /* U Y V Y ... */ -#define HDRSIG_MODEL1_176x144 0x0e /* U Y V Y ... */ -#define HDRSIG_MODEL1_352x288 0x00 /* V Y U Y ... */ - -#define IBMCAM_MODEL_1 1 /* XVP-501, 3 interfaces, rev. 0.02 */ -#define IBMCAM_MODEL_2 2 /* KSX-X9903, 2 interfaces, rev. 3.0a */ -#define IBMCAM_MODEL_3 3 /* KSX-X9902, 2 interfaces, rev. 3.01 */ -#define IBMCAM_MODEL_4 4 /* IBM NetCamera, 0545/8002/3.0a */ - -/* Video sizes supported */ -#define VIDEOSIZE_128x96 VIDEOSIZE(128, 96) -#define VIDEOSIZE_176x144 VIDEOSIZE(176,144) -#define VIDEOSIZE_352x288 VIDEOSIZE(352,288) -#define VIDEOSIZE_320x240 VIDEOSIZE(320,240) -#define VIDEOSIZE_352x240 VIDEOSIZE(352,240) -#define VIDEOSIZE_640x480 VIDEOSIZE(640,480) -#define VIDEOSIZE_160x120 VIDEOSIZE(160,120) - -/* Video sizes supported */ -enum { - SIZE_128x96 = 0, - SIZE_160x120, - SIZE_176x144, - SIZE_320x240, - SIZE_352x240, - SIZE_352x288, - SIZE_640x480, - /* Add/remove/rearrange items before this line */ - SIZE_LastItem -}; - -/* - * This structure lives in uvd->user field. - */ -typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; -} ibmcam_t; -#define IBMCAM_T(uvd) ((ibmcam_t *)((uvd)->user_data)) - -static struct usbvideo *cams; - -static int debug; - -static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ - -static const int min_canvasWidth = 8; -static const int min_canvasHeight = 4; - -static int lighting = 1; /* Medium */ - -#define SHARPNESS_MIN 0 -#define SHARPNESS_MAX 6 -static int sharpness = 4; /* Low noise, good details */ - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; - -static int size = SIZE_352x288; - -/* - * Here we define several initialization variables. They may - * be used to automatically set color, hue, brightness and - * contrast to desired values. This is particularly useful in - * case of webcams (which have no controls and no on-screen - * output) and also when a client V4L software is used that - * does not have some of those controls. In any case it's - * good to have startup values as options. - * - * These values are all in [0..255] range. This simplifies - * operation. Note that actual values of V4L variables may - * be scaled up (as much as << 8). User can see that only - * on overlay output, however, or through a V4L client. - */ -static int init_brightness = 128; -static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; - -/* Settings for camera model 2 */ -static int init_model2_rg2 = -1; -static int init_model2_sat = -1; -static int init_model2_yb = -1; - -/* 01.01.08 - Added for RCA video in support -LO */ -/* Settings for camera model 3 */ -static int init_model3_input; - -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -module_param(flags, int, 0); -MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames"); -module_param(framerate, int, 0); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); -module_param(lighting, int, 0); -MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); -module_param(sharpness, int, 0); -MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); -module_param(size, int, 0); -MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480 (default=5)"); -module_param(init_brightness, int, 0); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -module_param(init_contrast, int, 0); -MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -module_param(init_color, int, 0); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -module_param(init_hue, int, 0); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -module_param(hue_correction, int, 0); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); - -module_param(init_model2_rg2, int, 0); -MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)"); -module_param(init_model2_sat, int, 0); -MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)"); -module_param(init_model2_yb, int, 0); -MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)"); - -/* 01.01.08 - Added for RCA video in support -LO */ -module_param(init_model3_input, int, 0); -MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA"); - -MODULE_AUTHOR ("Dmitri"); -MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"); -MODULE_LICENSE("GPL"); - -/* Still mysterious i2c commands */ -static const unsigned short unknown_88 = 0x0088; -static const unsigned short unknown_89 = 0x0089; -static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 }; -static const unsigned short contrast_14 = 0x0014; -static const unsigned short light_27 = 0x0027; -static const unsigned short sharp_13 = 0x0013; - -/* i2c commands for Model 2 cameras */ -static const unsigned short mod2_brightness = 0x001a; /* $5b .. $ee; default=$5a */ -static const unsigned short mod2_set_framerate = 0x001c; /* 0 (fast).. $1F (slow) */ -static const unsigned short mod2_color_balance_rg2 = 0x001e; /* 0 (red) .. $7F (green) */ -static const unsigned short mod2_saturation = 0x0020; /* 0 (b/w) - $7F (full color) */ -static const unsigned short mod2_color_balance_yb = 0x0022; /* 0..$7F, $50 is about right */ -static const unsigned short mod2_hue = 0x0024; /* 0..$7F, $70 is about right */ -static const unsigned short mod2_sensitivity = 0x0028; /* 0 (min) .. $1F (max) */ - -struct struct_initData { - unsigned char req; - unsigned short value; - unsigned short index; -}; - -/* - * ibmcam_size_to_videosize() - * - * This procedure converts module option 'size' into the actual - * videosize_t that defines the image size in pixels. We need - * simplified 'size' because user wants a simple enumerated list - * of choices, not an infinite set of possibilities. - */ -static videosize_t ibmcam_size_to_videosize(int size) -{ - videosize_t vs = VIDEOSIZE_352x288; - RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1)); - switch (size) { - case SIZE_128x96: - vs = VIDEOSIZE_128x96; - break; - case SIZE_160x120: - vs = VIDEOSIZE_160x120; - break; - case SIZE_176x144: - vs = VIDEOSIZE_176x144; - break; - case SIZE_320x240: - vs = VIDEOSIZE_320x240; - break; - case SIZE_352x240: - vs = VIDEOSIZE_352x240; - break; - case SIZE_352x288: - vs = VIDEOSIZE_352x288; - break; - case SIZE_640x480: - vs = VIDEOSIZE_640x480; - break; - default: - err("size=%d. is not valid", size); - break; - } - return vs; -} - -/* - * ibmcam_find_header() - * - * Locate one of supported header markers in the queue. - * Once found, remove all preceding bytes AND the marker (4 bytes) - * from the data pump queue. Whatever follows must be video lines. - * - * History: - * 1/21/00 Created. - */ -static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */ -{ - struct usbvideo_frame *frame; - ibmcam_t *icam; - - if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("ibmcam_find_header: Illegal frame %d.", uvd->curframe); - return scan_EndParse; - } - icam = IBMCAM_T(uvd); - assert(icam != NULL); - frame = &uvd->frame[uvd->curframe]; - icam->has_hdr = 0; - switch (icam->camera_model) { - case IBMCAM_MODEL_1: - { - const int marker_len = 4; - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && - (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) - { -#if 0 /* This code helps to detect new frame markers */ - dev_info(&uvd->dev->dev, - "Header sig: 00 FF 00 %02X\n", - RING_QUEUE_PEEK(&uvd->dp, 3)); -#endif - frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); - if ((frame->header == HDRSIG_MODEL1_128x96) || - (frame->header == HDRSIG_MODEL1_176x144) || - (frame->header == HDRSIG_MODEL1_352x288)) - { -#if 0 - dev_info(&uvd->dev->dev, - "Header found.\n"); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - break; - } - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - case IBMCAM_MODEL_2: -case IBMCAM_MODEL_4: - { - int marker_len = 0; - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - marker_len = 10; - break; - default: - marker_len = 2; - break; - } - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) - { -#if 0 - dev_info(&uvd->dev->dev, "Header found.\n"); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - frame->header = HDRSIG_MODEL1_176x144; - break; - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - case IBMCAM_MODEL_3: - { /* - * Headers: (one precedes every frame). nc=no compression, - * bq=best quality bf=best frame rate. - * - * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf } - * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf } - * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf } - * - * Bytes '00 FF' seem to indicate header. Other two bytes - * encode the frame type. This is a set of bit fields that - * encode image size, compression type etc. These fields - * do NOT contain frame number because all frames carry - * the same header. - */ - const int marker_len = 4; - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && - (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF)) - { - /* - * Combine 2 bytes of frame type into one - * easy to use value - */ - unsigned long byte3, byte4; - - byte3 = RING_QUEUE_PEEK(&uvd->dp, 2); - byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); - frame->header = (byte3 << 8) | byte4; -#if 0 - dev_info(&uvd->dev->dev, "Header found.\n"); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - break; - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - default: - break; - } - if (!icam->has_hdr) { - if (uvd->debug > 2) - dev_info(&uvd->dev->dev, - "Skipping frame, no header\n"); - return scan_EndParse; - } - - /* Header found */ - icam->has_hdr = 1; - uvd->stats.header_count++; - frame->scanstate = ScanState_Lines; - frame->curline = 0; - - if (flags & FLAGS_FORCE_TESTPATTERN) { - usbvideo_TestPattern(uvd, 1, 1); - return scan_NextFrame; - } - return scan_Continue; -} - -/* - * ibmcam_parse_lines() - * - * Parse one line (interlaced) from the buffer, put - * decoded RGB value into the current frame buffer - * and add the written number of bytes (RGB) to - * the *pcopylen. - * - * History: - * 21-Jan-2000 Created. - * 12-Oct-2000 Reworked to reflect interlaced nature of the data. - */ -static enum ParseState ibmcam_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *f; - ibmcam_t *icam; - unsigned int len, scanLength, scanHeight, order_uv, order_yc; - int v4l_linesize; /* V4L line offset */ - const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ - const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ - const int ccm = 128; /* Color correction median - see below */ - int y, u, v, i, frame_done=0, color_corr; - static unsigned char lineBuffer[640*3]; - unsigned const char *chromaLine, *lumaLine; - - assert(uvd != NULL); - assert(frame != NULL); - icam = IBMCAM_T(uvd); - assert(icam != NULL); - color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) { - /* Model 4 frame markers do not carry image size identification */ - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - case VIDEOSIZE_160x120: - case VIDEOSIZE_176x144: - scanLength = VIDEOSIZE_X(uvd->videosize); - scanHeight = VIDEOSIZE_Y(uvd->videosize); - break; - default: - err("ibmcam_parse_lines: Wrong mode."); - return scan_Out; - } - order_yc = 1; /* order_yc: true=Yc false=cY ('c'=either U or V) */ - order_uv = 1; /* Always true in this algorithm */ - } else { - switch (frame->header) { - case HDRSIG_MODEL1_128x96: - scanLength = 128; - scanHeight = 96; - order_uv = 1; /* U Y V Y ... */ - break; - case HDRSIG_MODEL1_176x144: - scanLength = 176; - scanHeight = 144; - order_uv = 1; /* U Y V Y ... */ - break; - case HDRSIG_MODEL1_352x288: - scanLength = 352; - scanHeight = 288; - order_uv = 0; /* Y V Y V ... */ - break; - default: - err("Unknown header signature 00 FF 00 %02lX", frame->header); - return scan_NextFrame; - } - /* order_yc: true=Yc false=cY ('c'=either U or V) */ - order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2); - } - - len = scanLength * 3; - assert(len <= sizeof(lineBuffer)); - - /* - * Lines are organized this way: - * - * I420: - * ~~~~ - * <scanLength-> - * ___________________________________ - * |-----Y-----|---UVUVUV...UVUV-----| \ - * |-----------+---------------------| \ - * |<-- 176 -->|<------ 176*2 ------>| Total 72. lines (interlaced) - * |... ... | ... | / - * |<-- 352 -->|<------ 352*2 ------>| Total 144. lines (interlaced) - * |___________|_____________________| / - * \ \ - * lumaLine chromaLine - */ - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Mind that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) - return scan_NextFrame; - - /* - * Now we are sure that entire line (representing all 'scanLength' - * pixels from the camera) is available in the buffer. We - * start copying the line left-aligned to the V4L buffer. - * If the camera line is shorter then we should pad the V4L - * buffer with something (black) to complete the line. - */ - assert(frame->data != NULL); - f = frame->data + (v4l_linesize * frame->curline); - - /* - * To obtain chrominance data from the 'chromaLine' use this: - * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]... - * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]... - * - * Indices must be calculated this way: - * v_index = (i >> 1) << 2; - * u_index = (i >> 1) << 2 + 2; - * - * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1] - */ - lumaLine = lineBuffer; - chromaLine = lineBuffer + scanLength; - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) - { - unsigned char rv, gv, bv; /* RGB components */ - - /* Check for various visual debugging hints (colorized pixels) */ - if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) { - /* - * This is bad and should not happen. This means that - * we somehow overshoot the line and encountered new - * frame! Obviously our camera/V4L frame size is out - * of whack. This cyan dot will help you to figure - * out where exactly the new frame arrived. - */ - if (icam->has_hdr == 1) { - bv = 0; /* Yellow marker */ - gv = 0xFF; - rv = 0xFF; - } else { - bv = 0xFF; /* Cyan marker */ - gv = 0xFF; - rv = 0; - } - icam->has_hdr = 0; - goto make_pixel; - } - - /* - * Check if we are still in range. We may be out of range if our - * V4L canvas is wider or taller than the camera "native" image. - * Then we quickly fill the remainder of the line with zeros to - * make black color and quit the horizontal scanning loop. - */ - if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int j = i * V4L_BYTES_PER_PIXEL; -#if USES_IBMCAM_PUTPIXEL - /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + j; -#endif - memset(f, 0, v4l_linesize - j); - break; - } - - y = lumaLine[i]; - if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ - rv = gv = bv = y; - else { - int off_0, off_2; - - off_0 = (i >> 1) << 2; - off_2 = off_0 + 2; - - if (order_yc) { - off_0++; - off_2++; - } - if (!order_uv) { - off_0 += 2; - off_2 -= 2; - } - u = chromaLine[off_0] + hue_corr; - v = chromaLine[off_2] + hue2_corr; - - /* Apply color correction */ - if (color_corr != 0) { - /* Magnify up to 2 times, reduce down to zero saturation */ - u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; - v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; - } - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - } - - make_pixel: - /* - * The purpose of creating the pixel here, in one, - * dedicated place is that we may need to make the - * pixel wider and taller than it actually is. This - * may be used if camera generates small frames for - * sake of frame rate (or any other reason.) - * - * The output data consists of B, G, R bytes - * (in this order). - */ -#if USES_IBMCAM_PUTPIXEL - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); -#else - *f++ = bv; - *f++ = gv; - *f++ = rv; -#endif - /* - * Typically we do not decide within a legitimate frame - * that we want to end the frame. However debugging code - * may detect marker of new frame within the data. Then - * this condition activates. The 'data' pointer is already - * pointing at the new marker, so we'd better leave it as is. - */ - if (frame_done) - break; /* End scanning of lines */ - } - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - if (pcopylen != NULL) - *pcopylen += 2 * v4l_linesize; - frame->deinterlace = Deinterlace_FillOddLines; - - if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) - return scan_NextFrame; - else - return scan_Continue; -} - -/* - * ibmcam_model2_320x240_parse_lines() - * - * This procedure deals with a weird RGB format that is produced by IBM - * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175, - * depending on horizontal size of the picture: - * - * <--- 160 or 176 pairs of RA,RB bytes -----> - * *-----------------------------------------* \ - * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx | \ This is pair of horizontal lines, - * |-----+-----+-----+-----+ ... +-----+-----| *- or one interlaced line, total - * | B0 | G0 | B1 | G1 | ... | Bx | Gx | / 120 or 144 such pairs which yield - * |=====+=====+=====+=====+ ... +=====+=====| / 240 or 288 lines after deinterlacing. - * - * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1 - * defines ONE pixel. Therefore this format yields 176x144 "decoded" - * resolution at best. I do not know why camera sends such format - the - * previous model (1) just used interlaced I420 and everyone was happy. - * - * I do not know what is the difference between RAi and RBi bytes. Both - * seemingly represent R component, but slightly vary in value (so that - * the picture looks a bit colored if one or another is used). I use - * them both as R component in attempt to at least partially recover the - * lost resolution. - */ -static enum ParseState ibmcam_model2_320x240_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *f, *la, *lb; - unsigned int len; - int v4l_linesize; /* V4L line offset */ - int i, j, frame_done=0, color_corr; - int scanLength, scanHeight; - static unsigned char lineBuffer[352*2]; - - switch (uvd->videosize) { - case VIDEOSIZE_320x240: - case VIDEOSIZE_352x240: - case VIDEOSIZE_352x288: - scanLength = VIDEOSIZE_X(uvd->videosize); - scanHeight = VIDEOSIZE_Y(uvd->videosize); - break; - default: - err("ibmcam_model2_320x240_parse_lines: Wrong mode."); - return scan_Out; - } - - color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */ - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - len = scanLength * 2; /* See explanation above */ - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Mind that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) - return scan_NextFrame; - - la = lineBuffer; - lb = lineBuffer + scanLength; - - /* - * Now we are sure that entire line (representing all - * VIDEOSIZE_X(frame->request) - * pixels from the camera) is available in the scratch buffer. We - * start copying the line left-aligned to the V4L buffer (which - * might be larger - not smaller, hopefully). If the camera - * line is shorter then we should pad the V4L buffer with something - * (black in this case) to complete the line. - */ - f = frame->data + (v4l_linesize * frame->curline); - - /* Fill the 2-line strip */ - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y, rv, gv, bv; /* RGB components */ - - j = i & (~1); - - /* Check for various visual debugging hints (colorized pixels) */ - if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) { - if (IBMCAM_T(uvd)->has_hdr == 1) { - bv = 0; /* Yellow marker */ - gv = 0xFF; - rv = 0xFF; - } else { - bv = 0xFF; /* Cyan marker */ - gv = 0xFF; - rv = 0; - } - IBMCAM_T(uvd)->has_hdr = 0; - goto make_pixel; - } - - /* - * Check if we are still in range. We may be out of range if our - * V4L canvas is wider or taller than the camera "native" image. - * Then we quickly fill the remainder of the line with zeros to - * make black color and quit the horizontal scanning loop. - */ - if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int offset = i * V4L_BYTES_PER_PIXEL; -#if USES_IBMCAM_PUTPIXEL - /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + offset; -#endif - memset(f, 0, v4l_linesize - offset); - break; - } - - /* - * Here I use RA and RB components, one per physical pixel. - * This causes fine vertical grid on the picture but may improve - * horizontal resolution. If you prefer replicating, use this: - * rv = la[j + 0]; ... or ... rv = la[j + 1]; - * then the pixel will be replicated. - */ - rv = la[i]; - gv = lb[j + 1]; - bv = lb[j + 0]; - - y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */ - - if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ - rv = gv = bv = y; - else if (color_corr != 128) { - - /* Calculate difference between color and brightness */ - rv -= y; - gv -= y; - bv -= y; - - /* Scale differences */ - rv = (rv * color_corr) / 128; - gv = (gv * color_corr) / 128; - bv = (bv * color_corr) / 128; - - /* Reapply brightness */ - rv += y; - gv += y; - bv += y; - - /* Watch for overflows */ - RESTRICT_TO_RANGE(rv, 0, 255); - RESTRICT_TO_RANGE(gv, 0, 255); - RESTRICT_TO_RANGE(bv, 0, 255); - } - - make_pixel: - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); - } - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - *pcopylen += v4l_linesize * 2; - frame->deinterlace = Deinterlace_FillOddLines; - - if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) - return scan_NextFrame; - else - return scan_Continue; -} - -/* - * ibmcam_model3_parse_lines() - * - * | Even lines | Odd Lines | - * -----------------------------------| - * |YYY........Y|UYVYUYVY.........UYVY| - * |YYY........Y|UYVYUYVY.........UYVY| - * |............|.....................| - * |YYY........Y|UYVYUYVY.........UYVY| - * |------------+---------------------| - * - * There is one (U, V) chroma pair for every four luma (Y) values. This - * function reads a pair of lines at a time and obtains missing chroma values - * from adjacent pixels. - */ -static enum ParseState ibmcam_model3_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *data; - const unsigned char *color; - unsigned int len; - int v4l_linesize; /* V4L line offset */ - const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ - const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ - const int ccm = 128; /* Color correction median - see below */ - int i, u, v, rw, data_w=0, data_h=0, color_corr; - static unsigned char lineBuffer[640*3]; - int line; - - color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - /* The header tells us what sort of data is in this frame */ - switch (frame->header) { - /* - * Uncompressed modes (that are easy to decode). - */ - case 0x0308: - data_w = 640; - data_h = 480; - break; - case 0x0208: - data_w = 320; - data_h = 240; - break; - case 0x020A: - data_w = 160; - data_h = 120; - break; - /* - * Compressed modes (ViCE - that I don't know how to decode). - */ - case 0x0328: /* 640x480, best quality compression */ - case 0x0368: /* 640x480, best frame rate compression */ - case 0x0228: /* 320x240, best quality compression */ - case 0x0268: /* 320x240, best frame rate compression */ - case 0x02CA: /* 160x120, best quality compression */ - case 0x02EA: /* 160x120, best frame rate compression */ - /* Do nothing with this - not supported */ - err("Unsupported mode $%04lx", frame->header); - return scan_NextFrame; - default: - /* Catch unknown headers, may help in learning new headers */ - err("Strange frame->header=$%08lx", frame->header); - return scan_NextFrame; - } - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Note that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 1) >= data_h) { - if (uvd->debug >= 3) - dev_info(&uvd->dev->dev, - "Reached line %d. (frame is done)\n", - frame->curline); - return scan_NextFrame; - } - - /* Make sure that lineBuffer can store two lines of data */ - len = 3 * data_w; /* <y-data> <uyvy-data> */ - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for two lines */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck two lines of data out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - data = lineBuffer; - color = data + data_w; /* Point to where color planes begin */ - - /* Bottom-to-top scanning */ - rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1; - RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1); - - /* Iterate over two lines. */ - for (line = 0; line < 2; line++) { - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y; - int rv, gv, bv; /* RGB components */ - - if (i >= data_w) { - RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0); - continue; - } - - /* first line is YYY...Y; second is UYVY...UYVY */ - y = data[(line == 0) ? i : (i*2 + 1)]; - - /* Apply static color correction */ - u = color[(i/2)*4] + hue_corr; - v = color[(i/2)*4 + 2] + hue2_corr; - - /* Apply color correction */ - if (color_corr != 0) { - /* Magnify up to 2 times, reduce down to zero saturation */ - u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; - v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; - } - - - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* No deinterlacing */ - } - - /* Check for the end of requested data */ - if (rw == 0) - break; - - /* Prepare for the second line */ - rw--; - data = lineBuffer + data_w; - } - frame->deinterlace = Deinterlace_None; - - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - *pcopylen += 2 * v4l_linesize; - - if (frame->curline >= VIDEOSIZE_Y(frame->request)) { - if (uvd->debug >= 3) { - dev_info(&uvd->dev->dev, - "All requested lines (%ld.) done.\n", - VIDEOSIZE_Y(frame->request)); - } - return scan_NextFrame; - } else - return scan_Continue; -} - -/* - * ibmcam_model4_128x96_parse_lines() - * - * This decoder is for one strange data format that is produced by Model 4 - * camera only in 128x96 mode. This is RGB format and here is its description. - * First of all, this is non-interlaced stream, meaning that all scan lines - * are present in the datastream. There are 96 consecutive blocks of data - * that describe all 96 lines of the image. Each block is 5*128 bytes long - * and carries R, G, B components. The format of the block is shown in the - * code below. First 128*2 bytes are interleaved R and G components. Then - * we have a gap (junk data) 64 bytes long. Then follow B and something - * else, also interleaved (this makes another 128*2 bytes). After that - * probably another 64 bytes of junk follow. - * - * History: - * 10-Feb-2001 Created. - */ -static enum ParseState ibmcam_model4_128x96_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - const unsigned char *data_rv, *data_gv, *data_bv; - unsigned int len; - int i, v4l_linesize; /* V4L line offset */ - const int data_w=128, data_h=96; - static unsigned char lineBuffer[128*5]; - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Note that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 1) >= data_h) { - if (uvd->debug >= 3) - dev_info(&uvd->dev->dev, - "Reached line %d. (frame is done)\n", - frame->curline); - return scan_NextFrame; - } - - /* - * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________ - * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 ---> - */ - - /* Make sure there's enough data for the entire line */ - len = 5 * data_w; - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - data_rv = lineBuffer; - data_gv = lineBuffer + 1; - data_bv = lineBuffer + data_w*2 + data_w/2; - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int rv, gv, bv; /* RGB components */ - if (i < data_w) { - const int j = i * 2; - gv = data_rv[j]; - rv = data_gv[j]; - bv = data_bv[j]; - if (flags & FLAGS_MONOCHROME) { - unsigned long y; - y = rv + gv + bv; - y /= 3; - if (y > 0xFF) - y = 0xFF; - rv = gv = bv = (unsigned char) y; - } - } else { - rv = gv = bv = 0; - } - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); - } - frame->deinterlace = Deinterlace_None; - frame->curline++; - *pcopylen += v4l_linesize; - - if (frame->curline >= VIDEOSIZE_Y(frame->request)) { - if (uvd->debug >= 3) { - dev_info(&uvd->dev->dev, - "All requested lines (%ld.) done.\n", - VIDEOSIZE_Y(frame->request)); - } - return scan_NextFrame; - } else - return scan_Continue; -} - -/* - * ibmcam_ProcessIsocData() - * - * Generic routine to parse the ring queue data. It employs either - * ibmcam_find_header() or ibmcam_parse_lines() to do most - * of work. - * - * History: - * 1/21/00 Created. - */ -static void ibmcam_ProcessIsocData(struct uvd *uvd, - struct usbvideo_frame *frame) -{ - enum ParseState newstate; - long copylen = 0; - int mod = IBMCAM_T(uvd)->camera_model; - - while (1) { - newstate = scan_Out; - if (RingQueue_GetLength(&uvd->dp) > 0) { - if (frame->scanstate == ScanState_Scanning) { - newstate = ibmcam_find_header(uvd); - } else if (frame->scanstate == ScanState_Lines) { - if ((mod == IBMCAM_MODEL_2) && - ((uvd->videosize == VIDEOSIZE_352x288) || - (uvd->videosize == VIDEOSIZE_320x240) || - (uvd->videosize == VIDEOSIZE_352x240))) - { - newstate = ibmcam_model2_320x240_parse_lines( - uvd, frame, ©len); - } else if (mod == IBMCAM_MODEL_4) { - /* - * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB) - * for 320x240 and above; 160x120 and 176x144 uses Model 1 - * decoder (YUV), and 128x96 mode uses ??? - */ - if ((uvd->videosize == VIDEOSIZE_352x288) || - (uvd->videosize == VIDEOSIZE_320x240) || - (uvd->videosize == VIDEOSIZE_352x240)) - { - newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, ©len); - } else if (uvd->videosize == VIDEOSIZE_128x96) { - newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, ©len); - } else { - newstate = ibmcam_parse_lines(uvd, frame, ©len); - } - } else if (mod == IBMCAM_MODEL_3) { - newstate = ibmcam_model3_parse_lines(uvd, frame, ©len); - } else { - newstate = ibmcam_parse_lines(uvd, frame, ©len); - } - } - } - if (newstate == scan_Continue) - continue; - else if ((newstate == scan_NextFrame) || (newstate == scan_Out)) - break; - else - return; /* scan_EndParse */ - } - - if (newstate == scan_NextFrame) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) { - /* Need software contrast adjustment for those cameras */ - frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST; - } - } - - /* Update the frame's uncompressed length. */ - frame->seqRead_Length += copylen; - -#if 0 - { - static unsigned char j=0; - memset(frame->data, j++, uvd->max_frame_size); - frame->frameState = FrameState_Ready; - } -#endif -} - -/* - * ibmcam_veio() - * - * History: - * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. - */ -static int ibmcam_veio( - struct uvd *uvd, - unsigned char req, - unsigned short value, - unsigned short index) -{ - static const char proc[] = "ibmcam_veio"; - unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; - int i; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return 0; - - if (req == 1) { - i = usb_control_msg( - uvd->dev, - usb_rcvctrlpipe(uvd->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, - index, - cp, - sizeof(cp), - 1000); -#if 0 - dev_info(&uvd->dev->dev, - "USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)\n", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); -#endif - } else { - i = usb_control_msg( - uvd->dev, - usb_sndctrlpipe(uvd->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, - index, - NULL, - 0, - 1000); - } - if (i < 0) { - err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", - proc, i); - uvd->last_error = i; - } - return i; -} - -/* - * ibmcam_calculate_fps() - * - * This procedure roughly calculates the real frame rate based - * on FPS code (framerate=NNN option). Actual FPS differs - * slightly depending on lighting conditions, so that actual frame - * rate is determined by the camera. Since I don't know how to ask - * the camera what FPS is now I have to use the FPS code instead. - * - * The FPS code is in range [0..6], 0 is slowest, 6 is fastest. - * Corresponding real FPS should be in range [3..30] frames per second. - * The conversion formula is obvious: - * - * real_fps = 3 + (fps_code * 4.5) - * - * History: - * 1/18/00 Created. - */ -static int ibmcam_calculate_fps(struct uvd *uvd) -{ - return 3 + framerate*4 + framerate/2; -} - -/* - * ibmcam_send_FF_04_02() - * - * This procedure sends magic 3-command prefix to the camera. - * The purpose of this prefix is not known. - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_send_FF_04_02(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x00FF, 0x0127); - ibmcam_veio(uvd, 0, 0x0004, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); -} - -static void ibmcam_send_00_04_06(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x0004, 0x0124); - ibmcam_veio(uvd, 0, 0x0006, 0x0124); -} - -static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); -} - -static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x) -{ - ibmcam_send_x_00(uvd, x); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); -} - -static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); -} - -static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); -} - -static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); -} - -static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); -} - -static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val) -{ - ibmcam_send_x_01_00_05(uvd, unknown_88); - ibmcam_send_x_00_05(uvd, fkey); - ibmcam_send_x_00_05_02_08_01(uvd, val); - ibmcam_send_x_00_05(uvd, unknown_88); - ibmcam_send_x_00_05_02_01(uvd, fkey); - ibmcam_send_x_00_05(uvd, unknown_89); - ibmcam_send_x_00(uvd, fkey); - ibmcam_send_00_04_06(uvd); - ibmcam_veio(uvd, 1, 0x0000, 0x0126); - ibmcam_send_FF_04_02(uvd); -} - -static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val) -{ - ibmcam_send_x_01_00_05 (uvd, unknown_88); - ibmcam_send_x_00_05 (uvd, fkey); - ibmcam_send_x_00_05_02 (uvd, val); -} - -static void ibmcam_model2_Packet2(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x00ff, 0x012d); - ibmcam_veio(uvd, 0, 0xfea3, 0x0124); -} - -static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) -{ - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x00ff, 0x012e); - ibmcam_veio(uvd, 0, v1, 0x012f); - ibmcam_veio(uvd, 0, 0x00ff, 0x0130); - ibmcam_veio(uvd, 0, 0xc719, 0x0124); - ibmcam_veio(uvd, 0, v2, 0x0127); - - ibmcam_model2_Packet2(uvd); -} - -/* - * ibmcam_model3_Packet1() - * - * 00_0078_012d - * 00_0097_012f - * 00_d141_0124 - * 00_0096_0127 - * 00_fea8_0124 -*/ -static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) -{ - ibmcam_veio(uvd, 0, 0x0078, 0x012d); - ibmcam_veio(uvd, 0, v1, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, v2, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); -} - -static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i) -{ - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0026, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, i, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); -} - -/* - * ibmcam_adjust_contrast() - * - * The contrast value changes from 0 (high contrast) to 15 (low contrast). - * This is in reverse to usual order of things (such as TV controls), so - * we reverse it again here. - * - * TODO: we probably don't need to send the setup 5 times... - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_adjust_contrast(struct uvd *uvd) -{ - unsigned char a_contrast = uvd->vpic.contrast >> 12; - unsigned char new_contrast; - - if (a_contrast >= 16) - a_contrast = 15; - new_contrast = 15 - a_contrast; - if (new_contrast == uvd->vpic_old.contrast) - return; - uvd->vpic_old.contrast = new_contrast; - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - const int ntries = 5; - int i; - for (i=0; i < ntries; i++) { - ibmcam_Packet_Format1(uvd, contrast_14, new_contrast); - ibmcam_send_FF_04_02(uvd); - } - break; - } - case IBMCAM_MODEL_2: - case IBMCAM_MODEL_4: - /* Models 2, 4 do not have this control; implemented in software. */ - break; - case IBMCAM_MODEL_3: - { /* Preset hardware values */ - static const struct { - unsigned short cv1; - unsigned short cv2; - unsigned short cv3; - } cv[7] = { - { 0x05, 0x05, 0x0f }, /* Minimum */ - { 0x04, 0x04, 0x16 }, - { 0x02, 0x03, 0x16 }, - { 0x02, 0x08, 0x16 }, - { 0x01, 0x0c, 0x16 }, - { 0x01, 0x0e, 0x16 }, - { 0x01, 0x10, 0x16 } /* Maximum */ - }; - int i = a_contrast / 2; - RESTRICT_TO_RANGE(i, 0, 6); - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1); - ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2); - ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - break; - } - default: - break; - } -} - -/* - * ibmcam_change_lighting_conditions() - * - * Camera model 1: - * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. - * - * Camera model 2: - * We have 16 levels of lighting, 0 for bright light and up to 15 for - * low light. But values above 5 or so are useless because camera is - * not really capable to produce anything worth viewing at such light. - * This setting may be altered only in certain camera state. - * - * Low lighting forces slower FPS. Lighting is set as a module parameter. - * - * History: - * 1/5/00 Created. - * 2/20/00 Added support for Model 2 cameras. - */ -static void ibmcam_change_lighting_conditions(struct uvd *uvd) -{ - if (debug > 0) - dev_info(&uvd->dev->dev, - "%s: Set lighting to %hu.\n", __func__, lighting); - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - const int ntries = 5; - int i; - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting); - break; - } - case IBMCAM_MODEL_2: -#if 0 - /* - * This command apparently requires camera to be stopped. My - * experiments showed that it -is- possible to alter the lighting - * conditions setting "on the fly", but why bother? This setting does - * not work reliably in all cases, so I decided simply to leave the - * setting where Xirlink put it - in the camera setup phase. This code - * is commented out because it does not work at -any- moment, so its - * presence makes no sense. You may use it for experiments. - */ - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop camera */ - ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Start camera */ -#endif - break; - case IBMCAM_MODEL_3: - case IBMCAM_MODEL_4: - default: - break; - } -} - -/* - * ibmcam_set_sharpness() - * - * Cameras model 1 have internal smoothing feature. It is controlled by value in - * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). - * Recommended value is 4. Cameras model 2 do not have this feature at all. - */ -static void ibmcam_set_sharpness(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; - unsigned short i, sv; - - RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); - if (debug > 0) - dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n", - __func__, sharpness); - - sv = sa[sharpness - SHARPNESS_MIN]; - for (i=0; i < 2; i++) { - ibmcam_send_x_01_00_05 (uvd, unknown_88); - ibmcam_send_x_00_05 (uvd, sharp_13); - ibmcam_send_x_00_05_02 (uvd, sv); - } - break; - } - case IBMCAM_MODEL_2: - case IBMCAM_MODEL_4: - /* Models 2, 4 do not have this control */ - break; - case IBMCAM_MODEL_3: - { /* - * "Use a table of magic numbers. - * This setting doesn't really change much. - * But that's how Windows does it." - */ - static const struct { - unsigned short sv1; - unsigned short sv2; - unsigned short sv3; - unsigned short sv4; - } sv[7] = { - { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */ - { 0x01, 0x04, 0x05, 0x14 }, - { 0x02, 0x04, 0x05, 0x14 }, - { 0x03, 0x04, 0x05, 0x14 }, - { 0x03, 0x05, 0x05, 0x14 }, - { 0x03, 0x06, 0x05, 0x14 }, - { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */ - }; - RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); - RESTRICT_TO_RANGE(sharpness, 0, 6); - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1); - ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2); - ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3); - ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); - break; - } - default: - break; - } -} - -/* - * ibmcam_set_brightness() - * - * This procedure changes brightness of the picture. - */ -static void ibmcam_set_brightness(struct uvd *uvd) -{ - static const unsigned short n = 1; - - if (debug > 0) - dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n", - __func__, uvd->vpic.brightness); - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - unsigned short i, j, bv[3]; - bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10; - if (bv[0] == (uvd->vpic_old.brightness >> 10)) - return; - uvd->vpic_old.brightness = bv[0]; - for (j=0; j < 3; j++) - for (i=0; i < n; i++) - ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]); - break; - } - case IBMCAM_MODEL_2: - { - unsigned short i, j; - i = uvd->vpic.brightness >> 12; /* 0 .. 15 */ - j = 0x60 + i * ((0xee - 0x60) / 16); /* 0x60 .. 0xee or so */ - if (uvd->vpic_old.brightness == j) - break; - uvd->vpic_old.brightness = j; - ibmcam_model2_Packet1(uvd, mod2_brightness, j); - break; - } - case IBMCAM_MODEL_3: - { - /* Model 3: Brightness range 'i' in [0x0C..0x3F] */ - unsigned short i = - 0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1))); - RESTRICT_TO_RANGE(i, 0x0C, 0x3F); - if (uvd->vpic_old.brightness == i) - break; - uvd->vpic_old.brightness = i; - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0036, i); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); - break; - } - case IBMCAM_MODEL_4: - { - /* Model 4: Brightness range 'i' in [0x04..0xb4] */ - unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1))); - RESTRICT_TO_RANGE(i, 0x04, 0xb4); - if (uvd->vpic_old.brightness == i) - break; - uvd->vpic_old.brightness = i; - ibmcam_model4_BrightnessPacket(uvd, i); - break; - } - default: - break; - } -} - -static void ibmcam_set_hue(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_2: - { - unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */ - if (uvd->vpic_old.hue == hue) - return; - uvd->vpic_old.hue = hue; - ibmcam_model2_Packet1(uvd, mod2_hue, hue); - /* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */ - break; - } - case IBMCAM_MODEL_3: - { -#if 0 /* This seems not to work. No problem, will fix programmatically */ - unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1))); - RESTRICT_TO_RANGE(hue, 0x05, 0x37); - if (uvd->vpic_old.hue == hue) - return; - uvd->vpic_old.hue = hue; - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x007e, hue); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); -#endif - break; - } - case IBMCAM_MODEL_4: - { - unsigned short r_gain, g_gain, b_gain, hue; - - /* - * I am not sure r/g/b_gain variables exactly control gain - * of those channels. Most likely they subtly change some - * very internal image processing settings in the camera. - * In any case, here is what they do, and feel free to tweak: - * - * r_gain: seriously affects red gain - * g_gain: seriously affects green gain - * b_gain: seriously affects blue gain - * hue: changes average color from violet (0) to red (0xFF) - * - * These settings are preset for a decent white balance in - * 320x240, 352x288 modes. Low-res modes exhibit higher contrast - * and therefore may need different values here. - */ - hue = 20 + (uvd->vpic.hue >> 9); - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - r_gain = 90; - g_gain = 166; - b_gain = 175; - break; - case VIDEOSIZE_160x120: - r_gain = 70; - g_gain = 166; - b_gain = 185; - break; - case VIDEOSIZE_176x144: - r_gain = 160; - g_gain = 175; - b_gain = 185; - break; - default: - r_gain = 120; - g_gain = 166; - b_gain = 175; - break; - } - RESTRICT_TO_RANGE(hue, 1, 0x7f); - - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, g_gain, 0x0127); /* Green gain */ - ibmcam_veio(uvd, 0, r_gain, 0x012e); /* Red gain */ - ibmcam_veio(uvd, 0, b_gain, 0x0130); /* Blue gain */ - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, hue, 0x012d); /* Hue */ - ibmcam_veio(uvd, 0, 0xf545, 0x0124); - break; - } - default: - break; - } -} - -/* - * ibmcam_adjust_picture() - * - * This procedure gets called from V4L interface to update picture settings. - * Here we change brightness and contrast. - */ -static void ibmcam_adjust_picture(struct uvd *uvd) -{ - ibmcam_adjust_contrast(uvd); - ibmcam_set_brightness(uvd); - ibmcam_set_hue(uvd); -} - -static int ibmcam_model1_setup(struct uvd *uvd) -{ - const int ntries = 5; - int i; - - ibmcam_veio(uvd, 1, 0x00, 0x0128); - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 0, 0x01, 0x0108); - - ibmcam_veio(uvd, 0, 0x03, 0x0112); - ibmcam_veio(uvd, 1, 0x00, 0x0115); - ibmcam_veio(uvd, 0, 0x06, 0x0115); - ibmcam_veio(uvd, 1, 0x00, 0x0116); - ibmcam_veio(uvd, 0, 0x44, 0x0116); - ibmcam_veio(uvd, 1, 0x00, 0x0116); - ibmcam_veio(uvd, 0, 0x40, 0x0116); - ibmcam_veio(uvd, 1, 0x00, 0x0115); - ibmcam_veio(uvd, 0, 0x0e, 0x0115); - ibmcam_veio(uvd, 0, 0x19, 0x012c); - - ibmcam_Packet_Format1(uvd, 0x00, 0x1e); - ibmcam_Packet_Format1(uvd, 0x39, 0x0d); - ibmcam_Packet_Format1(uvd, 0x39, 0x09); - ibmcam_Packet_Format1(uvd, 0x3b, 0x00); - ibmcam_Packet_Format1(uvd, 0x28, 0x22); - ibmcam_Packet_Format1(uvd, light_27, 0); - ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); - ibmcam_Packet_Format1(uvd, 0x39, 0x08); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x2c, 0x00); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x30, 0x14); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x01, 0xe1); - ibmcam_PacketFormat2(uvd, 0x02, 0xcd); - ibmcam_PacketFormat2(uvd, 0x03, 0xcd); - ibmcam_PacketFormat2(uvd, 0x04, 0xfa); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x0a, 0x37); - ibmcam_PacketFormat2(uvd, 0x0b, 0xb8); - ibmcam_PacketFormat2(uvd, 0x0c, 0xf3); - ibmcam_PacketFormat2(uvd, 0x0d, 0xe3); - ibmcam_PacketFormat2(uvd, 0x0e, 0x0d); - ibmcam_PacketFormat2(uvd, 0x0f, 0xf2); - ibmcam_PacketFormat2(uvd, 0x10, 0xd5); - ibmcam_PacketFormat2(uvd, 0x11, 0xba); - ibmcam_PacketFormat2(uvd, 0x12, 0x53); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x16, 0x00); - ibmcam_PacketFormat2(uvd, 0x17, 0x28); - ibmcam_PacketFormat2(uvd, 0x18, 0x7d); - ibmcam_PacketFormat2(uvd, 0x19, 0xbe); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x00, 0x18); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x13, 0x18); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x14, 0x06); - - /* This is default brightness */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x31, 0x37); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x32, 0x46); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x33, 0x55); - - ibmcam_Packet_Format1(uvd, 0x2e, 0x04); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x2d, 0x04); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x29, 0x80); - ibmcam_Packet_Format1(uvd, 0x2c, 0x01); - ibmcam_Packet_Format1(uvd, 0x30, 0x17); - ibmcam_Packet_Format1(uvd, 0x39, 0x08); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x34, 0x00); - - ibmcam_veio(uvd, 0, 0x00, 0x0101); - ibmcam_veio(uvd, 0, 0x00, 0x010a); - - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_veio(uvd, 0, 0x80, 0x0103); - ibmcam_veio(uvd, 0, 0x60, 0x0105); - ibmcam_veio(uvd, 0, 0x0c, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x0b, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x00, 0x0129); - break; - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0xb0, 0x0103); - ibmcam_veio(uvd, 0, 0x8f, 0x0105); - ibmcam_veio(uvd, 0, 0x06, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x0d, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x03, 0x0129); - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0xb0, 0x0103); - ibmcam_veio(uvd, 0, 0x90, 0x0105); - ibmcam_veio(uvd, 0, 0x02, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x05, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x00, 0x0129); - break; - } - - ibmcam_veio(uvd, 0, 0xff, 0x012b); - - /* This is another brightness - don't know why */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x31, 0xc3); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x32, 0xd2); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x33, 0xe1); - - /* Default contrast */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, contrast_14, 0x0a); - - /* Default sharpness */ - for (i=0; i < 2; i++) - ibmcam_PacketFormat2(uvd, sharp_13, 0x1a); /* Level 4 FIXME */ - - /* Default lighting conditions */ - ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */ - - /* Assorted init */ - - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x36, 0x0102); - ibmcam_veio(uvd, 0, 0x1a, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2b, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ -#if 0 - ibmcam_veio(uvd, 0, 0x00, 0x0106); - ibmcam_veio(uvd, 0, 0x38, 0x0107); -#else - ibmcam_veio(uvd, 0, 0x02, 0x0106); - ibmcam_veio(uvd, 0, 0x2a, 0x0107); -#endif - break; - case VIDEOSIZE_176x144: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x04, 0x0102); - ibmcam_veio(uvd, 0, 0x02, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2b, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x01, 0x0106); - ibmcam_veio(uvd, 0, 0xca, 0x0107); - break; - case VIDEOSIZE_352x288: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x08, 0x0102); - ibmcam_veio(uvd, 0, 0x01, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2f, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x03, 0x0106); - ibmcam_veio(uvd, 0, 0xf6, 0x0107); - break; - } - return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); -} - -static int ibmcam_model2_setup(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0112); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0008, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0038, 0x0119); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x0090, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0028, 0x0103); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x0098, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_352x240: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x00da, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x00fe, 0x0107); /* Unique to every mode*/ - break; - } - return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); -} - -/* - * ibmcam_model1_setup_after_video_if() - * - * This code adds finishing touches to the video data interface. - * Here we configure the frame rate and turn on the LED. - */ -static void ibmcam_model1_setup_after_video_if(struct uvd *uvd) -{ - unsigned short internal_frame_rate; - - RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); - internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */ - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111); - ibmcam_veio(uvd, 0, 0x01, 0x0114); - ibmcam_veio(uvd, 0, 0xc0, 0x010c); -} - -static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) -{ - unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb; - - ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ - - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x0050, 0x0111); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - break; - case VIDEOSIZE_320x240: - case VIDEOSIZE_352x240: - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x0040, 0x0111); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - break; - } - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - - /* - * Hardware settings, may affect CMOS sensor; not user controls! - * ------------------------------------------------------------- - * 0x0004: no effect - * 0x0006: hardware effect - * 0x0008: no effect - * 0x000a: stops video stream, probably important h/w setting - * 0x000c: changes color in hardware manner (not user setting) - * 0x0012: changes number of colors (does not affect speed) - * 0x002a: no effect - * 0x002c: hardware setting (related to scan lines) - * 0x002e: stops video stream, probably important h/w setting - */ - ibmcam_model2_Packet1(uvd, 0x000a, 0x005c); - ibmcam_model2_Packet1(uvd, 0x0004, 0x0000); - ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb); - ibmcam_model2_Packet1(uvd, 0x0008, 0x0000); - ibmcam_model2_Packet1(uvd, 0x000c, 0x0009); - ibmcam_model2_Packet1(uvd, 0x0012, 0x000a); - ibmcam_model2_Packet1(uvd, 0x002a, 0x0000); - ibmcam_model2_Packet1(uvd, 0x002c, 0x0000); - ibmcam_model2_Packet1(uvd, 0x002e, 0x0008); - - /* - * Function 0x0030 pops up all over the place. Apparently - * it is a hardware control register, with every bit assigned to - * do something. - */ - ibmcam_model2_Packet1(uvd, 0x0030, 0x0000); - - /* - * Magic control of CMOS sensor. Only lower values like - * 0-3 work, and picture shifts left or right. Don't change. - */ - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0002); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ - break; - case VIDEOSIZE_320x240: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */ - break; - case VIDEOSIZE_352x240: - /* This mode doesn't work as Windows programs it; changed to work */ - ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */ - ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */ - break; - case VIDEOSIZE_352x288: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0003); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ - break; - } - - ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a); - - /* - * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest). - * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the - * slowest setting. However for all practical reasons high settings make no - * sense because USB is not fast enough to support high FPS. Be aware that - * the picture datastream will be severely disrupted if you ask for - * frame rate faster than allowed for the video size - see below: - * - * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz): - * ----------------------------------------------------------------- - * 176x144: [6..31] - * 320x240: [8..31] - * 352x240: [10..31] - * 352x288: [16..31] I have to raise lower threshold for stability... - * - * As usual, slower FPS provides better sensitivity. - */ - { - short hw_fps=31, i_framerate; - - RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); - i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN; - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - hw_fps = 6 + i_framerate*4; - break; - case VIDEOSIZE_320x240: - hw_fps = 8 + i_framerate*3; - break; - case VIDEOSIZE_352x240: - hw_fps = 10 + i_framerate*2; - break; - case VIDEOSIZE_352x288: - hw_fps = 28 + i_framerate/2; - break; - } - if (uvd->debug > 0) - dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n", - hw_fps); - RESTRICT_TO_RANGE(hw_fps, 0, 31); - ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); - } - - /* - * This setting does not visibly affect pictures; left it here - * because it was present in Windows USB data stream. This function - * does not allow arbitrary values and apparently is a bit mask, to - * be activated only at appropriate time. Don't change it randomly! - */ - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2); - break; - case VIDEOSIZE_320x240: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0044); - break; - case VIDEOSIZE_352x240: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0046); - break; - case VIDEOSIZE_352x288: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0048); - break; - } - - ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); - - if (init_model2_rg2 >= 0) { - RESTRICT_TO_RANGE(init_model2_rg2, 0, 255); - setup_model2_rg2 = init_model2_rg2; - } else - setup_model2_rg2 = 0x002f; - - if (init_model2_sat >= 0) { - RESTRICT_TO_RANGE(init_model2_sat, 0, 255); - setup_model2_sat = init_model2_sat; - } else - setup_model2_sat = 0x0034; - - if (init_model2_yb >= 0) { - RESTRICT_TO_RANGE(init_model2_yb, 0, 255); - setup_model2_yb = init_model2_yb; - } else - setup_model2_yb = 0x00a0; - - ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2); - ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat); - ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb); - ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */; - - /* Hardware control command */ - ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); - - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go camera, go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -static void ibmcam_model4_setup_after_video_if(struct uvd *uvd) -{ - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00d2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x005e, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000a, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00eb, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0031, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x012d); - ibmcam_veio(uvd, 0, 0x0078, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x0119); - ibmcam_veio(uvd, 0, 0x00d8, 0x0107); - ibmcam_veio(uvd, 0, 0x0002, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000b, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00c7, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0025, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0048, 0x0127); - ibmcam_veio(uvd, 0, 0x0035, 0x012e); - ibmcam_veio(uvd, 0, 0x00d0, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0048, 0x012d); - ibmcam_veio(uvd, 0, 0x0090, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x0119); - ibmcam_veio(uvd, 0, 0x00d6, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x0018, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x002c, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x0024, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0007, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0001, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005e, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0049, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00c7, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0028, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x002a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x012d); - ibmcam_veio(uvd, 0, 0x006d, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00d2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x005e, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000a, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00eb, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0031, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x012d); - ibmcam_veio(uvd, 0, 0x0078, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00f2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x008c, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x002c, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x0024, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0006, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0002, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005e, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0049, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00cf, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0025, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x012d); - ibmcam_veio(uvd, 0, 0x0048, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - } - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) -{ - int i; - /* - * 01.01.08 - Added for RCA video in support -LO - * This struct is used to init the Model3 cam to use the RCA video in port - * instead of the CCD sensor. - */ - static const struct struct_initData initData[] = { - {0, 0x0000, 0x010c}, - {0, 0x0006, 0x012c}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {1, 0x0000, 0x0116}, - {0, 0x0064, 0x0116}, - {1, 0x0000, 0x0115}, - {0, 0x0003, 0x0115}, - {0, 0x0008, 0x0123}, - {0, 0x0000, 0x0117}, - {0, 0x0000, 0x0112}, - {0, 0x0080, 0x0100}, - {0, 0x0000, 0x0100}, - {1, 0x0000, 0x0116}, - {0, 0x0060, 0x0116}, - {0, 0x0002, 0x0112}, - {0, 0x0000, 0x0123}, - {0, 0x0001, 0x0117}, - {0, 0x0040, 0x0108}, - {0, 0x0019, 0x012c}, - {0, 0x0040, 0x0116}, - {0, 0x000a, 0x0115}, - {0, 0x000b, 0x0115}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {0, 0x0064, 0x0116}, - {0, 0x0000, 0x0115}, - {0, 0x0001, 0x0115}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00aa, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f2, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f8, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00fc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f9, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x003c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0027, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0019, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0021, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0006, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0045, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002a, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002b, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f4, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0004, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002d, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0053, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0000, 0x0101}, - {0, 0x00a0, 0x0103}, - {0, 0x0078, 0x0105}, - {0, 0x0000, 0x010a}, - {0, 0x0024, 0x010b}, - {0, 0x0028, 0x0119}, - {0, 0x0088, 0x011b}, - {0, 0x0002, 0x011d}, - {0, 0x0003, 0x011e}, - {0, 0x0000, 0x0129}, - {0, 0x00fc, 0x012b}, - {0, 0x0008, 0x0102}, - {0, 0x0000, 0x0104}, - {0, 0x0008, 0x011a}, - {0, 0x0028, 0x011c}, - {0, 0x0021, 0x012a}, - {0, 0x0000, 0x0118}, - {0, 0x0000, 0x0132}, - {0, 0x0000, 0x0109}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0031, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00dc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0032, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0020, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0030, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0008, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0003, 0x0106}, - {0, 0x0062, 0x0107}, - {0, 0x0003, 0x0111}, - }; -#define NUM_INIT_DATA - - unsigned short compression = 0; /* 0=none, 7=best frame rate */ - int f_rate; /* 0=Fastest 7=slowest */ - - if (IBMCAM_T(uvd)->initialized) - return; - - /* Internal frame rate is controlled by f_rate value */ - f_rate = 7 - framerate; - RESTRICT_TO_RANGE(f_rate, 0, 7); - - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0112); - ibmcam_veio(uvd, 0, 0x0000, 0x0123); - ibmcam_veio(uvd, 0, 0x0001, 0x0117); - ibmcam_veio(uvd, 0, 0x0040, 0x0108); - ibmcam_veio(uvd, 0, 0x0019, 0x012c); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0115); - ibmcam_veio(uvd, 0, 0x0003, 0x0115); - ibmcam_veio(uvd, 1, 0x0000, 0x0115); - ibmcam_veio(uvd, 0, 0x000b, 0x0115); - ibmcam_model3_Packet1(uvd, 0x000a, 0x0040); - ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6); - ibmcam_model3_Packet1(uvd, 0x000c, 0x0002); - ibmcam_model3_Packet1(uvd, 0x000d, 0x0020); - ibmcam_model3_Packet1(uvd, 0x000e, 0x0033); - ibmcam_model3_Packet1(uvd, 0x000f, 0x0007); - ibmcam_model3_Packet1(uvd, 0x0010, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0011, 0x0070); - ibmcam_model3_Packet1(uvd, 0x0012, 0x0030); - ibmcam_model3_Packet1(uvd, 0x0013, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0014, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0015, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0016, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0017, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0018, 0x0000); - ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3); - ibmcam_model3_Packet1(uvd, 0x0020, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0028, 0x0010); - ibmcam_model3_Packet1(uvd, 0x0029, 0x0054); - ibmcam_model3_Packet1(uvd, 0x002a, 0x0013); - ibmcam_model3_Packet1(uvd, 0x002b, 0x0007); - ibmcam_model3_Packet1(uvd, 0x002d, 0x0028); - ibmcam_model3_Packet1(uvd, 0x002e, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0031, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0032, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0033, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0034, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0035, 0x0038); - ibmcam_model3_Packet1(uvd, 0x003a, 0x0001); - ibmcam_model3_Packet1(uvd, 0x003c, 0x001e); - ibmcam_model3_Packet1(uvd, 0x003f, 0x000a); - ibmcam_model3_Packet1(uvd, 0x0041, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0046, 0x003f); - ibmcam_model3_Packet1(uvd, 0x0047, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0050, 0x0005); - ibmcam_model3_Packet1(uvd, 0x0052, 0x001a); - ibmcam_model3_Packet1(uvd, 0x0053, 0x0003); - ibmcam_model3_Packet1(uvd, 0x005a, 0x006b); - ibmcam_model3_Packet1(uvd, 0x005d, 0x001e); - ibmcam_model3_Packet1(uvd, 0x005e, 0x0030); - ibmcam_model3_Packet1(uvd, 0x005f, 0x0041); - ibmcam_model3_Packet1(uvd, 0x0064, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0065, 0x0015); - ibmcam_model3_Packet1(uvd, 0x0068, 0x000f); - ibmcam_model3_Packet1(uvd, 0x0079, 0x0000); - ibmcam_model3_Packet1(uvd, 0x007a, 0x0000); - ibmcam_model3_Packet1(uvd, 0x007c, 0x003f); - ibmcam_model3_Packet1(uvd, 0x0082, 0x000f); - ibmcam_model3_Packet1(uvd, 0x0085, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0099, 0x0000); - ibmcam_model3_Packet1(uvd, 0x009b, 0x0023); - ibmcam_model3_Packet1(uvd, 0x009c, 0x0022); - ibmcam_model3_Packet1(uvd, 0x009d, 0x0096); - ibmcam_model3_Packet1(uvd, 0x009e, 0x0096); - ibmcam_model3_Packet1(uvd, 0x009f, 0x000a); - - switch (uvd->videosize) { - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x00a9, 0x0119); - ibmcam_veio(uvd, 0, 0x0016, 0x011b); - ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - ibmcam_veio(uvd, 0, 0x0018, 0x0102); - ibmcam_veio(uvd, 0, 0x0004, 0x0104); - ibmcam_veio(uvd, 0, 0x0004, 0x011a); - ibmcam_veio(uvd, 0, 0x0028, 0x011c); - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_veio(uvd, 0, 0x0000, 0x0118); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */ - ibmcam_veio(uvd, 0, 0x0000, 0x011e); - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - /* 4 commands from 160x120 skipped */ - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - ibmcam_veio(uvd, 0, 0x00d9, 0x0119); - ibmcam_veio(uvd, 0, 0x0006, 0x011b); - ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0010, 0x0104); - ibmcam_veio(uvd, 0, 0x0004, 0x011a); - ibmcam_veio(uvd, 0, 0x003f, 0x011c); - ibmcam_veio(uvd, 0, 0x001c, 0x0118); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); - break; - case VIDEOSIZE_640x480: - ibmcam_veio(uvd, 0, 0x00f0, 0x0105); - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */ - ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */ - ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */ - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - ibmcam_veio(uvd, 0, 0x0040, 0x0101); - ibmcam_veio(uvd, 0, 0x0040, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */ - break; - } - ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); /* Hue */ - ibmcam_model3_Packet1(uvd, 0x0036, 0x0011); /* Brightness */ - ibmcam_model3_Packet1(uvd, 0x0060, 0x0002); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0061, 0x0004); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0062, 0x0005); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0063, 0x0014); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ - ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ - ibmcam_model3_Packet1(uvd, 0x0067, 0x0001); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x005b, 0x000c); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x005c, 0x0016); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); - ibmcam_model3_Packet1(uvd, 0x002c, 0x0003); /* Was 1, broke 640x480 */ - ibmcam_model3_Packet1(uvd, 0x002f, 0x002a); - ibmcam_model3_Packet1(uvd, 0x0030, 0x0029); - ibmcam_model3_Packet1(uvd, 0x0037, 0x0002); - ibmcam_model3_Packet1(uvd, 0x0038, 0x0059); - ibmcam_model3_Packet1(uvd, 0x003d, 0x002e); - ibmcam_model3_Packet1(uvd, 0x003e, 0x0028); - ibmcam_model3_Packet1(uvd, 0x0078, 0x0005); - ibmcam_model3_Packet1(uvd, 0x007b, 0x0011); - ibmcam_model3_Packet1(uvd, 0x007d, 0x004b); - ibmcam_model3_Packet1(uvd, 0x007f, 0x0022); - ibmcam_model3_Packet1(uvd, 0x0080, 0x000c); - ibmcam_model3_Packet1(uvd, 0x0081, 0x000b); - ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd); - ibmcam_model3_Packet1(uvd, 0x0086, 0x000b); - ibmcam_model3_Packet1(uvd, 0x0087, 0x000b); - ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); - ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ - ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ - ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); - - switch (uvd->videosize) { - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0002, 0x0106); - ibmcam_veio(uvd, 0, 0x0008, 0x0107); - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ - ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x000a); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x0062, 0x0107); - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ - ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000b); - break; - case VIDEOSIZE_640x480: - ibmcam_veio(uvd, 0, 0x0002, 0x0106); /* Adjustments */ - ibmcam_veio(uvd, 0, 0x00b4, 0x0107); /* Adjustments */ - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); - break; - } - - /* 01.01.08 - Added for RCA video in support -LO */ - if(init_model3_input) { - if (debug > 0) - dev_info(&uvd->dev->dev, "Setting input to RCA.\n"); - for (i=0; i < ARRAY_SIZE(initData); i++) { - ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); - } - } - - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -/* - * ibmcam_video_stop() - * - * This code tells camera to stop streaming. The interface remains - * configured and bandwidth - claimed. - */ -static void ibmcam_video_stop(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_veio(uvd, 0, 0x01, 0x0114); - ibmcam_veio(uvd, 0, 0xc0, 0x010c); - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_send_FF_04_02(uvd); - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ - break; - case IBMCAM_MODEL_2: -case IBMCAM_MODEL_4: - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop the camera */ - - ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); - - ibmcam_veio(uvd, 0, 0x0080, 0x0100); /* LED Off */ - ibmcam_veio(uvd, 0, 0x0020, 0x0111); - ibmcam_veio(uvd, 0, 0x00a0, 0x0111); - - ibmcam_model2_Packet1(uvd, 0x0030, 0x0002); - - ibmcam_veio(uvd, 0, 0x0020, 0x0111); - ibmcam_veio(uvd, 0, 0x0000, 0x0112); - break; - case IBMCAM_MODEL_3: -#if 1 - ibmcam_veio(uvd, 0, 0x0000, 0x010c); - - /* Here we are supposed to select video interface alt. setting 0 */ - ibmcam_veio(uvd, 0, 0x0006, 0x012c); - - ibmcam_model3_Packet1(uvd, 0x0046, 0x0000); - - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0064, 0x0116); - ibmcam_veio(uvd, 1, 0x0000, 0x0115); - ibmcam_veio(uvd, 0, 0x0003, 0x0115); - ibmcam_veio(uvd, 0, 0x0008, 0x0123); - ibmcam_veio(uvd, 0, 0x0000, 0x0117); - ibmcam_veio(uvd, 0, 0x0000, 0x0112); - ibmcam_veio(uvd, 0, 0x0080, 0x0100); - IBMCAM_T(uvd)->initialized = 0; -#endif - break; - } /* switch */ -} - -/* - * ibmcam_reinit_iso() - * - * This procedure sends couple of commands to the camera and then - * resets the video pipe. This sequence was observed to reinit the - * camera or, at least, to initiate ISO data stream. - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - if (do_stop) - ibmcam_video_stop(uvd); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_model1_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_2: - ibmcam_model2_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_3: - ibmcam_video_stop(uvd); - ibmcam_model3_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_4: - ibmcam_model4_setup_after_video_if(uvd); - break; - } -} - -static void ibmcam_video_start(struct uvd *uvd) -{ - ibmcam_change_lighting_conditions(uvd); - ibmcam_set_sharpness(uvd); - ibmcam_reinit_iso(uvd, 0); -} - -/* - * Return negative code on failure, 0 on success. - */ -static int ibmcam_setup_on_open(struct uvd *uvd) -{ - int setup_ok = 0; /* Success by default */ - /* Send init sequence only once, it's large! */ - if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - setup_ok = ibmcam_model1_setup(uvd); - break; - case IBMCAM_MODEL_2: - setup_ok = ibmcam_model2_setup(uvd); - break; - case IBMCAM_MODEL_3: - case IBMCAM_MODEL_4: - /* We do all setup when Isoc stream is requested */ - break; - } - IBMCAM_T(uvd)->initialized = (setup_ok != 0); - } - return setup_ok; -} - -static void ibmcam_configure_video(struct uvd *uvd) -{ - if (uvd == NULL) - return; - - RESTRICT_TO_RANGE(init_brightness, 0, 255); - RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - uvd->vpic.colour = init_color << 8; - uvd->vpic.hue = init_hue << 8; - uvd->vpic.brightness = init_brightness << 8; - uvd->vpic.contrast = init_contrast << 8; - uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ - uvd->vpic.depth = 24; - uvd->vpic.palette = VIDEO_PALETTE_RGB24; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM USB Camera"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); - uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); - uvd->vcap.minwidth = min_canvasWidth; - uvd->vcap.minheight = min_canvasHeight; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); -} - -/* - * ibmcam_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like IBM C-it camera. - * - * History: - * 22-Jan-2000 Moved camera init code to ibmcam_open() - * 27=Jan-2000 Changed to use static structures, added locking. - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - * 03-Jul-2000 Fixed endianness bug. - * 12-Nov-2000 Reworked to comply with new probe() signature. - * 23-Jan-2001 Added compatibility with 2.2.x kernels. - */ -static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas, model=0, canvasX=0, canvasY=0; - int actInterface=-1, inactInterface=-1, maxPS=0; - __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; - unsigned char video_ep = 0; - - if (debug >= 1) - dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - /* Check the version/revision */ - switch (le16_to_cpu(dev->descriptor.bcdDevice)) { - case 0x0002: - if (ifnum != 2) - return -ENODEV; - model = IBMCAM_MODEL_1; - break; - case 0x030A: - if (ifnum != 0) - return -ENODEV; - if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) || - (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID)) - model = IBMCAM_MODEL_4; - else - model = IBMCAM_MODEL_2; - break; - case 0x0301: - if (ifnum != 0) - return -ENODEV; - model = IBMCAM_MODEL_3; - break; - default: - err("IBM camera with revision 0x%04x is not supported.", - le16_to_cpu(dev->descriptor.bcdDevice)); - return -ENODEV; - } - - /* Print detailed info on what we found so far */ - do { - char *brand = NULL; - switch (le16_to_cpu(dev->descriptor.idProduct)) { - case NETCAM_PRODUCT_ID: - brand = "IBM NetCamera"; - break; - case VEO_800C_PRODUCT_ID: - brand = "Veo Stingray [800C]"; - break; - case VEO_800D_PRODUCT_ID: - brand = "Veo Stingray [800D]"; - break; - case IBMCAM_PRODUCT_ID: - default: - brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ - break; - } - dev_info(&dev->dev, - "%s USB camera found (model %d, rev. 0x%04x)\n", - brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); - } while (0); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (debug > 0) - dev_info(&dev->dev, "Number of alternate settings=%d.\n", - nas); - if (nas < 2) { - err("Too few alternate settings for this camera!"); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 1) { - err("Interface %d. has %u. endpoints!", - ifnum, (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[0].desc; - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if (!usb_endpoint_xfer_isoc(endpoint)) { - err("Interface %d. has non-ISO endpoint!", ifnum); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - err("Interface %d. has ISO OUT endpoint!", ifnum); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (actInterface < 0) { - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) - dev_info(&dev->dev, - "Active setting=%d. " - "maxPS=%d.\n", i, maxPS); - } else - err("More than one active alt. setting! Ignoring #%d.", i); - } - } - if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { - err("Failed to recognize the camera!"); - return -ENODEV; - } - - /* Validate options */ - switch (model) { - case IBMCAM_MODEL_1: - RESTRICT_TO_RANGE(lighting, 0, 2); - RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288); - if (framerate < 0) - framerate = 2; - canvasX = 352; - canvasY = 288; - break; - case IBMCAM_MODEL_2: - RESTRICT_TO_RANGE(lighting, 0, 15); - RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240); - if (framerate < 0) - framerate = 2; - canvasX = 352; - canvasY = 240; - break; - case IBMCAM_MODEL_3: - RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */ - switch (size) { - case SIZE_160x120: - canvasX = 160; - canvasY = 120; - if (framerate < 0) - framerate = 2; - RESTRICT_TO_RANGE(framerate, 0, 5); - break; - default: - dev_info(&dev->dev, "IBM camera: using 320x240\n"); - size = SIZE_320x240; - /* No break here */ - case SIZE_320x240: - canvasX = 320; - canvasY = 240; - if (framerate < 0) - framerate = 3; - RESTRICT_TO_RANGE(framerate, 0, 5); - break; - case SIZE_640x480: - canvasX = 640; - canvasY = 480; - framerate = 0; /* Slowest, and maybe even that is too fast */ - break; - } - break; - case IBMCAM_MODEL_4: - RESTRICT_TO_RANGE(lighting, 0, 2); - switch (size) { - case SIZE_128x96: - canvasX = 128; - canvasY = 96; - break; - case SIZE_160x120: - canvasX = 160; - canvasY = 120; - break; - default: - dev_info(&dev->dev, "IBM NetCamera: using 176x144\n"); - size = SIZE_176x144; - /* No break here */ - case SIZE_176x144: - canvasX = 176; - canvasY = 144; - break; - case SIZE_320x240: - canvasX = 320; - canvasY = 240; - break; - case SIZE_352x288: - canvasX = 352; - canvasY = 288; - break; - } - break; - default: - err("IBM camera: Model %d. not supported!", model); - return -ENODEV; - } - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ - uvd->flags = flags; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = ifnum; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; - uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(canvasX, canvasY); - uvd->videosize = ibmcam_size_to_videosize(size); - - /* Initialize ibmcam-specific data */ - assert(IBMCAM_T(uvd) != NULL); - IBMCAM_T(uvd)->camera_model = model; - IBMCAM_T(uvd)->initialized = 0; - - ibmcam_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - } - usb_set_intfdata (intf, uvd); - return 0; -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { } /* Terminating entry */ -}; - -/* - * ibmcam_init() - * - * This code is run to initialize the driver. - * - * History: - * 1/27/00 Reworked to use statically allocated ibmcam structures. - * 21/10/00 Completely redesigned to use usbvideo services. - */ -static int __init ibmcam_init(void) -{ - struct usbvideo_cb cbTbl; - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = ibmcam_probe; - cbTbl.setupOnOpen = ibmcam_setup_on_open; - cbTbl.videoStart = ibmcam_video_start; - cbTbl.videoStop = ibmcam_video_stop; - cbTbl.processData = ibmcam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; - cbTbl.adjustPicture = ibmcam_adjust_picture; - cbTbl.getFPS = ibmcam_calculate_fps; - return usbvideo_register( - &cams, - MAX_IBMCAM, - sizeof(ibmcam_t), - "ibmcam", - &cbTbl, - THIS_MODULE, - id_table); -} - -static void __exit ibmcam_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - -MODULE_DEVICE_TABLE(usb, id_table); - -module_init(ibmcam_init); -module_exit(ibmcam_cleanup); diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c deleted file mode 100644 index 562e1d170be..00000000000 --- a/drivers/media/video/usbvideo/konicawc.c +++ /dev/null @@ -1,992 +0,0 @@ -/* - * konicawc.c - konica webcam driver - * - * Author: Simon Evans <spse@secret.org.uk> - * - * Copyright (C) 2002 Simon Evans - * - * Licence: GPL - * - * Driver for USB webcams based on Konica chipset. This - * chipset is used in Intel YC76 camera. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> -#include <linux/gfp.h> - -#include "usbvideo.h" - -#define MAX_BRIGHTNESS 108 -#define MAX_CONTRAST 108 -#define MAX_SATURATION 108 -#define MAX_SHARPNESS 108 -#define MAX_WHITEBAL 372 -#define MAX_SPEED 6 - - -#define MAX_CAMERAS 1 - -#define DRIVER_VERSION "v1.4" -#define DRIVER_DESC "Konica Webcam driver" - -enum ctrl_req { - SetWhitebal = 0x01, - SetBrightness = 0x02, - SetSharpness = 0x03, - SetContrast = 0x04, - SetSaturation = 0x05, -}; - - -enum frame_sizes { - SIZE_160X120 = 0, - SIZE_160X136 = 1, - SIZE_176X144 = 2, - SIZE_320X240 = 3, - -}; - -#define MAX_FRAME_SIZE SIZE_320X240 - -static struct usbvideo *cams; - -#ifdef CONFIG_USB_DEBUG -static int debug; -#define DEBUG(n, format, arg...) \ - if (n <= debug) { \ - printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ - } -#else -#define DEBUG(n, arg...) -static const int debug; -#endif - - -/* Some default values for initial camera settings, - can be set by modprobe */ - -static int size; -static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ -static int brightness = MAX_BRIGHTNESS/2; -static int contrast = MAX_CONTRAST/2; -static int saturation = MAX_SATURATION/2; -static int sharpness = MAX_SHARPNESS/2; -static int whitebal = 3*(MAX_WHITEBAL/4); - -static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; - -/* These FPS speeds are from the windows config box. They are - * indexed on size (0-2) and speed (0-6). Divide by 3 to get the - * real fps. - */ - -static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, - { 24, 40, 48, 60, 72, 80, 100 }, - { 18, 30, 36, 45, 54, 60, 75 }, - { 6, 10, 12, 15, 18, 21, 25 } }; - -struct cam_size { - u16 width; - u16 height; - u8 cmd; -}; - -static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, - { 160, 136, 0xa }, - { 176, 144, 0x4 }, - { 320, 240, 0x5 } }; - -struct konicawc { - u8 brightness; /* camera uses 0 - 9, x11 for real value */ - u8 contrast; /* as above */ - u8 saturation; /* as above */ - u8 sharpness; /* as above */ - u8 white_bal; /* 0 - 33, x11 for real value */ - u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */ - u8 size; /* Frame Size */ - int height; - int width; - struct urb *sts_urb[USBVIDEO_NUMSBUF]; - u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC]; - struct urb *last_data_urb; - int lastframe; - int cur_frame_size; /* number of bytes in current frame size */ - int maxline; /* number of lines per frame */ - int yplanesz; /* Number of bytes in the Y plane */ - unsigned int buttonsts:1; -#ifdef CONFIG_INPUT - struct input_dev *input; - char input_physname[64]; -#endif -}; - - -#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0) -#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz) -#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0) - - -static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) -{ - int retval = usb_control_msg(uvd->dev, - dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), - request, 0x40 | dir, value, index, buf, len, 1000); - return retval < 0 ? retval : 0; -} - - -static inline void konicawc_camera_on(struct uvd *uvd) -{ - DEBUG(0, "camera on"); - konicawc_set_misc(uvd, 0x2, 1, 0x0b); -} - - -static inline void konicawc_camera_off(struct uvd *uvd) -{ - DEBUG(0, "camera off"); - konicawc_set_misc(uvd, 0x2, 0, 0x0b); -} - - -static void konicawc_set_camera_size(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08); - cam->width = camera_sizes[cam->size].width; - cam->height = camera_sizes[cam->size].height; - cam->yplanesz = cam->height * cam->width; - cam->cur_frame_size = (cam->yplanesz * 3) / 2; - cam->maxline = cam->yplanesz / 256; - uvd->videosize = VIDEOSIZE(cam->width, cam->height); -} - - -static int konicawc_setup_on_open(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - DEBUG(1, "setting brightness to %d (%d)", cam->brightness, - cam->brightness * 11); - konicawc_set_value(uvd, cam->brightness, SetBrightness); - DEBUG(1, "setting white balance to %d (%d)", cam->white_bal, - cam->white_bal * 11); - konicawc_set_value(uvd, cam->white_bal, SetWhitebal); - DEBUG(1, "setting contrast to %d (%d)", cam->contrast, - cam->contrast * 11); - konicawc_set_value(uvd, cam->contrast, SetContrast); - DEBUG(1, "setting saturation to %d (%d)", cam->saturation, - cam->saturation * 11); - konicawc_set_value(uvd, cam->saturation, SetSaturation); - DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness, - cam->sharpness * 11); - konicawc_set_value(uvd, cam->sharpness, SetSharpness); - konicawc_set_camera_size(uvd); - cam->lastframe = -2; - cam->buttonsts = 0; - return 0; -} - - -static void konicawc_adjust_picture(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_camera_off(uvd); - DEBUG(1, "new brightness: %d", uvd->vpic.brightness); - uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness; - if(cam->brightness != uvd->vpic.brightness / 11) { - cam->brightness = uvd->vpic.brightness / 11; - DEBUG(1, "setting brightness to %d (%d)", cam->brightness, - cam->brightness * 11); - konicawc_set_value(uvd, cam->brightness, SetBrightness); - } - - DEBUG(1, "new contrast: %d", uvd->vpic.contrast); - uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast; - if(cam->contrast != uvd->vpic.contrast / 11) { - cam->contrast = uvd->vpic.contrast / 11; - DEBUG(1, "setting contrast to %d (%d)", cam->contrast, - cam->contrast * 11); - konicawc_set_value(uvd, cam->contrast, SetContrast); - } - konicawc_camera_on(uvd); -} - -#ifdef CONFIG_INPUT - -static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) -{ - struct input_dev *input_dev; - int error; - - usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); - strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); - - cam->input = input_dev = input_allocate_device(); - if (!input_dev) { - dev_warn(&dev->dev, - "Not enough memory for camera's input device\n"); - return; - } - - input_dev->name = "Konicawc snapshot button"; - input_dev->phys = cam->input_physname; - usb_to_input_id(dev, &input_dev->id); - input_dev->dev.parent = &dev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY); - input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); - - error = input_register_device(cam->input); - if (error) { - dev_warn(&dev->dev, - "Failed to register camera's input device, err: %d\n", - error); - input_free_device(cam->input); - cam->input = NULL; - } -} - -static void konicawc_unregister_input(struct konicawc *cam) -{ - if (cam->input) { - input_unregister_device(cam->input); - cam->input = NULL; - } -} - -static void konicawc_report_buttonstat(struct konicawc *cam) -{ - if (cam->input) { - input_report_key(cam->input, KEY_CAMERA, cam->buttonsts); - input_sync(cam->input); - } -} - -#else - -static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { } -static inline void konicawc_unregister_input(struct konicawc *cam) { } -static inline void konicawc_report_buttonstat(struct konicawc *cam) { } - -#endif /* CONFIG_INPUT */ - -static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb) -{ - char *cdata; - int i, totlen = 0; - unsigned char *status = stsurb->transfer_buffer; - int keep = 0, discard = 0, bad = 0; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - for (i = 0; i < dataurb->number_of_packets; i++) { - int button = cam->buttonsts; - unsigned char sts; - int n = dataurb->iso_frame_desc[i].actual_length; - int st = dataurb->iso_frame_desc[i].status; - cdata = dataurb->transfer_buffer + - dataurb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (st < 0) { - DEBUG(1, "Data error: packet=%d. len=%d. status=%d.", - i, n, st); - uvd->stats.iso_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (n <= 0) { - uvd->stats.iso_skip_count++; - continue; - } - - /* See what the status data said about the packet */ - sts = *(status+stsurb->iso_frame_desc[i].offset); - - /* sts: 0x80-0xff: frame start with frame number (ie 0-7f) - * otherwise: - * bit 0 0: keep packet - * 1: drop packet (padding data) - * - * bit 4 0 button not clicked - * 1 button clicked - * button is used to `take a picture' (in software) - */ - - if(sts < 0x80) { - button = !!(sts & 0x40); - sts &= ~0x40; - } - - /* work out the button status, but don't do - anything with it for now */ - - if(button != cam->buttonsts) { - DEBUG(2, "button: %sclicked", button ? "" : "un"); - cam->buttonsts = button; - konicawc_report_buttonstat(cam); - } - - if(sts == 0x01) { /* drop frame */ - discard++; - continue; - } - - if((sts > 0x01) && (sts < 0x80)) { - dev_info(&uvd->dev->dev, "unknown status %2.2x\n", - sts); - bad++; - continue; - } - if(!sts && cam->lastframe == -2) { - DEBUG(2, "dropping frame looking for image start"); - continue; - } - - keep++; - if(sts & 0x80) { /* frame start */ - unsigned char marker[] = { 0, 0xff, 0, 0x00 }; - - if(cam->lastframe == -2) { - DEBUG(2, "found initial image"); - cam->lastframe = -1; - } - - marker[3] = sts & 0x7F; - RingQueue_Enqueue(&uvd->dp, marker, 4); - totlen += 4; - } - - totlen += n; /* Little local accounting */ - RingQueue_Enqueue(&uvd->dp, cdata, n); - } - DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes", - keep, discard, bad, totlen); - return totlen; -} - - -static void resubmit_urb(struct uvd *uvd, struct urb *urb) -{ - int i, ret; - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - } - urb->dev = uvd->dev; - urb->status = 0; - ret = usb_submit_urb(urb, GFP_ATOMIC); - DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length); - if(ret) - err("usb_submit_urb error (%d)", ret); - -} - - -static void konicawc_isoc_irq(struct urb *urb) -{ - struct uvd *uvd = urb->context; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - /* We don't want to do anything if we are about to be removed! */ - if (!CAMERA_IS_OPERATIONAL(uvd)) - return; - - if (!uvd->streaming) { - DEBUG(1, "Not streaming, but interrupt!"); - return; - } - - DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length); - - uvd->stats.urb_count++; - - if (urb->transfer_buffer_length > 32) { - cam->last_data_urb = urb; - return; - } - /* Copy the data received into ring queue */ - if(cam->last_data_urb) { - int len = 0; - if(urb->start_frame != cam->last_data_urb->start_frame) - err("Lost sync on frames"); - else if (!urb->status && !cam->last_data_urb->status) - len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); - - resubmit_urb(uvd, cam->last_data_urb); - resubmit_urb(uvd, urb); - cam->last_data_urb = NULL; - uvd->stats.urb_length = len; - uvd->stats.data_count += len; - if(len) - RingQueue_WakeUpInterruptible(&uvd->dp); - return; - } - return; -} - - -static int konicawc_start_data(struct uvd *uvd) -{ - struct usb_device *dev = uvd->dev; - int i, errFlag; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int pktsz; - struct usb_interface *intf; - struct usb_host_interface *interface = NULL; - - intf = usb_ifnum_to_if(dev, uvd->iface); - if (intf) - interface = usb_altnum_to_altsetting(intf, - spd_to_iface[cam->speed]); - if (!interface) - return -ENXIO; - pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize); - DEBUG(1, "pktsz = %d", pktsz); - if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("Camera is not operational"); - return -EFAULT; - } - uvd->curframe = -1; - konicawc_camera_on(uvd); - /* Alternate interface 1 is is the biggest frame size */ - i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); - if (i < 0) { - err("usb_set_interface error"); - uvd->last_error = i; - return -EBUSY; - } - - /* We double buffer the Iso lists */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - int j, k; - struct urb *urb = uvd->sbuf[i].urb; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = uvd->sbuf[i].data; - urb->complete = konicawc_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; - for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = pktsz; - } - - urb = cam->sts_urb[i]; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = cam->sts_buf[i]; - urb->complete = konicawc_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAMES_PER_DESC; - for (j=0; j < FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j; - urb->iso_frame_desc[j].length = 1; - } - } - - cam->last_data_urb = NULL; - - /* Submit all URBs */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL); - if (errFlag) - err("usb_submit_isoc(%d) ret %d", i, errFlag); - - errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); - if (errFlag) - err ("usb_submit_isoc(%d) ret %d", i, errFlag); - } - - uvd->streaming = 1; - DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp); - return 0; -} - - -static void konicawc_stop_data(struct uvd *uvd) -{ - int i, j; - struct konicawc *cam; - - if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) - return; - - konicawc_camera_off(uvd); - uvd->streaming = 0; - cam = (struct konicawc *)uvd->user_data; - cam->last_data_urb = NULL; - - /* Unschedule all of the iso td's */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - usb_kill_urb(uvd->sbuf[i].urb); - usb_kill_urb(cam->sts_urb[i]); - } - - if (!uvd->remove_pending) { - /* Set packet size to 0 */ - j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); - if (j < 0) { - err("usb_set_interface() error %d.", j); - uvd->last_error = j; - } - } -} - - -static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int maxline = cam->maxline; - int yplanesz = cam->yplanesz; - - assert(frame != NULL); - - DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz); - DEBUG(3, "Frame state = %d", frame->scanstate); - - if(frame->scanstate == ScanState_Scanning) { - int drop = 0; - int curframe; - int fdrops = 0; - DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); - while(RingQueue_GetLength(&uvd->dp) >= 4) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && - (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { - curframe = RING_QUEUE_PEEK(&uvd->dp, 3); - if(cam->lastframe >= 0) { - fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; - fdrops--; - if(fdrops) { - dev_info(&uvd->dev->dev, - "Dropped %d frames " - "(%d -> %d)\n", - fdrops, - cam->lastframe, - curframe); - } - } - cam->lastframe = curframe; - frame->curline = 0; - frame->scanstate = ScanState_Lines; - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); - break; - } - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - drop++; - } - if(drop) - DEBUG(2, "dropped %d bytes looking for new frame", drop); - } - - if(frame->scanstate == ScanState_Scanning) - return; - - /* Try to move data from queue into frame buffer - * We get data in blocks of 384 bytes made up of: - * 256 Y, 64 U, 64 V. - * This needs to be written out as a Y plane, a U plane and a V plane. - */ - - while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { - /* Y */ - RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); - /* U */ - RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); - /* V */ - RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); - frame->seqRead_Length += 384; - frame->curline++; - } - /* See if we filled the frame */ - if (frame->curline == maxline) { - DEBUG(5, "got whole frame"); - - frame->frameState = FrameState_Done_Hold; - frame->curline = 0; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - - -static int konicawc_find_fps(int size, int fps) -{ - int i; - - fps *= 3; - DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps); - if(fps <= spd_to_fps[size][0]) - return 0; - - if(fps >= spd_to_fps[size][MAX_SPEED]) - return MAX_SPEED; - - for(i = 0; i < MAX_SPEED; i++) { - if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { - DEBUG(2, "fps %d between %d and %d", fps, i, i+1); - if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) - return i; - else - return i+1; - } - } - return MAX_SPEED+1; -} - - -static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int newspeed = cam->speed; - int newsize; - int x = vw->width; - int y = vw->height; - int fps = vw->flags; - - if(x > 0 && y > 0) { - DEBUG(2, "trying to find size %d,%d", x, y); - for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { - if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) - break; - } - } else { - newsize = cam->size; - } - - if(newsize > MAX_FRAME_SIZE) { - DEBUG(1, "couldn't find size %d,%d", x, y); - return -EINVAL; - } - - if(fps > 0) { - DEBUG(1, "trying to set fps to %d", fps); - newspeed = konicawc_find_fps(newsize, fps); - DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); - } - - if(newspeed > MAX_SPEED) - return -EINVAL; - - DEBUG(1, "setting size to %d speed to %d", newsize, newspeed); - if((newsize == cam->size) && (newspeed == cam->speed)) { - DEBUG(1, "Nothing to do"); - return 0; - } - DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width, - camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); - - konicawc_stop_data(uvd); - uvd->ifaceAltActive = spd_to_iface[newspeed]; - DEBUG(1, "new interface = %d", uvd->ifaceAltActive); - cam->speed = newspeed; - - if(cam->size != newsize) { - cam->size = newsize; - konicawc_set_camera_size(uvd); - } - - /* Flush the input queue and clear any current frame in progress */ - - RingQueue_Flush(&uvd->dp); - cam->lastframe = -2; - if(uvd->curframe != -1) { - uvd->frame[uvd->curframe].curline = 0; - uvd->frame[uvd->curframe].seqRead_Length = 0; - uvd->frame[uvd->curframe].seqRead_Index = 0; - } - - konicawc_start_data(uvd); - return 0; -} - - -static int konicawc_calculate_fps(struct uvd *uvd) -{ - struct konicawc *cam = uvd->user_data; - return spd_to_fps[cam->size][cam->speed]/3; -} - - -static void konicawc_configure_video(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - u8 buf[2]; - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); - RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); - RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); - RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); - RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); - - cam->brightness = brightness / 11; - cam->contrast = contrast / 11; - cam->saturation = saturation / 11; - cam->sharpness = sharpness / 11; - cam->white_bal = whitebal / 11; - - uvd->vpic.colour = 108; - uvd->vpic.hue = 108; - uvd->vpic.brightness = brightness; - uvd->vpic.contrast = contrast; - uvd->vpic.whiteness = whitebal; - uvd->vpic.depth = 6; - uvd->vpic.palette = VIDEO_PALETTE_YUV420P; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "Konica Webcam"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; - uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; - uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; - uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0 ; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); - - /* Talk to device */ - DEBUG(1, "device init"); - if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) - DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); - if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) - DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); - if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) - DEBUG(2, "2,0,d failed"); - DEBUG(1, "setting initial values"); -} - -static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas; - int actInterface=-1, inactInterface=-1, maxPS=0; - unsigned char video_ep = 0; - - DEBUG(1, "konicawc_probe(%p)", intf); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n", - le16_to_cpu(dev->descriptor.bcdDevice)); - RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (nas != 8) { - err("Incorrect number of alternate settings (%d) for this camera!", nas); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 2) { - err("Interface %d. has %u. endpoints!", - interface->desc.bInterfaceNumber, - (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[1].desc; - DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", - endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize)); - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if (!usb_endpoint_xfer_isoc(endpoint)) { - err("Interface %d. has non-ISO endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - err("Interface %d. has ISO OUT endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (i == spd_to_iface[speed]) { - /* This one is the requested one */ - actInterface = i; - } - } - if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS) - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - } - if(actInterface == -1) { - err("Cant find required endpoint"); - return -ENODEV; - } - - DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - struct konicawc *cam = (struct konicawc *)(uvd->user_data); - /* Here uvd is a fully allocated uvd object */ - for(i = 0; i < USBVIDEO_NUMSBUF; i++) { - cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if(cam->sts_urb[i] == NULL) { - while(i--) { - usb_free_urb(cam->sts_urb[i]); - } - err("can't allocate urbs"); - return -ENOMEM; - } - } - cam->speed = speed; - RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); - cam->width = camera_sizes[size].width; - cam->height = camera_sizes[size].height; - cam->size = size; - - uvd->flags = 0; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = intf->altsetting->desc.bInterfaceNumber; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; - uvd->defaultPalette = VIDEO_PALETTE_YUV420P; - uvd->canvas = VIDEOSIZE(320, 240); - uvd->videosize = VIDEOSIZE(cam->width, cam->height); - - /* Initialize konicawc specific data */ - konicawc_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - uvd->max_frame_size = (320 * 240 * 3)/2; - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - - konicawc_register_input(cam, dev); - } - - if (uvd) { - usb_set_intfdata (intf, uvd); - return 0; - } - return -EIO; -} - - -static void konicawc_free_uvd(struct uvd *uvd) -{ - int i; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_unregister_input(cam); - - for (i = 0; i < USBVIDEO_NUMSBUF; i++) { - usb_free_urb(cam->sts_urb[i]); - cam->sts_urb[i] = NULL; - } -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ - { } /* Terminating entry */ -}; - - -static int __init konicawc_init(void) -{ - struct usbvideo_cb cbTbl; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = konicawc_probe; - cbTbl.setupOnOpen = konicawc_setup_on_open; - cbTbl.processData = konicawc_process_isoc; - cbTbl.getFPS = konicawc_calculate_fps; - cbTbl.setVideoMode = konicawc_set_video_mode; - cbTbl.startDataPump = konicawc_start_data; - cbTbl.stopDataPump = konicawc_stop_data; - cbTbl.adjustPicture = konicawc_adjust_picture; - cbTbl.userFree = konicawc_free_uvd; - return usbvideo_register( - &cams, - MAX_CAMERAS, - sizeof(struct konicawc), - "konicawc", - &cbTbl, - THIS_MODULE, - id_table); -} - - -static void __exit konicawc_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - - -MODULE_DEVICE_TABLE(usb, id_table); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>"); -MODULE_DESCRIPTION(DRIVER_DESC); -module_param(speed, int, 0); -MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); -module_param(size, int, 0); -MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); -module_param(brightness, int, 0); -MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); -module_param(contrast, int, 0); -MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); -module_param(saturation, int, 0); -MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); -module_param(sharpness, int, 0); -MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108"); -module_param(whitebal, int, 0); -MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); - -#ifdef CONFIG_USB_DEBUG -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -#endif - -module_init(konicawc_init); -module_exit(konicawc_cleanup); diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c deleted file mode 100644 index fbd1b639229..00000000000 --- a/drivers/media/video/usbvideo/ultracam.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * USB NB Camera driver - * - * HISTORY: - * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> - -#include "usbvideo.h" - -#define ULTRACAM_VENDOR_ID 0x0461 -#define ULTRACAM_PRODUCT_ID 0x0813 - -#define MAX_CAMERAS 4 /* How many devices we allow to connect */ - -/* - * This structure lives in uvd_t->user field. - */ -typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; -} ultracam_t; -#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) - -static struct usbvideo *cams = NULL; - -static int debug; - -static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ - -static const int min_canvasWidth = 8; -static const int min_canvasHeight = 4; - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; - -/* - * Here we define several initialization variables. They may - * be used to automatically set color, hue, brightness and - * contrast to desired values. This is particularly useful in - * case of webcams (which have no controls and no on-screen - * output) and also when a client V4L software is used that - * does not have some of those controls. In any case it's - * good to have startup values as options. - * - * These values are all in [0..255] range. This simplifies - * operation. Note that actual values of V4L variables may - * be scaled up (as much as << 8). User can see that only - * on overlay output, however, or through a V4L client. - */ -static int init_brightness = 128; -static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; - -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -module_param(flags, int, 0); -MODULE_PARM_DESC(flags, - "Bitfield: 0=VIDIOCSYNC, " - "1=B/W, " - "2=show hints, " - "3=show stats, " - "4=test pattern, " - "5=separate frames, " - "6=clean frames"); -module_param(framerate, int, 0); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); - -module_param(init_brightness, int, 0); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -module_param(init_contrast, int, 0); -MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -module_param(init_color, int, 0); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -module_param(init_hue, int, 0); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -module_param(hue_correction, int, 0); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); - -/* - * ultracam_ProcessIsocData() - * - * Generic routine to parse the ring queue data. It employs either - * ultracam_find_header() or ultracam_parse_lines() to do most - * of work. - * - * 02-Nov-2000 First (mostly dummy) version. - * 06-Nov-2000 Rewrote to dump all data into frame. - */ -static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) -{ - int n; - - assert(uvd != NULL); - assert(frame != NULL); - - /* Try to move data from queue into frame buffer */ - n = RingQueue_GetLength(&uvd->dp); - if (n > 0) { - int m; - /* See how much spare we have left */ - m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; - /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; - } - /* See if we filled the frame */ - if (frame->seqRead_Length >= uvd->max_frame_size) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - -/* - * ultracam_veio() - * - * History: - * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. - */ -static int ultracam_veio( - struct uvd *uvd, - unsigned char req, - unsigned short value, - unsigned short index, - int is_out) -{ - static const char proc[] = "ultracam_veio"; - unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; - int i; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return 0; - - if (!is_out) { - i = usb_control_msg( - uvd->dev, - usb_rcvctrlpipe(uvd->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - cp, - sizeof(cp), - 1000); -#if 1 - dev_info(&uvd->dev->dev, - "USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)\n", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); -#endif - } else { - i = usb_control_msg( - uvd->dev, - usb_sndctrlpipe(uvd->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - NULL, - 0, - 1000); - } - if (i < 0) { - err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", - proc, i); - uvd->last_error = i; - } - return i; -} - -/* - * ultracam_calculate_fps() - */ -static int ultracam_calculate_fps(struct uvd *uvd) -{ - return 3 + framerate*4 + framerate/2; -} - -/* - * ultracam_adjust_contrast() - */ -static void ultracam_adjust_contrast(struct uvd *uvd) -{ -} - -/* - * ultracam_set_brightness() - * - * This procedure changes brightness of the picture. - */ -static void ultracam_set_brightness(struct uvd *uvd) -{ -} - -static void ultracam_set_hue(struct uvd *uvd) -{ -} - -/* - * ultracam_adjust_picture() - * - * This procedure gets called from V4L interface to update picture settings. - * Here we change brightness and contrast. - */ -static void ultracam_adjust_picture(struct uvd *uvd) -{ - ultracam_adjust_contrast(uvd); - ultracam_set_brightness(uvd); - ultracam_set_hue(uvd); -} - -/* - * ultracam_video_stop() - * - * This code tells camera to stop streaming. The interface remains - * configured and bandwidth - claimed. - */ -static void ultracam_video_stop(struct uvd *uvd) -{ -} - -/* - * ultracam_reinit_iso() - * - * This procedure sends couple of commands to the camera and then - * resets the video pipe. This sequence was observed to reinit the - * camera or, at least, to initiate ISO data stream. - */ -static void ultracam_reinit_iso(struct uvd *uvd, int do_stop) -{ -} - -static void ultracam_video_start(struct uvd *uvd) -{ - ultracam_reinit_iso(uvd, 0); -} - -static int ultracam_resetPipe(struct uvd *uvd) -{ - usb_clear_halt(uvd->dev, uvd->video_endp); - return 0; -} - -static int ultracam_alternateSetting(struct uvd *uvd, int setting) -{ - static const char proc[] = "ultracam_alternateSetting"; - int i; - i = usb_set_interface(uvd->dev, uvd->iface, setting); - if (i < 0) { - err("%s: usb_set_interface error", proc); - uvd->last_error = i; - return -EBUSY; - } - return 0; -} - -/* - * Return negative code on failure, 0 on success. - */ -static int ultracam_setup_on_open(struct uvd *uvd) -{ - int setup_ok = 0; /* Success by default */ - /* Send init sequence only once, it's large! */ - if (!ULTRACAM_T(uvd)->initialized) { - ultracam_alternateSetting(uvd, 0x04); - ultracam_alternateSetting(uvd, 0x00); - ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1); - ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1); - ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1); - ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1); - ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1); - ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1); - ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1); - ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1); - ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1); - ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1); - ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1); - ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1); - ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1); - ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1); - ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1); - ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1); - ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1); - ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1); - ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1); - ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1); - ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1); - ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0); - ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1); - ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_alternateSetting(uvd, 0x04); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1); - ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0); - ultracam_resetPipe(uvd); - ULTRACAM_T(uvd)->initialized = (setup_ok != 0); - } - return setup_ok; -} - -static void ultracam_configure_video(struct uvd *uvd) -{ - if (uvd == NULL) - return; - - RESTRICT_TO_RANGE(init_brightness, 0, 255); - RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - uvd->vpic.colour = init_color << 8; - uvd->vpic.hue = init_hue << 8; - uvd->vpic.brightness = init_brightness << 8; - uvd->vpic.contrast = init_contrast << 8; - uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ - uvd->vpic.depth = 24; - uvd->vpic.palette = VIDEO_PALETTE_RGB24; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM Ultra Camera"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); - uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); - uvd->vcap.minwidth = min_canvasWidth; - uvd->vcap.minheight = min_canvasHeight; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); -} - -/* - * ultracam_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like our camera. - * - * History: - * 12-Nov-2000 Reworked to comply with new probe() signature. - * 23-Jan-2001 Added compatibility with 2.2.x kernels. - */ -static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas; - int actInterface=-1, inactInterface=-1, maxPS=0; - unsigned char video_ep = 0; - - if (debug >= 1) - dev_info(&intf->dev, "ultracam_probe\n"); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n", - le16_to_cpu(dev->descriptor.bcdDevice)); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (debug > 0) - dev_info(&intf->dev, "Number of alternate settings=%d.\n", - nas); - if (nas < 8) { - err("Too few alternate settings for this camera!"); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 1) { - err("Interface %d. has %u. endpoints!", - interface->desc.bInterfaceNumber, - (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[0].desc; - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if (!usb_endpoint_xfer_isoc(endpoint)) { - err("Interface %d. has non-ISO endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - err("Interface %d. has ISO OUT endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (actInterface < 0) { - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) - dev_info(&intf->dev, - "Active setting=%d. " - "maxPS=%d.\n", i, maxPS); - } else { - /* Got another active alt. setting */ - if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { - /* This one is better! */ - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) { - dev_info(&intf->dev, - "Even better ctive " - "setting=%d. " - "maxPS=%d.\n", - i, maxPS); - } - } - } - } - } - if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { - err("Failed to recognize the camera!"); - return -ENODEV; - } - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ - uvd->flags = flags; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = intf->altsetting->desc.bInterfaceNumber; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; - uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */ - uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/ - - /* Initialize ibmcam-specific data */ - assert(ULTRACAM_T(uvd) != NULL); - ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */ - ULTRACAM_T(uvd)->initialized = 0; - - ultracam_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - } - - if (uvd) { - usb_set_intfdata (intf, uvd); - return 0; - } - return -EIO; -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -/* - * ultracam_init() - * - * This code is run to initialize the driver. - */ -static int __init ultracam_init(void) -{ - struct usbvideo_cb cbTbl; - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = ultracam_probe; - cbTbl.setupOnOpen = ultracam_setup_on_open; - cbTbl.videoStart = ultracam_video_start; - cbTbl.videoStop = ultracam_video_stop; - cbTbl.processData = ultracam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; - cbTbl.adjustPicture = ultracam_adjust_picture; - cbTbl.getFPS = ultracam_calculate_fps; - return usbvideo_register( - &cams, - MAX_CAMERAS, - sizeof(ultracam_t), - "ultracam", - &cbTbl, - THIS_MODULE, - id_table); -} - -static void __exit ultracam_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - -MODULE_DEVICE_TABLE(usb, id_table); -MODULE_LICENSE("GPL"); - -module_init(ultracam_init); -module_exit(ultracam_cleanup); diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c deleted file mode 100644 index f1fcf974496..00000000000 --- a/drivers/media/video/usbvideo/usbvideo.c +++ /dev/null @@ -1,2230 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/init.h> -#include <linux/spinlock.h> - -#include <asm/io.h> - -#include "usbvideo.h" - -#if defined(MAP_NR) -#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */ -#endif - -static int video_nr = -1; -module_param(video_nr, int, 0); - -/* - * Local prototypes. - */ -static void usbvideo_Disconnect(struct usb_interface *intf); -static void usbvideo_CameraRelease(struct uvd *uvd); - -static long usbvideo_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); -static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); -static int usbvideo_v4l_open(struct file *file); -static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos); -static int usbvideo_v4l_close(struct file *file); - -static int usbvideo_StartDataPump(struct uvd *uvd); -static void usbvideo_StopDataPump(struct uvd *uvd); -static int usbvideo_GetFrame(struct uvd *uvd, int frameNum); -static int usbvideo_NewFrame(struct uvd *uvd, int framenum); -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, - struct usbvideo_frame *frame); - -/*******************************/ -/* Memory management functions */ -/*******************************/ -static void *usbvideo_rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void usbvideo_rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -static void RingQueue_Initialize(struct RingQueue *rq) -{ - assert(rq != NULL); - init_waitqueue_head(&rq->wqh); -} - -static void RingQueue_Allocate(struct RingQueue *rq, int rqLen) -{ - /* Make sure the requested size is a power of 2 and - round up if necessary. This allows index wrapping - using masks rather than modulo */ - - int i = 1; - assert(rq != NULL); - assert(rqLen > 0); - - while(rqLen >> i) - i++; - if(rqLen != 1 << (i-1)) - rqLen = 1 << i; - - rq->length = rqLen; - rq->ri = rq->wi = 0; - rq->queue = usbvideo_rvmalloc(rq->length); - assert(rq->queue != NULL); -} - -static int RingQueue_IsAllocated(const struct RingQueue *rq) -{ - if (rq == NULL) - return 0; - return (rq->queue != NULL) && (rq->length > 0); -} - -static void RingQueue_Free(struct RingQueue *rq) -{ - assert(rq != NULL); - if (RingQueue_IsAllocated(rq)) { - usbvideo_rvfree(rq->queue, rq->length); - rq->queue = NULL; - rq->length = 0; - } -} - -int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len) -{ - int rql, toread; - - assert(rq != NULL); - assert(dst != NULL); - - rql = RingQueue_GetLength(rq); - if(!rql) - return 0; - - /* Clip requested length to available data */ - if(len > rql) - len = rql; - - toread = len; - if(rq->ri > rq->wi) { - /* Read data from tail */ - int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; - memcpy(dst, rq->queue + rq->ri, read); - toread -= read; - dst += read; - rq->ri = (rq->ri + read) & (rq->length-1); - } - if(toread) { - /* Read data from head */ - memcpy(dst, rq->queue + rq->ri, toread); - rq->ri = (rq->ri + toread) & (rq->length-1); - } - return len; -} - -EXPORT_SYMBOL(RingQueue_Dequeue); - -int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n) -{ - int enqueued = 0; - - assert(rq != NULL); - assert(cdata != NULL); - assert(rq->length > 0); - while (n > 0) { - int m, q_avail; - - /* Calculate the largest chunk that fits the tail of the ring */ - q_avail = rq->length - rq->wi; - if (q_avail <= 0) { - rq->wi = 0; - q_avail = rq->length; - } - m = n; - assert(q_avail > 0); - if (m > q_avail) - m = q_avail; - - memcpy(rq->queue + rq->wi, cdata, m); - RING_QUEUE_ADVANCE_INDEX(rq, wi, m); - cdata += m; - enqueued += m; - n -= m; - } - return enqueued; -} - -EXPORT_SYMBOL(RingQueue_Enqueue); - -static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq) -{ - assert(rq != NULL); - interruptible_sleep_on(&rq->wqh); -} - -void RingQueue_WakeUpInterruptible(struct RingQueue *rq) -{ - assert(rq != NULL); - if (waitqueue_active(&rq->wqh)) - wake_up_interruptible(&rq->wqh); -} - -EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); - -void RingQueue_Flush(struct RingQueue *rq) -{ - assert(rq != NULL); - rq->ri = 0; - rq->wi = 0; -} - -EXPORT_SYMBOL(RingQueue_Flush); - - -/* - * usbvideo_VideosizeToString() - * - * This procedure converts given videosize value to readable string. - * - * History: - * 07-Aug-2000 Created. - * 19-Oct-2000 Reworked for usbvideo module. - */ -static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) -{ - char tmp[40]; - int n; - - n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs)); - assert(n < sizeof(tmp)); - if ((buf == NULL) || (bufLen < n)) - err("usbvideo_VideosizeToString: buffer is too small."); - else - memmove(buf, tmp, n); -} - -/* - * usbvideo_OverlayChar() - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, - int x, int y, int ch) -{ - static const unsigned short digits[16] = { - 0xF6DE, /* 0 */ - 0x2492, /* 1 */ - 0xE7CE, /* 2 */ - 0xE79E, /* 3 */ - 0xB792, /* 4 */ - 0xF39E, /* 5 */ - 0xF3DE, /* 6 */ - 0xF492, /* 7 */ - 0xF7DE, /* 8 */ - 0xF79E, /* 9 */ - 0x77DA, /* a */ - 0xD75C, /* b */ - 0xF24E, /* c */ - 0xD6DC, /* d */ - 0xF34E, /* e */ - 0xF348 /* f */ - }; - unsigned short digit; - int ix, iy; - int value; - - if ((uvd == NULL) || (frame == NULL)) - return; - - value = hex_to_bin(ch); - if (value < 0) - return; - digit = digits[value]; - - for (iy=0; iy < 5; iy++) { - for (ix=0; ix < 3; ix++) { - if (digit & 0x8000) { - if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { -/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); - } - } - digit = digit << 1; - } - } -} - -/* - * usbvideo_OverlayString() - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, - int x, int y, const char *str) -{ - while (*str) { - usbvideo_OverlayChar(uvd, frame, x, y, *str); - str++; - x += 4; /* 3 pixels character + 1 space */ - } -} - -/* - * usbvideo_OverlayStats() - * - * Overlays important debugging information. - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame) -{ - const int y_diff = 8; - char tmp[16]; - int x = 10, y=10; - long i, j, barLength; - const int qi_x1 = 60, qi_y1 = 10; - const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10; - - /* Call the user callback, see if we may proceed after that */ - if (VALID_CALLBACK(uvd, overlayHook)) { - if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0) - return; - } - - /* - * We draw a (mostly) hollow rectangle with qi_xxx coordinates. - * Left edge symbolizes the queue index 0; right edge symbolizes - * the full capacity of the queue. - */ - barLength = qi_x2 - qi_x1 - 2; - if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) { -/* TODO */ long u_lo, u_hi, q_used; - long m_ri, m_wi, m_lo, m_hi; - - /* - * Determine fill zones (used areas of the queue): - * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length - * - * if u_lo < 0 then there is no first filler. - */ - - q_used = RingQueue_GetLength(&uvd->dp); - if ((uvd->dp.ri + q_used) >= uvd->dp.length) { - u_hi = uvd->dp.length; - u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); - } else { - u_hi = (q_used + uvd->dp.ri); - u_lo = -1; - } - - /* Convert byte indices into screen units */ - m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length); - m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length); - m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1; - m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length); - - for (j=qi_y1; j < (qi_y1 + qi_h); j++) { - for (i=qi_x1; i < qi_x2; i++) { - /* Draw border lines */ - if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) || - (i == qi_x1) || (i == (qi_x2 - 1))) { - RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF); - continue; - } - /* For all other points the Y coordinate does not matter */ - if ((i >= m_ri) && (i <= (m_ri + 3))) { - RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00); - } else if ((i >= m_wi) && (i <= (m_wi + 3))) { - RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00); - } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi))) - RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF); - } - } - } - - sprintf(tmp, "%8lx", uvd->stats.frame_num); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.urb_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.urb_length); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.data_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.header_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.iso_err_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.colour); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.hue); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; -} - -/* - * usbvideo_ReportStatistics() - * - * This procedure prints packet and transfer statistics. - * - * History: - * 14-Jan-2000 Corrected default multiplier. - */ -static void usbvideo_ReportStatistics(const struct uvd *uvd) -{ - if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { - unsigned long allPackets, badPackets, goodPackets, percent; - allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; - badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; - goodPackets = allPackets - badPackets; - /* Calculate percentage wisely, remember integer limits */ - assert(allPackets != 0); - if (goodPackets < (((unsigned long)-1)/100)) - percent = (100 * goodPackets) / allPackets; - else - percent = goodPackets / (allPackets / 100); - dev_info(&uvd->dev->dev, - "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n", - allPackets, badPackets, percent); - if (uvd->iso_packet_len > 0) { - unsigned long allBytes, xferBytes; - char multiplier = ' '; - allBytes = allPackets * uvd->iso_packet_len; - xferBytes = uvd->stats.data_count; - assert(allBytes != 0); - if (xferBytes < (((unsigned long)-1)/100)) - percent = (100 * xferBytes) / allBytes; - else - percent = xferBytes / (allBytes / 100); - /* Scale xferBytes for easy reading */ - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'K'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'M'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'G'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'T'; - } - } - } - } - dev_info(&uvd->dev->dev, - "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n", - xferBytes, multiplier, percent); - } - } -} - -/* - * usbvideo_TestPattern() - * - * Procedure forms a test pattern (yellow grid on blue background). - * - * Parameters: - * fullframe: if TRUE then entire frame is filled, otherwise the procedure - * continues from the current scanline. - * pmode 0: fill the frame with solid blue color (like on VCR or TV) - * 1: Draw a colored grid - * - * History: - * 01-Feb-2000 Created. - */ -void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) -{ - struct usbvideo_frame *frame; - int num_cell = 0; - int scan_length = 0; - static int num_pass; - - if (uvd == NULL) { - err("%s: uvd == NULL", __func__); - return; - } - if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("%s: uvd->curframe=%d.", __func__, uvd->curframe); - return; - } - - /* Grab the current frame */ - frame = &uvd->frame[uvd->curframe]; - - /* Optionally start at the beginning */ - if (fullframe) { - frame->curline = 0; - frame->seqRead_Length = 0; - } -#if 0 - { /* For debugging purposes only */ - char tmp[20]; - usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); - dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp); - } -#endif - /* Form every scan line */ - for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { - int i; - unsigned char *f = frame->data + - (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); - for (i=0; i < VIDEOSIZE_X(frame->request); i++) { - unsigned char cb=0x80; - unsigned char cg = 0; - unsigned char cr = 0; - - if (pmode == 1) { - if (frame->curline % 32 == 0) - cb = 0, cg = cr = 0xFF; - else if (i % 32 == 0) { - if (frame->curline % 32 == 1) - num_cell++; - cb = 0, cg = cr = 0xFF; - } else { - cb = ((num_cell*7) + num_pass) & 0xFF; - cg = ((num_cell*5) + num_pass*2) & 0xFF; - cr = ((num_cell*3) + num_pass*3) & 0xFF; - } - } else { - /* Just the blue screen */ - } - - *f++ = cb; - *f++ = cg; - *f++ = cr; - scan_length += 3; - } - } - - frame->frameState = FrameState_Done; - frame->seqRead_Length += scan_length; - ++num_pass; - - /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ - usbvideo_OverlayStats(uvd, frame); -} - -EXPORT_SYMBOL(usbvideo_TestPattern); - - -#ifdef DEBUG -/* - * usbvideo_HexDump() - * - * A debugging tool. Prints hex dumps. - * - * History: - * 29-Jul-2000 Added printing of offsets. - */ -void usbvideo_HexDump(const unsigned char *data, int len) -{ - const int bytes_per_line = 32; - char tmp[128]; /* 32*3 + 5 */ - int i, k; - - for (i=k=0; len > 0; i++, len--) { - if (i > 0 && ((i % bytes_per_line) == 0)) { - printk("%s\n", tmp); - k=0; - } - if ((i % bytes_per_line) == 0) - k += sprintf(&tmp[k], "%04x: ", i); - k += sprintf(&tmp[k], "%02x ", data[i]); - } - if (k > 0) - printk("%s\n", tmp); -} - -EXPORT_SYMBOL(usbvideo_HexDump); - -#endif - -/* ******************************************************************** */ - -/* XXX: this piece of crap really wants some error handling.. */ -static int usbvideo_ClientIncModCount(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: uvd == NULL", __func__); - return -EINVAL; - } - if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __func__); - return -EINVAL; - } - if (!try_module_get(uvd->handle->md_module)) { - err("%s: try_module_get() == 0", __func__); - return -ENODEV; - } - return 0; -} - -static void usbvideo_ClientDecModCount(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: uvd == NULL", __func__); - return; - } - if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __func__); - return; - } - if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", __func__); - return; - } - module_put(uvd->handle->md_module); -} - -int usbvideo_register( - struct usbvideo **pCams, - const int num_cams, - const int num_extra, - const char *driverName, - const struct usbvideo_cb *cbTbl, - struct module *md, - const struct usb_device_id *id_table) -{ - struct usbvideo *cams; - int i, base_size, result; - - /* Check parameters for sanity */ - if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { - err("%s: Illegal call", __func__); - return -EINVAL; - } - - /* Check registration callback - must be set! */ - if (cbTbl->probe == NULL) { - err("%s: probe() is required!", __func__); - return -EINVAL; - } - - base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); - cams = kzalloc(base_size, GFP_KERNEL); - if (cams == NULL) { - err("Failed to allocate %d. bytes for usbvideo struct", base_size); - return -ENOMEM; - } - dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", - __func__, cams, base_size, num_cams); - - /* Copy callbacks, apply defaults for those that are not set */ - memmove(&cams->cb, cbTbl, sizeof(cams->cb)); - if (cams->cb.getFrame == NULL) - cams->cb.getFrame = usbvideo_GetFrame; - if (cams->cb.disconnect == NULL) - cams->cb.disconnect = usbvideo_Disconnect; - if (cams->cb.startDataPump == NULL) - cams->cb.startDataPump = usbvideo_StartDataPump; - if (cams->cb.stopDataPump == NULL) - cams->cb.stopDataPump = usbvideo_StopDataPump; - - cams->num_cameras = num_cams; - cams->cam = (struct uvd *) &cams[1]; - cams->md_module = md; - mutex_init(&cams->lock); /* to 1 == available */ - - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; - - up->handle = cams; - - /* Allocate user_data separately because of kmalloc's limits */ - if (num_extra > 0) { - up->user_size = num_cams * num_extra; - up->user_data = kmalloc(up->user_size, GFP_KERNEL); - if (up->user_data == NULL) { - err("%s: Failed to allocate user_data (%d. bytes)", - __func__, up->user_size); - while (i) { - up = &cams->cam[--i]; - kfree(up->user_data); - } - kfree(cams); - return -ENOMEM; - } - dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", - __func__, i, up->user_data, up->user_size); - } - } - - /* - * Register ourselves with USB stack. - */ - strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); - cams->usbdrv.name = cams->drvName; - cams->usbdrv.probe = cams->cb.probe; - cams->usbdrv.disconnect = cams->cb.disconnect; - cams->usbdrv.id_table = id_table; - - /* - * Update global handle to usbvideo. This is very important - * because probe() can be called before usb_register() returns. - * If the handle is not yet updated then the probe() will fail. - */ - *pCams = cams; - result = usb_register(&cams->usbdrv); - if (result) { - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; - kfree(up->user_data); - } - kfree(cams); - } - - return result; -} - -EXPORT_SYMBOL(usbvideo_register); - -/* - * usbvideo_Deregister() - * - * Procedure frees all usbvideo and user data structures. Be warned that - * if you had some dynamically allocated components in ->user field then - * you should free them before calling here. - */ -void usbvideo_Deregister(struct usbvideo **pCams) -{ - struct usbvideo *cams; - int i; - - if (pCams == NULL) { - err("%s: pCams == NULL", __func__); - return; - } - cams = *pCams; - if (cams == NULL) { - err("%s: cams == NULL", __func__); - return; - } - - dbg("%s: Deregistering %s driver.", __func__, cams->drvName); - usb_deregister(&cams->usbdrv); - - dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras); - for (i=0; i < cams->num_cameras; i++) { - struct uvd *up = &cams->cam[i]; - int warning = 0; - - if (up->user_data != NULL) { - if (up->user_size <= 0) - ++warning; - } else { - if (up->user_size > 0) - ++warning; - } - if (warning) { - err("%s: Warning: user_data=$%p user_size=%d.", - __func__, up->user_data, up->user_size); - } else { - dbg("%s: Freeing %d. $%p->user_data=$%p", - __func__, i, up, up->user_data); - kfree(up->user_data); - } - } - /* Whole array was allocated in one chunk */ - dbg("%s: Freed %d uvd structures", - __func__, cams->num_cameras); - kfree(cams); - *pCams = NULL; -} - -EXPORT_SYMBOL(usbvideo_Deregister); - -/* - * usbvideo_Disconnect() - * - * This procedure stops all driver activity. Deallocation of - * the interface-private structure (pointed by 'ptr') is done now - * (if we don't have any open files) or later, when those files - * are closed. After that driver should be removable. - * - * This code handles surprise removal. The uvd->user is a counter which - * increments on open() and decrements on close(). If we see here that - * this counter is not 0 then we have a client who still has us opened. - * We set uvd->remove_pending flag as early as possible, and after that - * all access to the camera will gracefully fail. These failures should - * prompt client to (eventually) close the video device, and then - in - * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. - * - * History: - * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. - * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - * 19-Oct-2000 Moved to usbvideo module. - */ -static void usbvideo_Disconnect(struct usb_interface *intf) -{ - struct uvd *uvd = usb_get_intfdata (intf); - int i; - - if (uvd == NULL) { - err("%s($%p): Illegal call.", __func__, intf); - return; - } - - usb_set_intfdata (intf, NULL); - - usbvideo_ClientIncModCount(uvd); - if (uvd->debug > 0) - dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); - - mutex_lock(&uvd->lock); - uvd->remove_pending = 1; /* Now all ISO data will be ignored */ - - /* At this time we ask to cancel outstanding URBs */ - GET_CALLBACK(uvd, stopDataPump)(uvd); - - for (i=0; i < USBVIDEO_NUMSBUF; i++) - usb_free_urb(uvd->sbuf[i].urb); - - usb_put_dev(uvd->dev); - uvd->dev = NULL; /* USB device is no more */ - - video_unregister_device(&uvd->vdev); - if (uvd->debug > 0) - dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); - - if (uvd->user) - dev_info(&intf->dev, "%s: In use, disconnect pending.\n", - __func__); - else - usbvideo_CameraRelease(uvd); - mutex_unlock(&uvd->lock); - dev_info(&intf->dev, "USB camera disconnected.\n"); - - usbvideo_ClientDecModCount(uvd); -} - -/* - * usbvideo_CameraRelease() - * - * This code does final release of uvd. This happens - * after the device is disconnected -and- all clients - * closed their files. - * - * History: - * 27-Jan-2000 Created. - */ -static void usbvideo_CameraRelease(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: Illegal call", __func__); - return; - } - - RingQueue_Free(&uvd->dp); - if (VALID_CALLBACK(uvd, userFree)) - GET_CALLBACK(uvd, userFree)(uvd); - uvd->uvd_used = 0; /* This is atomic, no need to take mutex */ -} - -/* - * usbvideo_find_struct() - * - * This code searches the array of preallocated (static) structures - * and returns index of the first one that isn't in use. Returns -1 - * if there are no free structures. - * - * History: - * 27-Jan-2000 Created. - */ -static int usbvideo_find_struct(struct usbvideo *cams) -{ - int u, rv = -1; - - if (cams == NULL) { - err("No usbvideo handle?"); - return -1; - } - mutex_lock(&cams->lock); - for (u = 0; u < cams->num_cameras; u++) { - struct uvd *uvd = &cams->cam[u]; - if (!uvd->uvd_used) /* This one is free */ - { - uvd->uvd_used = 1; /* In use now */ - mutex_init(&uvd->lock); /* to 1 == available */ - uvd->dev = NULL; - rv = u; - break; - } - } - mutex_unlock(&cams->lock); - return rv; -} - -static const struct v4l2_file_operations usbvideo_fops = { - .owner = THIS_MODULE, - .open = usbvideo_v4l_open, - .release =usbvideo_v4l_close, - .read = usbvideo_v4l_read, - .mmap = usbvideo_v4l_mmap, - .ioctl = usbvideo_v4l_ioctl, -}; -static const struct video_device usbvideo_template = { - .fops = &usbvideo_fops, -}; - -struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) -{ - int i, devnum; - struct uvd *uvd = NULL; - - if (cams == NULL) { - err("No usbvideo handle?"); - return NULL; - } - - devnum = usbvideo_find_struct(cams); - if (devnum == -1) { - err("IBM USB camera driver: Too many devices!"); - return NULL; - } - uvd = &cams->cam[devnum]; - dbg("Device entry #%d. at $%p", devnum, uvd); - - /* Not relying upon caller we increase module counter ourselves */ - usbvideo_ClientIncModCount(uvd); - - mutex_lock(&uvd->lock); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (uvd->sbuf[i].urb == NULL) { - err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); - uvd->uvd_used = 0; - uvd = NULL; - goto allocate_done; - } - } - uvd->user=0; - uvd->remove_pending = 0; - uvd->last_error = 0; - RingQueue_Initialize(&uvd->dp); - - /* Initialize video device structure */ - uvd->vdev = usbvideo_template; - sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName); - /* - * The client is free to overwrite those because we - * return control to the client's probe function right now. - */ -allocate_done: - mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - return uvd; -} - -EXPORT_SYMBOL(usbvideo_AllocateDevice); - -int usbvideo_RegisterVideoDevice(struct uvd *uvd) -{ - char tmp1[20], tmp2[20]; /* Buffers for printing */ - - if (uvd == NULL) { - err("%s: Illegal call.", __func__); - return -EINVAL; - } - if (uvd->video_endp == 0) { - dev_info(&uvd->dev->dev, - "%s: No video endpoint specified; data pump disabled.\n", - __func__); - } - if (uvd->paletteBits == 0) { - err("%s: No palettes specified!", __func__); - return -EINVAL; - } - if (uvd->defaultPalette == 0) { - dev_info(&uvd->dev->dev, "%s: No default palette!\n", - __func__); - } - - uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * - VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; - usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); - usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); - - if (uvd->debug > 0) { - dev_info(&uvd->dev->dev, - "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", - __func__, uvd->iface, uvd->video_endp, - uvd->paletteBits); - } - if (uvd->dev == NULL) { - err("%s: uvd->dev == NULL", __func__); - return -EINVAL; - } - uvd->vdev.parent = &uvd->dev->dev; - uvd->vdev.release = video_device_release_empty; - if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - err("%s: video_register_device failed", __func__); - return -EPIPE; - } - if (uvd->debug > 1) { - dev_info(&uvd->dev->dev, - "%s: video_register_device() successful\n", __func__); - } - - dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n", - (uvd->handle != NULL) ? uvd->handle->drvName : "???", - video_device_node_name(&uvd->vdev), tmp2, tmp1); - - usb_get_dev(uvd->dev); - return 0; -} - -EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); - -/* ******************************************************************** */ - -static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct uvd *uvd = file->private_data; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return -EFAULT; - - if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) - return -EINVAL; - - pos = (unsigned long) uvd->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -/* - * usbvideo_v4l_open() - * - * This is part of Video 4 Linux API. The driver can be opened by one - * client only (checks internal counter 'uvdser'). The procedure - * then allocates buffers needed for video processing. - * - * History: - * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the - * camera is also initialized here (once per connect), at - * expense of V4L client (it waits on open() call). - * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - */ -static int usbvideo_v4l_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct uvd *uvd = (struct uvd *) dev; - const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; - int i, errCode = 0; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); - - if (usbvideo_ClientIncModCount(uvd) < 0) - return -ENODEV; - mutex_lock(&uvd->lock); - - if (uvd->user) { - err("%s: Someone tried to open an already opened device!", __func__); - errCode = -EBUSY; - } else { - /* Clear statistics */ - memset(&uvd->stats, 0, sizeof(uvd->stats)); - - /* Clean pointers so we know if we allocated something */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) - uvd->sbuf[i].data = NULL; - - /* Allocate memory for the frame buffers */ - uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; - uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); - RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); - if ((uvd->fbuf == NULL) || - (!RingQueue_IsAllocated(&uvd->dp))) { - err("%s: Failed to allocate fbuf or dp", __func__); - errCode = -ENOMEM; - } else { - /* Allocate all buffers */ - for (i=0; i < USBVIDEO_NUMFRAMES; i++) { - uvd->frame[i].frameState = FrameState_Unused; - uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size); - /* - * Set default sizes in case IOCTL (VIDIOCMCAPTURE) - * is not used (using read() instead). - */ - uvd->frame[i].canvas = uvd->canvas; - uvd->frame[i].seqRead_Index = 0; - } - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); - if (uvd->sbuf[i].data == NULL) { - errCode = -ENOMEM; - break; - } - } - } - if (errCode != 0) { - /* Have to free all that memory */ - if (uvd->fbuf != NULL) { - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; - } - RingQueue_Free(&uvd->dp); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - kfree(uvd->sbuf[i].data); - uvd->sbuf[i].data = NULL; - } - } - } - - /* If so far no errors then we shall start the camera */ - if (errCode == 0) { - /* Start data pump if we have valid endpoint */ - if (uvd->video_endp != 0) - errCode = GET_CALLBACK(uvd, startDataPump)(uvd); - if (errCode == 0) { - if (VALID_CALLBACK(uvd, setupOnOpen)) { - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, - "%s: setupOnOpen callback\n", - __func__); - errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); - if (errCode < 0) { - err("%s: setupOnOpen callback failed (%d.).", - __func__, errCode); - } else if (uvd->debug > 1) { - dev_info(&uvd->dev->dev, - "%s: setupOnOpen callback successful\n", - __func__); - } - } - if (errCode == 0) { - uvd->settingsAdjusted = 0; - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, - "%s: Open succeeded.\n", - __func__); - uvd->user++; - file->private_data = uvd; - } - } - } - mutex_unlock(&uvd->lock); - if (errCode != 0) - usbvideo_ClientDecModCount(uvd); - if (uvd->debug > 0) - dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__, - errCode); - return errCode; -} - -/* - * usbvideo_v4l_close() - * - * This is part of Video 4 Linux API. The procedure - * stops streaming and deallocates all buffers that were earlier - * allocated in usbvideo_v4l_open(). - * - * History: - * 22-Jan-2000 Moved scratch buffer deallocation here. - * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. - * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. - */ -static int usbvideo_v4l_close(struct file *file) -{ - struct video_device *dev = file->private_data; - struct uvd *uvd = (struct uvd *) dev; - int i; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); - - mutex_lock(&uvd->lock); - GET_CALLBACK(uvd, stopDataPump)(uvd); - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; - RingQueue_Free(&uvd->dp); - - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - kfree(uvd->sbuf[i].data); - uvd->sbuf[i].data = NULL; - } - -#if USBVIDEO_REPORT_STATS - usbvideo_ReportStatistics(uvd); -#endif - - uvd->user--; - if (uvd->remove_pending) { - if (uvd->debug > 0) - dev_info(&uvd->dev->dev, "%s: Final disconnect.\n", - __func__); - usbvideo_CameraRelease(uvd); - } - mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__); - file->private_data = NULL; - return 0; -} - -/* - * usbvideo_v4l_ioctl() - * - * This is part of Video 4 Linux API. The procedure handles ioctl() calls. - * - * History: - * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. - */ -static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct uvd *uvd = file->private_data; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - *b = uvd->vcap; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - *v = uvd->vchan; - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - *pic = uvd->vpic; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - /* - * Use temporary 'video_picture' structure to preserve our - * own settings (such as color depth, palette) that we - * aren't allowing everyone (V4L client) to change. - */ - uvd->vpic.brightness = pic->brightness; - uvd->vpic.hue = pic->hue; - uvd->vpic.colour = pic->colour; - uvd->vpic.contrast = pic->contrast; - uvd->settingsAdjusted = 0; /* Will force new settings */ - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if(VALID_CALLBACK(uvd, setVideoMode)) { - return GET_CALLBACK(uvd, setVideoMode)(uvd, vw); - } - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->width != VIDEOSIZE_X(uvd->canvas)) - return -EINVAL; - if (vw->height != VIDEOSIZE_Y(uvd->canvas)) - return -EINVAL; - - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; - vw->y = 0; - vw->width = VIDEOSIZE_X(uvd->videosize); - vw->height = VIDEOSIZE_Y(uvd->videosize); - vw->chromakey = 0; - if (VALID_CALLBACK(uvd, getFPS)) - vw->flags = GET_CALLBACK(uvd, getFPS)(uvd); - else - vw->flags = 10; /* FIXME: do better! */ - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; - vm->frames = USBVIDEO_NUMFRAMES; - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) - vm->offsets[i] = i * uvd->max_frame_size; - - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (uvd->debug >= 1) { - dev_info(&uvd->dev->dev, - "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n", - vm->frame, vm->width, vm->height, vm->format); - } - /* - * Check if the requested size is supported. If the requestor - * requests too big a frame then we may be tricked into accessing - * outside of own preallocated frame buffer (in uvd->frame). - * This will cause oops or a security hole. Theoretically, we - * could only clamp the size down to acceptable bounds, but then - * we'd need to figure out how to insert our smaller buffer into - * larger caller's buffer... this is not an easy question. So we - * here just flatly reject too large requests, assuming that the - * caller will resubmit with smaller size. Callers should know - * what size we support (returned by VIDIOCGCAP). However vidcat, - * for one, does not care and allows to ask for any size. - */ - if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || - (vm->height > VIDEOSIZE_Y(uvd->canvas))) { - if (uvd->debug > 0) { - dev_info(&uvd->dev->dev, - "VIDIOCMCAPTURE: Size=%dx%d " - "too large; allowed only up " - "to %ldx%ld\n", vm->width, - vm->height, - VIDEOSIZE_X(uvd->canvas), - VIDEOSIZE_Y(uvd->canvas)); - } - return -EINVAL; - } - /* Check if the palette is supported */ - if (((1L << vm->format) & uvd->paletteBits) == 0) { - if (uvd->debug > 0) { - dev_info(&uvd->dev->dev, - "VIDIOCMCAPTURE: format=%d. " - "not supported " - "(paletteBits=$%08lx)\n", - vm->format, uvd->paletteBits); - } - return -EINVAL; - } - if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) { - err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1); - return -EINVAL; - } - if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) { - /* Not an error - can happen */ - } - uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height); - uvd->frame[vm->frame].palette = vm->format; - - /* Mark it as ready */ - uvd->frame[vm->frame].frameState = FrameState_Ready; - - return usbvideo_NewFrame(uvd, vm->frame); - } - case VIDIOCSYNC: - { - int *frameNum = arg; - int ret; - - if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES) - return -EINVAL; - - if (uvd->debug >= 1) - dev_info(&uvd->dev->dev, - "VIDIOCSYNC: syncing to frame %d.\n", - *frameNum); - if (uvd->flags & FLAGS_NO_DECODING) - ret = usbvideo_GetFrame(uvd, *frameNum); - else if (VALID_CALLBACK(uvd, getFrame)) { - ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum); - if ((ret < 0) && (uvd->debug >= 1)) { - err("VIDIOCSYNC: getFrame() returned %d.", ret); - } - } else { - err("VIDIOCSYNC: getFrame is not set"); - ret = -EFAULT; - } - - /* - * The frame is in FrameState_Done_Hold state. Release it - * right now because its data is already mapped into - * the user space and it's up to the application to - * make use of it until it asks for another frame. - */ - uvd->frame[*frameNum].frameState = FrameState_Unused; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - - case VIDIOCCAPTURE: - return -EINVAL; - - case VIDIOCSFBUF: - - case VIDIOCGTUNER: - case VIDIOCSTUNER: - - case VIDIOCGFREQ: - case VIDIOCSFREQ: - - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static long usbvideo_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl); -} - -/* - * usbvideo_v4l_read() - * - * This is mostly boring stuff. We simply ask for a frame and when it - * arrives copy all the video data from it into user space. There is - * no obvious need to override this method. - * - * History: - * 20-Oct-2000 Created. - * 01-Nov-2000 Added mutex (uvd->lock). - */ -static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct uvd *uvd = file->private_data; - int noblock = file->f_flags & O_NONBLOCK; - int frmx = -1, i; - struct usbvideo_frame *frame; - - if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) - return -EFAULT; - - if (uvd->debug >= 1) - dev_info(&uvd->dev->dev, - "%s: %Zd. bytes, noblock=%d.\n", - __func__, count, noblock); - - mutex_lock(&uvd->lock); - - /* See if a frame is completed, then use it. */ - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { - if ((uvd->frame[i].frameState == FrameState_Done) || - (uvd->frame[i].frameState == FrameState_Done_Hold) || - (uvd->frame[i].frameState == FrameState_Error)) { - frmx = i; - break; - } - } - - /* FIXME: If we don't start a frame here then who ever does? */ - if (noblock && (frmx == -1)) { - count = -EAGAIN; - goto read_done; - } - - /* - * If no FrameState_Done, look for a FrameState_Grabbing state. - * See if a frame is in process (grabbing), then use it. - * We will need to wait until it becomes cooked, of course. - */ - if (frmx == -1) { - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { - if (uvd->frame[i].frameState == FrameState_Grabbing) { - frmx = i; - break; - } - } - } - - /* - * If no frame is active, start one. We don't care which one - * it will be, so #0 is as good as any. - * In read access mode we don't have convenience of VIDIOCMCAPTURE - * to specify the requested palette (video format) on per-frame - * basis. This means that we have to return data in -some- format - * and just hope that the client knows what to do with it. - * The default format is configured in uvd->defaultPalette field - * as one of VIDEO_PALETTE_xxx values. We stuff it into the new - * frame and initiate the frame filling process. - */ - if (frmx == -1) { - if (uvd->defaultPalette == 0) { - err("%s: No default palette; don't know what to do!", __func__); - count = -EFAULT; - goto read_done; - } - frmx = 0; - /* - * We have no per-frame control over video size. - * Therefore we only can use whatever size was - * specified as default. - */ - uvd->frame[frmx].request = uvd->videosize; - uvd->frame[frmx].palette = uvd->defaultPalette; - uvd->frame[frmx].frameState = FrameState_Ready; - usbvideo_NewFrame(uvd, frmx); - /* Now frame 0 is supposed to start filling... */ - } - - /* - * Get a pointer to the active frame. It is either previously - * completed frame or frame in progress but not completed yet. - */ - frame = &uvd->frame[frmx]; - - /* - * Sit back & wait until the frame gets filled and postprocessed. - * If we fail to get the picture [in time] then return the error. - * In this call we specify that we want the frame to be waited for, - * postprocessed and switched into FrameState_Done_Hold state. This - * state is used to hold the frame as "fully completed" between - * subsequent partial reads of the same frame. - */ - if (frame->frameState != FrameState_Done_Hold) { - long rv = -EFAULT; - if (uvd->flags & FLAGS_NO_DECODING) - rv = usbvideo_GetFrame(uvd, frmx); - else if (VALID_CALLBACK(uvd, getFrame)) - rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx); - else - err("getFrame is not set"); - if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) { - count = rv; - goto read_done; - } - } - - /* - * Copy bytes to user space. We allow for partial reads, which - * means that the user application can request read less than - * the full frame size. It is up to the application to issue - * subsequent calls until entire frame is read. - * - * First things first, make sure we don't copy more than we - * have - even if the application wants more. That would be - * a big security embarassment! - */ - if ((count + frame->seqRead_Index) > frame->seqRead_Length) - count = frame->seqRead_Length - frame->seqRead_Index; - - /* - * Copy requested amount of data to user space. We start - * copying from the position where we last left it, which - * will be zero for a new frame (not read before). - */ - if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) { - count = -EFAULT; - goto read_done; - } - - /* Update last read position */ - frame->seqRead_Index += count; - if (uvd->debug >= 1) { - err("%s: {copy} count used=%Zd, new seqRead_Index=%ld", - __func__, count, frame->seqRead_Index); - } - - /* Finally check if the frame is done with and "release" it */ - if (frame->seqRead_Index >= frame->seqRead_Length) { - /* All data has been read */ - frame->seqRead_Index = 0; - - /* Mark it as available to be used again. */ - uvd->frame[frmx].frameState = FrameState_Unused; - if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { - err("%s: usbvideo_NewFrame failed.", __func__); - } - } -read_done: - mutex_unlock(&uvd->lock); - return count; -} - -/* - * Make all of the blocks of data contiguous - */ -static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb) -{ - char *cdata; - int i, totlen = 0; - - for (i = 0; i < urb->number_of_packets; i++) { - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - - cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (st < 0) { - if (uvd->debug >= 1) - err("Data error: packet=%d. len=%d. status=%d.", i, n, st); - uvd->stats.iso_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (n <= 0) { - uvd->stats.iso_skip_count++; - continue; - } - totlen += n; /* Little local accounting */ - RingQueue_Enqueue(&uvd->dp, cdata, n); - } - return totlen; -} - -static void usbvideo_IsocIrq(struct urb *urb) -{ - int i, ret, len; - struct uvd *uvd = urb->context; - - /* We don't want to do anything if we are about to be removed! */ - if (!CAMERA_IS_OPERATIONAL(uvd)) - return; -#if 0 - if (urb->actual_length > 0) { - dev_info(&uvd->dev->dev, - "urb=$%p status=%d. errcount=%d. length=%d.\n", - urb, urb->status, urb->error_count, - urb->actual_length); - } else { - static int c = 0; - if (c++ % 100 == 0) - dev_info(&uvd->dev->dev, "No Isoc data\n"); - } -#endif - - if (!uvd->streaming) { - if (uvd->debug >= 1) - dev_info(&uvd->dev->dev, - "Not streaming, but interrupt!\n"); - return; - } - - uvd->stats.urb_count++; - if (urb->actual_length <= 0) - goto urb_done_with; - - /* Copy the data received into ring queue */ - len = usbvideo_CompressIsochronous(uvd, urb); - uvd->stats.urb_length = len; - if (len <= 0) - goto urb_done_with; - - /* Here we got some data */ - uvd->stats.data_count += len; - RingQueue_WakeUpInterruptible(&uvd->dp); - -urb_done_with: - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - urb->dev = uvd->dev; - ret = usb_submit_urb (urb, GFP_KERNEL); - if(ret) - err("usb_submit_urb error (%d)", ret); - return; -} - -/* - * usbvideo_StartDataPump() - * - * History: - * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead - * of hardcoded values. Simplified by using for loop, - * allowed any number of URBs. - */ -static int usbvideo_StartDataPump(struct uvd *uvd) -{ - struct usb_device *dev = uvd->dev; - int i, errFlag; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); - - if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("%s: Camera is not operational", __func__); - return -EFAULT; - } - uvd->curframe = -1; - - /* Alternate interface 1 is is the biggest frame size */ - i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); - if (i < 0) { - err("%s: usb_set_interface error", __func__); - uvd->last_error = i; - return -EBUSY; - } - if (VALID_CALLBACK(uvd, videoStart)) - GET_CALLBACK(uvd, videoStart)(uvd); - else - err("%s: videoStart not set", __func__); - - /* We double buffer the Iso lists */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - int j, k; - struct urb *urb = uvd->sbuf[i].urb; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = uvd->sbuf[i].data; - urb->complete = usbvideo_IsocIrq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC; - for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = uvd->iso_packet_len; - } - } - - /* Submit all URBs */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); - if (errFlag) - err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag); - } - - uvd->streaming = 1; - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, - "%s: streaming=1 video_endp=$%02x\n", __func__, - uvd->video_endp); - return 0; -} - -/* - * usbvideo_StopDataPump() - * - * This procedure stops streaming and deallocates URBs. Then it - * activates zero-bandwidth alt. setting of the video interface. - * - * History: - * 22-Jan-2000 Corrected order of actions to work after surprise removal. - * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. - */ -static void usbvideo_StopDataPump(struct uvd *uvd) -{ - int i, j; - - if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) - return; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); - - /* Unschedule all of the iso td's */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - usb_kill_urb(uvd->sbuf[i].urb); - } - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__); - uvd->streaming = 0; - - if (!uvd->remove_pending) { - /* Invoke minidriver's magic to stop the camera */ - if (VALID_CALLBACK(uvd, videoStop)) - GET_CALLBACK(uvd, videoStop)(uvd); - else - err("%s: videoStop not set", __func__); - - /* Set packet size to 0 */ - j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); - if (j < 0) { - err("%s: usb_set_interface() error %d.", __func__, j); - uvd->last_error = j; - } - } -} - -/* - * usbvideo_NewFrame() - * - * History: - * 29-Mar-00 Added copying of previous frame into the current one. - * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. - */ -static int usbvideo_NewFrame(struct uvd *uvd, int framenum) -{ - struct usbvideo_frame *frame; - int n; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd, - framenum); - - /* If we're not grabbing a frame right now and the other frame is */ - /* ready to be grabbed into, then use it instead */ - if (uvd->curframe != -1) - return 0; - - /* If necessary we adjust picture settings between frames */ - if (!uvd->settingsAdjusted) { - if (VALID_CALLBACK(uvd, adjustPicture)) - GET_CALLBACK(uvd, adjustPicture)(uvd); - uvd->settingsAdjusted = 1; - } - - n = (framenum + 1) % USBVIDEO_NUMFRAMES; - if (uvd->frame[n].frameState == FrameState_Ready) - framenum = n; - - frame = &uvd->frame[framenum]; - - frame->frameState = FrameState_Grabbing; - frame->scanstate = ScanState_Scanning; - frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */ - frame->deinterlace = Deinterlace_None; - frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */ - uvd->curframe = framenum; - - /* - * Normally we would want to copy previous frame into the current one - * before we even start filling it with data; this allows us to stop - * filling at any moment; top portion of the frame will be new and - * bottom portion will stay as it was in previous frame. If we don't - * do that then missing chunks of video stream will result in flickering - * portions of old data whatever it was before. - * - * If we choose not to copy previous frame (to, for example, save few - * bus cycles - the frame can be pretty large!) then we have an option - * to clear the frame before using. If we experience losses in this - * mode then missing picture will be black (no flickering). - * - * Finally, if user chooses not to clean the current frame before - * filling it with data then the old data will be visible if we fail - * to refill entire frame with new data. - */ - if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { - /* This copies previous frame into this one to mask losses */ - int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; - memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); - } else { - if (uvd->flags & FLAGS_CLEAN_FRAMES) { - /* This provides a "clean" frame but slows things down */ - memset(frame->data, 0, uvd->max_frame_size); - } - } - return 0; -} - -/* - * usbvideo_CollectRawData() - * - * This procedure can be used instead of 'processData' callback if you - * only want to dump the raw data from the camera into the output - * device (frame buffer). You can look at it with V4L client, but the - * image will be unwatchable. The main purpose of this code and of the - * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from - * new, unknown cameras. This procedure will be automatically invoked - * instead of the specified callback handler when uvd->flags has bit - * FLAGS_NO_DECODING set. Therefore, any regular build of any driver - * based on usbvideo can use this feature at any time. - */ -static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame) -{ - int n; - - assert(uvd != NULL); - assert(frame != NULL); - - /* Try to move data from queue into frame buffer */ - n = RingQueue_GetLength(&uvd->dp); - if (n > 0) { - int m; - /* See how much space we have left */ - m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; - /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; - } - /* See if we filled the frame */ - if (frame->seqRead_Length >= uvd->max_frame_size) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - -static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) -{ - struct usbvideo_frame *frame = &uvd->frame[frameNum]; - - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd, - frameNum); - - switch (frame->frameState) { - case FrameState_Unused: - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n", - __func__); - return -EINVAL; - case FrameState_Ready: - case FrameState_Grabbing: - case FrameState_Error: - { - int ntries, signalPending; - redo: - if (!CAMERA_IS_OPERATIONAL(uvd)) { - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Camera is not operational (1)\n", - __func__); - return -EIO; - } - ntries = 0; - do { - RingQueue_InterruptibleSleepOn(&uvd->dp); - signalPending = signal_pending(current); - if (!CAMERA_IS_OPERATIONAL(uvd)) { - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Camera is not " - "operational (2)\n", __func__); - return -EIO; - } - assert(uvd->fbuf != NULL); - if (signalPending) { - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Signal=$%08x\n", __func__, - signalPending); - if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { - usbvideo_TestPattern(uvd, 1, 0); - uvd->curframe = -1; - uvd->stats.frame_num++; - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Forced test " - "pattern screen\n", - __func__); - return 0; - } else { - /* Standard answer: Interrupted! */ - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Interrupted!\n", - __func__); - return -EINTR; - } - } else { - /* No signals - we just got new data in dp queue */ - if (uvd->flags & FLAGS_NO_DECODING) - usbvideo_CollectRawData(uvd, frame); - else if (VALID_CALLBACK(uvd, processData)) - GET_CALLBACK(uvd, processData)(uvd, frame); - else - err("%s: processData not set", __func__); - } - } while (frame->frameState == FrameState_Grabbing); - if (uvd->debug >= 2) { - dev_info(&uvd->dev->dev, - "%s: Grabbing done; state=%d. (%lu. bytes)\n", - __func__, frame->frameState, - frame->seqRead_Length); - } - if (frame->frameState == FrameState_Error) { - int ret = usbvideo_NewFrame(uvd, frameNum); - if (ret < 0) { - err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret); - return ret; - } - goto redo; - } - /* Note that we fall through to meet our destiny below */ - } - case FrameState_Done: - /* - * Do all necessary postprocessing of data prepared in - * "interrupt" code and the collecting code above. The - * frame gets marked as FrameState_Done by queue parsing code. - * This status means that we collected enough data and - * most likely processed it as we went through. However - * the data may need postprocessing, such as deinterlacing - * or picture adjustments implemented in software (horror!) - * - * As soon as the frame becomes "final" it gets promoted to - * FrameState_Done_Hold status where it will remain until the - * caller consumed all the video data from the frame. Then - * the empty shell of ex-frame is thrown out for dogs to eat. - * But we, worried about pets, will recycle the frame! - */ - uvd->stats.frame_num++; - if ((uvd->flags & FLAGS_NO_DECODING) == 0) { - if (VALID_CALLBACK(uvd, postProcess)) - GET_CALLBACK(uvd, postProcess)(uvd, frame); - if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST) - usbvideo_SoftwareContrastAdjustment(uvd, frame); - } - frame->frameState = FrameState_Done_Hold; - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Entered FrameState_Done_Hold state.\n", - __func__); - return 0; - - case FrameState_Done_Hold: - /* - * We stay in this state indefinitely until someone external, - * like ioctl() or read() call finishes digesting the frame - * data. Then it will mark the frame as FrameState_Unused and - * it will be released back into the wild to roam freely. - */ - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: FrameState_Done_Hold state.\n", - __func__); - return 0; - } - - /* Catch-all for other cases. We shall not be here. */ - err("%s: Invalid state %d.", __func__, frame->frameState); - frame->frameState = FrameState_Unused; - return 0; -} - -/* - * usbvideo_DeinterlaceFrame() - * - * This procedure deinterlaces the given frame. Some cameras produce - * only half of scanlines - sometimes only even lines, sometimes only - * odd lines. The deinterlacing method is stored in frame->deinterlace - * variable. - * - * Here we scan the frame vertically and replace missing scanlines with - * average between surrounding ones - before and after. If we have no - * line above then we just copy next line. Similarly, if we need to - * create a last line then preceding line is used. - */ -void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame) -{ - if ((uvd == NULL) || (frame == NULL)) - return; - - if ((frame->deinterlace == Deinterlace_FillEvenLines) || - (frame->deinterlace == Deinterlace_FillOddLines)) - { - const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1; - - for (; i < VIDEOSIZE_Y(frame->request); i += 2) { - const unsigned char *fs1, *fs2; - unsigned char *fd; - int ip, in, j; /* Previous and next lines */ - - /* - * Need to average lines before and after 'i'. - * If we go out of bounds seeking those lines then - * we point back to existing line. - */ - ip = i - 1; /* First, get rough numbers */ - in = i + 1; - - /* Now validate */ - if (ip < 0) - ip = in; - if (in >= VIDEOSIZE_Y(frame->request)) - in = ip; - - /* Sanity check */ - if ((ip < 0) || (in < 0) || - (ip >= VIDEOSIZE_Y(frame->request)) || - (in >= VIDEOSIZE_Y(frame->request))) - { - err("Error: ip=%d. in=%d. req.height=%ld.", - ip, in, VIDEOSIZE_Y(frame->request)); - break; - } - - /* Now we need to average lines 'ip' and 'in' to produce line 'i' */ - fs1 = frame->data + (v4l_linesize * ip); - fs2 = frame->data + (v4l_linesize * in); - fd = frame->data + (v4l_linesize * i); - - /* Average lines around destination */ - for (j=0; j < v4l_linesize; j++) { - fd[j] = (unsigned char)((((unsigned) fs1[j]) + - ((unsigned)fs2[j])) >> 1); - } - } - } - - /* Optionally display statistics on the screen */ - if (uvd->flags & FLAGS_OVERLAY_STATS) - usbvideo_OverlayStats(uvd, frame); -} - -EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); - -/* - * usbvideo_SoftwareContrastAdjustment() - * - * This code adjusts the contrast of the frame, assuming RGB24 format. - * As most software image processing, this job is CPU-intensive. - * Get a camera that supports hardware adjustment! - * - * History: - * 09-Feb-2001 Created. - */ -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, - struct usbvideo_frame *frame) -{ - int i, j, v4l_linesize; - signed long adj; - const int ccm = 128; /* Color correction median - see below */ - - if ((uvd == NULL) || (frame == NULL)) { - err("%s: Illegal call.", __func__); - return; - } - adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(adj, -ccm, ccm+1); - if (adj == 0) { - /* In rare case of no adjustment */ - return; - } - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - for (i=0; i < VIDEOSIZE_Y(frame->request); i++) { - unsigned char *fd = frame->data + (v4l_linesize * i); - for (j=0; j < v4l_linesize; j++) { - signed long v = (signed long) fd[j]; - /* Magnify up to 2 times, reduce down to zero */ - v = 128 + ((ccm + adj) * (v - 128)) / ccm; - RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */ - fd[j] = (unsigned char) v; - } - } -} - -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h deleted file mode 100644 index c66985beb8c..00000000000 --- a/drivers/media/video/usbvideo/usbvideo.h +++ /dev/null @@ -1,395 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef usbvideo_h -#define usbvideo_h - -#include <linux/videodev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <linux/usb.h> -#include <linux/mutex.h> - -/* Most helpful debugging aid */ -#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) - -#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */ - -/* Bit flags (options) */ -#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) -#define FLAGS_MONOCHROME (1 << 1) -#define FLAGS_DISPLAY_HINTS (1 << 2) -#define FLAGS_OVERLAY_STATS (1 << 3) -#define FLAGS_FORCE_TESTPATTERN (1 << 4) -#define FLAGS_SEPARATE_FRAMES (1 << 5) -#define FLAGS_CLEAN_FRAMES (1 << 6) -#define FLAGS_NO_DECODING (1 << 7) - -/* Bit flags for frames (apply to the frame where they are specified) */ -#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0) - -/* Camera capabilities (maximum) */ -#define CAMERA_URB_FRAMES 32 -#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ -#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) -#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) - -/* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } - -#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */ - -/* - * Use this macro to construct constants for different video sizes. - * We have to deal with different video sizes that have to be - * configured in the device or compared against when we receive - * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y - * #defines and that's the end of story. However this solution - * does not allow to convert between real pixel sizes and the - * constant (integer) value that may be used to tag a frame or - * whatever. The set of macros below constructs videosize constants - * from the pixel size and allows to reconstruct the pixel size - * from the combined value later. - */ -#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16)) -#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL) -#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL) -typedef unsigned long videosize_t; - -/* - * This macro checks if the camera is still operational. The 'uvd' - * pointer must be valid, uvd->dev must be valid, we are not - * removing the device and the device has not erred on us. - */ -#define CAMERA_IS_OPERATIONAL(uvd) (\ - (uvd != NULL) && \ - ((uvd)->dev != NULL) && \ - ((uvd)->last_error == 0) && \ - (!(uvd)->remove_pending)) - -/* - * We use macros to do YUV -> RGB conversion because this is - * very important for speed and totally unimportant for size. - * - * YUV -> RGB Conversion - * --------------------- - * - * B = 1.164*(Y-16) + 2.018*(V-128) - * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) - * R = 1.164*(Y-16) + 1.596*(U-128) - * - * If you fancy integer arithmetics (as you should), hear this: - * - * 65536*B = 76284*(Y-16) + 132252*(V-128) - * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) - * 65536*R = 76284*(Y-16) + 104595*(U-128) - * - * Make sure the output values are within [0..255] range. - */ -#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc= mm_y * 76284; \ - mm_b = (mm_yc + 132252*mm_v ) >> 16; \ - mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ - mm_r = (mm_yc + 104595*mm_u ) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ -} - -#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ -#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) -#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) -#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) - -struct RingQueue { - unsigned char *queue; /* Data from the Isoc data pump */ - int length; /* How many bytes allocated for the queue */ - int wi; /* That's where we write */ - int ri; /* Read from here until you hit write index */ - wait_queue_head_t wqh; /* Processes waiting */ -}; - -enum ScanState { - ScanState_Scanning, /* Scanning for header */ - ScanState_Lines /* Parsing lines */ -}; - -/* Completion states of the data parser */ -enum ParseState { - scan_Continue, /* Just parse next item */ - scan_NextFrame, /* Frame done, send it to V4L */ - scan_Out, /* Not enough data for frame */ - scan_EndParse /* End parsing */ -}; - -enum FrameState { - FrameState_Unused, /* Unused (no MCAPTURE) */ - FrameState_Ready, /* Ready to start grabbing */ - FrameState_Grabbing, /* In the process of being grabbed into */ - FrameState_Done, /* Finished grabbing, but not been synced yet */ - FrameState_Done_Hold, /* Are syncing or reading */ - FrameState_Error, /* Something bad happened while processing */ -}; - -/* - * Some frames may contain only even or odd lines. This type - * specifies what type of deinterlacing is required. - */ -enum Deinterlace { - Deinterlace_None=0, - Deinterlace_FillOddLines, - Deinterlace_FillEvenLines -}; - -#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ -#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ - -/* This structure represents one Isoc request - URB and buffer */ -struct usbvideo_sbuf { - char *data; - struct urb *urb; -}; - -struct usbvideo_frame { - char *data; /* Frame buffer */ - unsigned long header; /* Significant bits from the header */ - - videosize_t canvas; /* The canvas (max. image) allocated */ - videosize_t request; /* That's what the application asked for */ - unsigned short palette; /* The desired format */ - - enum FrameState frameState;/* State of grabbing */ - enum ScanState scanstate; /* State of scanning */ - enum Deinterlace deinterlace; - int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ - - int curline; /* Line of frame we're working on */ - - long seqRead_Length; /* Raw data length of frame */ - long seqRead_Index; /* Amount of data that has been already read */ - - void *user; /* Additional data that user may need */ -}; - -/* Statistics that can be overlaid on screen */ -struct usbvideo_statistics { - unsigned long frame_num; /* Sequential number of the frame */ - unsigned long urb_count; /* How many URBs we received so far */ - unsigned long urb_length; /* Length of last URB */ - unsigned long data_count; /* How many bytes we received */ - unsigned long header_count; /* How many frame headers we found */ - unsigned long iso_skip_count; /* How many empty ISO packets received */ - unsigned long iso_err_count; /* How many bad ISO packets received */ -}; - -struct usbvideo; - -struct uvd { - struct video_device vdev; /* Must be the first field! */ - struct usb_device *dev; - struct usbvideo *handle; /* Points back to the struct usbvideo */ - void *user_data; /* Camera-dependent data */ - int user_size; /* Size of that camera-dependent data */ - int debug; /* Debug level for usbvideo */ - unsigned char iface; /* Video interface number */ - unsigned char video_endp; - unsigned char ifaceAltActive; - unsigned char ifaceAltInactive; /* Alt settings */ - unsigned long flags; /* FLAGS_USBVIDEO_xxx */ - unsigned long paletteBits; /* Which palettes we accept? */ - unsigned short defaultPalette; /* What palette to use for read() */ - struct mutex lock; - int user; /* user count for exclusive use */ - - videosize_t videosize; /* Current setting */ - videosize_t canvas; /* This is the width,height of the V4L canvas */ - int max_frame_size; /* Bytes in one video frame */ - - int uvd_used; /* Is this structure in use? */ - int streaming; /* Are we streaming Isochronous? */ - int grabbing; /* Are we grabbing? */ - int settingsAdjusted; /* Have we adjusted contrast etc.? */ - int last_error; /* What calamity struck us? */ - - char *fbuf; /* Videodev buffer area */ - int fbuf_size; /* Videodev buffer size */ - - int curframe; - int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ - - struct RingQueue dp; /* Isoc data pump */ - struct usbvideo_frame frame[USBVIDEO_NUMFRAMES]; - struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF]; - - volatile int remove_pending; /* If set then about to exit */ - - struct video_picture vpic, vpic_old; /* Picture settings */ - struct video_capability vcap; /* Video capabilities */ - struct video_channel vchan; /* May be used for tuner support */ - struct usbvideo_statistics stats; - char videoName[32]; /* Holds name like "video7" */ -}; - -/* - * usbvideo callbacks (virtual methods). They are set when usbvideo - * services are registered. All of these default to NULL, except those - * that default to usbvideo-provided methods. - */ -struct usbvideo_cb { - int (*probe)(struct usb_interface *, const struct usb_device_id *); - void (*userFree)(struct uvd *); - void (*disconnect)(struct usb_interface *); - int (*setupOnOpen)(struct uvd *); - void (*videoStart)(struct uvd *); - void (*videoStop)(struct uvd *); - void (*processData)(struct uvd *, struct usbvideo_frame *); - void (*postProcess)(struct uvd *, struct usbvideo_frame *); - void (*adjustPicture)(struct uvd *); - int (*getFPS)(struct uvd *); - int (*overlayHook)(struct uvd *, struct usbvideo_frame *); - int (*getFrame)(struct uvd *, int); - int (*startDataPump)(struct uvd *uvd); - void (*stopDataPump)(struct uvd *uvd); - int (*setVideoMode)(struct uvd *uvd, struct video_window *vw); -}; - -struct usbvideo { - int num_cameras; /* As allocated */ - struct usb_driver usbdrv; /* Interface to the USB stack */ - char drvName[80]; /* Driver name */ - struct mutex lock; /* Mutex protecting camera structures */ - struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ - struct video_device vdt; /* Video device template */ - struct uvd *cam; /* Array of camera structures */ - struct module *md_module; /* Minidriver module */ -}; - - -/* - * This macro retrieves callback address from the struct uvd object. - * No validity checks are done here, so be sure to check the - * callback beforehand with VALID_CALLBACK. - */ -#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName) - -/* - * This macro returns either callback pointer or NULL. This is safe - * macro, meaning that most of components of data structures involved - * may be NULL - this only results in NULL being returned. You may - * wish to use this macro to make sure that the callback is callable. - * However keep in mind that those checks take time. - */ -#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ - ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) - -int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len); -int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n); -void RingQueue_WakeUpInterruptible(struct RingQueue *rq); -void RingQueue_Flush(struct RingQueue *rq); - -static inline int RingQueue_GetLength(const struct RingQueue *rq) -{ - return (rq->wi - rq->ri + rq->length) & (rq->length-1); -} - -static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq) -{ - return rq->length - RingQueue_GetLength(rq); -} - -void usbvideo_DrawLine( - struct usbvideo_frame *frame, - int x1, int y1, - int x2, int y2, - unsigned char cr, unsigned char cg, unsigned char cb); -void usbvideo_HexDump(const unsigned char *data, int len); -void usbvideo_SayAndWait(const char *what); -void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode); - -/* Memory allocation routines */ -unsigned long usbvideo_kvirt_to_pa(unsigned long adr); - -int usbvideo_register( - struct usbvideo **pCams, - const int num_cams, - const int num_extra, - const char *driverName, - const struct usbvideo_cb *cbTable, - struct module *md, - const struct usb_device_id *id_table); -struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams); -int usbvideo_RegisterVideoDevice(struct uvd *uvd); -void usbvideo_Deregister(struct usbvideo **uvt); - -int usbvideo_v4l_initialize(struct video_device *dev); - -void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame); - -/* - * This code performs bounds checking - use it when working with - * new formats, or else you may get oopses all over the place. - * If pixel falls out of bounds then it gets shoved back (as close - * to place of offence as possible) and is painted bright red. - * - * There are two important concepts: frame width, height and - * V4L canvas width, height. The former is the area requested by - * the application -for this very frame-. The latter is the largest - * possible frame that we can serve (we advertise that via V4L ioctl). - * The frame data is expected to be formatted as lines of length - * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. - */ -static inline void RGB24_PUTPIXEL( - struct usbvideo_frame *fr, - int ix, int iy, - unsigned char vr, - unsigned char vg, - unsigned char vb) -{ - register unsigned char *pf; - int limiter = 0, mx, my; - mx = ix; - my = iy; - if (mx < 0) { - mx=0; - limiter++; - } else if (mx >= VIDEOSIZE_X((fr)->request)) { - mx= VIDEOSIZE_X((fr)->request) - 1; - limiter++; - } - if (my < 0) { - my = 0; - limiter++; - } else if (my >= VIDEOSIZE_Y((fr)->request)) { - my = VIDEOSIZE_Y((fr)->request) - 1; - limiter++; - } - pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix)); - if (limiter) { - *pf++ = 0; - *pf++ = 0; - *pf++ = 0xFF; - } else { - *pf++ = (vb); - *pf++ = (vg); - *pf++ = (vr); - } -} - -#endif /* usbvideo_h */ diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c deleted file mode 100644 index dc17cce2fbb..00000000000 --- a/drivers/media/video/usbvideo/vicam.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * USB ViCam WebCam driver - * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), - * Christopher L Cheney (ccheney@cheney.cx), - * Pavel Machek (pavel@ucw.cz), - * John Tyner (jtyner@cs.ucr.edu), - * Monroe Williams (monroe@pobox.com) - * - * Supports 3COM HomeConnect PC Digital WebCam - * Supports Compro PS39U WebCam - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This source code is based heavily on the CPiA webcam driver which was - * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt - * - * Portions of this code were also copied from usbvideo.c - * - * Special thanks to the whole team at Sourceforge for help making - * this driver become a reality. Notably: - * Andy Armstrong who reverse engineered the color encoding and - * Pavel Machek and Chris Cheney who worked on reverse engineering the - * camera controls and wrote the first generation driver. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/videodev.h> -#include <linux/usb.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/firmware.h> -#include <linux/ihex.h> -#include "usbvideo.h" - -// #define VICAM_DEBUG - -#ifdef VICAM_DEBUG -#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args) -#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) -#else -#define DBG(fmn,args...) do {} while(0) -#endif - -#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" -#define DRIVER_DESC "ViCam WebCam Driver" - -/* Define these values to match your device */ -#define USB_VICAM_VENDOR_ID 0x04c1 -#define USB_VICAM_PRODUCT_ID 0x009d -#define USB_COMPRO_VENDOR_ID 0x0602 -#define USB_COMPRO_PRODUCT_ID 0x1001 - -#define VICAM_BYTES_PER_PIXEL 3 -#define VICAM_MAX_READ_SIZE (512*242+128) -#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) -#define VICAM_FRAMES 2 - -#define VICAM_HEADER_SIZE 64 - -/* rvmalloc / rvfree copied from usbvideo.c - * - * Not sure why these are not yet non-statics which I can reference through - * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime - * in the future. - * -*/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -struct vicam_camera { - u16 shutter_speed; // capture shutter speed - u16 gain; // capture gain - - u8 *raw_image; // raw data captured from the camera - u8 *framebuf; // processed data in RGB24 format - u8 *cntrlbuf; // area used to send control msgs - - struct video_device vdev; // v4l video device - struct usb_device *udev; // usb device - - /* guard against simultaneous accesses to the camera */ - struct mutex cam_lock; - - int is_initialized; - u8 open_count; - u8 bulkEndpoint; - int needsDummyRead; -}; - -static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); -static void vicam_disconnect(struct usb_interface *intf); -static void read_frame(struct vicam_camera *cam, int framenum); -static void vicam_decode_color(const u8 *, u8 *); - -static int __send_control_msg(struct vicam_camera *cam, - u8 request, - u16 value, - u16 index, - unsigned char *cp, - u16 size) -{ - int status; - - /* cp must be memory that has been allocated by kmalloc */ - - status = usb_control_msg(cam->udev, - usb_sndctrlpipe(cam->udev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, - cp, size, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_INFO "Failed sending control message, error %d.\n", - status); - } - - return status; -} - -static int send_control_msg(struct vicam_camera *cam, - u8 request, - u16 value, - u16 index, - unsigned char *cp, - u16 size) -{ - int status = -ENODEV; - mutex_lock(&cam->cam_lock); - if (cam->udev) { - status = __send_control_msg(cam, request, value, - index, cp, size); - } - mutex_unlock(&cam->cam_lock); - return status; -} -static int -initialize_camera(struct vicam_camera *cam) -{ - int err; - const struct ihex_binrec *rec; - const struct firmware *uninitialized_var(fw); - - err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev); - if (err) { - printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %d\n", - err); - return err; - } - - for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { - memcpy(cam->cntrlbuf, rec->data, be16_to_cpu(rec->len)); - - err = send_control_msg(cam, 0xff, 0, 0, - cam->cntrlbuf, be16_to_cpu(rec->len)); - if (err) - break; - } - - release_firmware(fw); - - return err; -} - -static int -set_camera_power(struct vicam_camera *cam, int state) -{ - int status; - - if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0) - return status; - - if (state) { - send_control_msg(cam, 0x55, 1, 0, NULL, 0); - } - - return 0; -} - -static long -vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg) -{ - void __user *user_arg = (void __user *)arg; - struct vicam_camera *cam = file->private_data; - long retval = 0; - - if (!cam) - return -ENODEV; - - switch (ioctlnr) { - /* query capabilities */ - case VIDIOCGCAP: - { - struct video_capability b; - - DBG("VIDIOCGCAP\n"); - memset(&b, 0, sizeof(b)); - strcpy(b.name, "ViCam-based Camera"); - b.type = VID_TYPE_CAPTURE; - b.channels = 1; - b.audios = 0; - b.maxwidth = 320; /* VIDEOSIZE_CIF */ - b.maxheight = 240; - b.minwidth = 320; /* VIDEOSIZE_48_48 */ - b.minheight = 240; - - if (copy_to_user(user_arg, &b, sizeof(b))) - retval = -EFAULT; - - break; - } - /* get/set video source - we are a camera and nothing else */ - case VIDIOCGCHAN: - { - struct video_channel v; - - DBG("VIDIOCGCHAN\n"); - if (copy_from_user(&v, user_arg, sizeof(v))) { - retval = -EFAULT; - break; - } - if (v.channel != 0) { - retval = -EINVAL; - break; - } - - v.channel = 0; - strcpy(v.name, "Camera"); - v.tuners = 0; - v.flags = 0; - v.type = VIDEO_TYPE_CAMERA; - v.norm = 0; - - if (copy_to_user(user_arg, &v, sizeof(v))) - retval = -EFAULT; - break; - } - - case VIDIOCSCHAN: - { - int v; - - if (copy_from_user(&v, user_arg, sizeof(v))) - retval = -EFAULT; - DBG("VIDIOCSCHAN %d\n", v); - - if (retval == 0 && v != 0) - retval = -EINVAL; - - break; - } - - /* image properties */ - case VIDIOCGPICT: - { - struct video_picture vp; - DBG("VIDIOCGPICT\n"); - memset(&vp, 0, sizeof (struct video_picture)); - vp.brightness = cam->gain << 8; - vp.depth = 24; - vp.palette = VIDEO_PALETTE_RGB24; - if (copy_to_user(user_arg, &vp, sizeof (struct video_picture))) - retval = -EFAULT; - break; - } - - case VIDIOCSPICT: - { - struct video_picture vp; - - if (copy_from_user(&vp, user_arg, sizeof(vp))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, - vp.palette); - - cam->gain = vp.brightness >> 8; - - if (vp.depth != 24 - || vp.palette != VIDEO_PALETTE_RGB24) - retval = -EINVAL; - - break; - } - - /* get/set capture window */ - case VIDIOCGWIN: - { - struct video_window vw; - vw.x = 0; - vw.y = 0; - vw.width = 320; - vw.height = 240; - vw.chromakey = 0; - vw.flags = 0; - vw.clips = NULL; - vw.clipcount = 0; - - DBG("VIDIOCGWIN\n"); - - if (copy_to_user(user_arg, (void *)&vw, sizeof(vw))) - retval = -EFAULT; - - // I'm not sure what the deal with a capture window is, it is very poorly described - // in the doc. So I won't support it now. - break; - } - - case VIDIOCSWIN: - { - - struct video_window vw; - - if (copy_from_user(&vw, user_arg, sizeof(vw))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height); - - if ( vw.width != 320 || vw.height != 240 ) - retval = -EFAULT; - - break; - } - - /* mmap interface */ - case VIDIOCGMBUF: - { - struct video_mbuf vm; - int i; - - DBG("VIDIOCGMBUF\n"); - memset(&vm, 0, sizeof (vm)); - vm.size = - VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; - vm.frames = VICAM_FRAMES; - for (i = 0; i < VICAM_FRAMES; i++) - vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; - - if (copy_to_user(user_arg, (void *)&vm, sizeof(vm))) - retval = -EFAULT; - - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - // int video_size; - - if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); - - if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) - retval = -EINVAL; - - // in theory right here we'd start the image capturing - // (fill in a bulk urb and submit it asynchronously) - // - // Instead we're going to do a total hack job for now and - // retrieve the frame in VIDIOCSYNC - - break; - } - - case VIDIOCSYNC: - { - int frame; - - if (copy_from_user((void *)&frame, user_arg, sizeof(int))) { - retval = -EFAULT; - break; - } - DBG("VIDIOCSYNC: %d\n", frame); - - read_frame(cam, frame); - vicam_decode_color(cam->raw_image, - cam->framebuf + - frame * VICAM_MAX_FRAME_SIZE ); - - break; - } - - /* pointless to implement overlay with this camera */ - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCKEY: - retval = -EINVAL; - break; - - /* tuner interface - we have none */ - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - retval = -EINVAL; - break; - - /* audio interface - we have none */ - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - retval = -EINVAL; - break; - default: - retval = -ENOIOCTLCMD; - break; - } - - return retval; -} - -static int -vicam_open(struct file *file) -{ - struct vicam_camera *cam = video_drvdata(file); - - DBG("open\n"); - - if (!cam) { - printk(KERN_ERR - "vicam video_device improperly initialized"); - return -EINVAL; - } - - /* cam_lock/open_count protects us from simultaneous opens - * ... for now. we probably shouldn't rely on this fact forever. - */ - - mutex_lock(&cam->cam_lock); - if (cam->open_count > 0) { - printk(KERN_INFO - "vicam_open called on already opened camera"); - mutex_unlock(&cam->cam_lock); - return -EBUSY; - } - - cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); - if (!cam->raw_image) { - mutex_unlock(&cam->cam_lock); - return -ENOMEM; - } - - cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - if (!cam->framebuf) { - kfree(cam->raw_image); - mutex_unlock(&cam->cam_lock); - return -ENOMEM; - } - - cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!cam->cntrlbuf) { - kfree(cam->raw_image); - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - mutex_unlock(&cam->cam_lock); - return -ENOMEM; - } - - cam->needsDummyRead = 1; - cam->open_count++; - - file->private_data = cam; - mutex_unlock(&cam->cam_lock); - - - // First upload firmware, then turn the camera on - - if (!cam->is_initialized) { - initialize_camera(cam); - - cam->is_initialized = 1; - } - - set_camera_power(cam, 1); - - return 0; -} - -static int -vicam_close(struct file *file) -{ - struct vicam_camera *cam = file->private_data; - int open_count; - struct usb_device *udev; - - DBG("close\n"); - - /* it's not the end of the world if - * we fail to turn the camera off. - */ - - set_camera_power(cam, 0); - - kfree(cam->raw_image); - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - kfree(cam->cntrlbuf); - - mutex_lock(&cam->cam_lock); - - cam->open_count--; - open_count = cam->open_count; - udev = cam->udev; - - mutex_unlock(&cam->cam_lock); - - if (!open_count && !udev) { - kfree(cam); - } - - return 0; -} - -static void vicam_decode_color(const u8 *data, u8 *rgb) -{ - /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB - * Copyright (C) 2002 Monroe Williams (monroe@pobox.com) - */ - - int i, prevY, nextY; - - prevY = 512; - nextY = 512; - - data += VICAM_HEADER_SIZE; - - for( i = 0; i < 240; i++, data += 512 ) { - const int y = ( i * 242 ) / 240; - - int j, prevX, nextX; - int Y, Cr, Cb; - - if ( y == 242 - 1 ) { - nextY = -512; - } - - prevX = 1; - nextX = 1; - - for ( j = 0; j < 320; j++, rgb += 3 ) { - const int x = ( j * 512 ) / 320; - const u8 * const src = &data[x]; - - if ( x == 512 - 1 ) { - nextX = -1; - } - - Cr = ( src[prevX] - src[0] ) + - ( src[nextX] - src[0] ); - Cr /= 2; - - Cb = ( src[prevY] - src[prevX + prevY] ) + - ( src[prevY] - src[nextX + prevY] ) + - ( src[nextY] - src[prevX + nextY] ) + - ( src[nextY] - src[nextX + nextY] ); - Cb /= 4; - - Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 ); - - if ( i & 1 ) { - int Ct = Cr; - Cr = Cb; - Cb = Ct; - } - - if ( ( x ^ i ) & 1 ) { - Cr = -Cr; - Cb = -Cb; - } - - rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) + - 500 ) / 900, 0, 255 ); - rgb[1] = clamp( ( ( Y - ( 392 * Cb ) - - ( 813 * Cr ) ) + - 500 ) / 1000, 0, 255 ); - rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) + - 500 ) / 1300, 0, 255 ); - - prevX = -1; - } - - prevY = -512; - } -} - -static void -read_frame(struct vicam_camera *cam, int framenum) -{ - unsigned char *request = cam->cntrlbuf; - int realShutter; - int n; - int actual_length; - - if (cam->needsDummyRead) { - cam->needsDummyRead = 0; - read_frame(cam, framenum); - } - - memset(request, 0, 16); - request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain - - request[1] = 0; // 512x242 capture - - request[2] = 0x90; // the function of these two bytes - request[3] = 0x07; // is not yet understood - - if (cam->shutter_speed > 60) { - // Short exposure - realShutter = - ((-15631900 / cam->shutter_speed) + 260533) / 1000; - request[4] = realShutter & 0xFF; - request[5] = (realShutter >> 8) & 0xFF; - request[6] = 0x03; - request[7] = 0x01; - } else { - // Long exposure - realShutter = 15600 / cam->shutter_speed - 1; - request[4] = 0; - request[5] = 0; - request[6] = realShutter & 0xFF; - request[7] = realShutter >> 8; - } - - // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0 - request[8] = 0; - // bytes 9-15 do not seem to affect exposure or image quality - - mutex_lock(&cam->cam_lock); - - if (!cam->udev) { - goto done; - } - - n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); - - if (n < 0) { - printk(KERN_ERR - " Problem sending frame capture control message"); - goto done; - } - - n = usb_bulk_msg(cam->udev, - usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), - cam->raw_image, - 512 * 242 + 128, &actual_length, 10000); - - if (n < 0) { - printk(KERN_ERR "Problem during bulk read of frame data: %d\n", - n); - } - - done: - mutex_unlock(&cam->cam_lock); -} - -static ssize_t -vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ) -{ - struct vicam_camera *cam = file->private_data; - - DBG("read %d bytes.\n", (int) count); - - if (*ppos >= VICAM_MAX_FRAME_SIZE) { - *ppos = 0; - return 0; - } - - if (*ppos == 0) { - read_frame(cam, 0); - vicam_decode_color(cam->raw_image, - cam->framebuf + - 0 * VICAM_MAX_FRAME_SIZE); - } - - count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); - - if (copy_to_user(buf, &cam->framebuf[*ppos], count)) { - count = -EFAULT; - } else { - *ppos += count; - } - - if (count == VICAM_MAX_FRAME_SIZE) { - *ppos = 0; - } - - return count; -} - - -static int -vicam_mmap(struct file *file, struct vm_area_struct *vma) -{ - // TODO: allocate the raw frame buffer if necessary - unsigned long page, pos; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - struct vicam_camera *cam = file->private_data; - - if (!cam) - return -ENODEV; - - DBG("vicam_mmap: %ld\n", size); - - /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes - * to the size the application requested for mmap and it was screwing apps up. - if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) - return -EINVAL; - */ - - pos = (unsigned long)cam->framebuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -static const struct v4l2_file_operations vicam_fops = { - .owner = THIS_MODULE, - .open = vicam_open, - .release = vicam_close, - .read = vicam_read, - .mmap = vicam_mmap, - .ioctl = vicam_ioctl, -}; - -static struct video_device vicam_template = { - .name = "ViCam-based USB Camera", - .fops = &vicam_fops, - .release = video_device_release_empty, -}; - -/* table of devices that work with this driver */ -static struct usb_device_id vicam_table[] = { - {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, - {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)}, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, vicam_table); - -static struct usb_driver vicam_driver = { - .name = "vicam", - .probe = vicam_probe, - .disconnect = vicam_disconnect, - .id_table = vicam_table -}; - -/** - * vicam_probe - * @intf: the interface - * @id: the device id - * - * Called by the usb core when a new device is connected that it thinks - * this driver might be interested in. - */ -static int -vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - int bulkEndpoint = 0; - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - struct vicam_camera *cam; - - printk(KERN_INFO "ViCam based webcam connected\n"); - - interface = intf->cur_altsetting; - - DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", - interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); - endpoint = &interface->endpoint[0].desc; - - if (usb_endpoint_is_bulk_in(endpoint)) { - /* we found a bulk in endpoint */ - bulkEndpoint = endpoint->bEndpointAddress; - } else { - printk(KERN_ERR - "No bulk in endpoint was found ?! (this is bad)\n"); - } - - if ((cam = - kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { - printk(KERN_WARNING - "could not allocate kernel memory for vicam_camera struct\n"); - return -ENOMEM; - } - - - cam->shutter_speed = 15; - - mutex_init(&cam->cam_lock); - - memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template)); - video_set_drvdata(&cam->vdev, cam); - - cam->udev = dev; - cam->bulkEndpoint = bulkEndpoint; - - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) { - kfree(cam); - printk(KERN_WARNING "video_register_device failed\n"); - return -EIO; - } - - printk(KERN_INFO "ViCam webcam driver now controlling device %s\n", - video_device_node_name(&cam->vdev)); - - usb_set_intfdata (intf, cam); - - return 0; -} - -static void -vicam_disconnect(struct usb_interface *intf) -{ - int open_count; - struct vicam_camera *cam = usb_get_intfdata (intf); - usb_set_intfdata (intf, NULL); - - /* we must unregister the device before taking its - * cam_lock. This is because the video open call - * holds the same lock as video unregister. if we - * unregister inside of the cam_lock and open also - * uses the cam_lock, we get deadlock. - */ - - video_unregister_device(&cam->vdev); - - /* stop the camera from being used */ - - mutex_lock(&cam->cam_lock); - - /* mark the camera as gone */ - - cam->udev = NULL; - - /* the only thing left to do is synchronize with - * our close/release function on who should release - * the camera memory. if there are any users using the - * camera, it's their job. if there are no users, - * it's ours. - */ - - open_count = cam->open_count; - - mutex_unlock(&cam->cam_lock); - - if (!open_count) { - kfree(cam); - } - - printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); -} - -/* - */ -static int __init -usb_vicam_init(void) -{ - int retval; - DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); - retval = usb_register(&vicam_driver); - if (retval) - printk(KERN_WARNING "usb_register failed!\n"); - return retval; -} - -static void __exit -usb_vicam_exit(void) -{ - DBG(KERN_INFO - "ViCam-based WebCam driver shutdown\n"); - - usb_deregister(&vicam_driver); -} - -module_init(usb_vicam_init); -module_exit(usb_vicam_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("vicam/firmware.fw"); diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index 503b13beb92..68b998bd203 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c @@ -32,1072 +32,1072 @@ /* Supported Devices: A table for usbvision.c*/ struct usbvision_device_data_st usbvision_device_data[] = { [XANBOO] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 4, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Xanboo", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 4, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "Xanboo", }, [BELKIN_VIDEOBUS_II] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Belkin USB VideoBus II Adapter", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Belkin USB VideoBus II Adapter", }, [BELKIN_VIDEOBUS] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Belkin Components USB VideoBus", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "Belkin Components USB VideoBus", }, [BELKIN_USB_VIDEOBUS_II] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Belkin USB VideoBus II", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Belkin USB VideoBus II", }, [ECHOFX_INTERVIEW_LITE] = { - .Interface = 0, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "echoFX InterView Lite", + .interface = 0, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "echoFX InterView Lite", }, [USBGEAR_USBG_V1] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "USBGear USBG-V1 resp. HAMA USB", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "USBGear USBG-V1 resp. HAMA USB", }, [D_LINK_V100] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 4, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "D-Link V100", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 4, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "D-Link V100", }, [X10_USB_CAMERA] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "X10 USB Camera", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "X10 USB Camera", }, [HPG_WINTV_LIVE_PAL_BG] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Live (PAL B/G)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Live (PAL B/G)", }, [HPG_WINTV_LIVE_PRO_NTSC_MN] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Live Pro (NTSC M/N)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Live Pro (NTSC M/N)", }, [ZORAN_PMD_NOGATECH] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 2, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 2, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan", }, [NOGATECH_USB_TV_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = 20, - .ModelString = "Nogatech USB-TV (NTSC) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = 20, + .model_string = "Nogatech USB-TV (NTSC) FM", }, [PNY_USB_TV_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = 20, - .ModelString = "PNY USB-TV (NTSC) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = 20, + .model_string = "PNY USB-TV (NTSC) FM", }, [PV_PLAYTV_USB_PRO_PAL_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "PixelView PlayTv-USB PRO (PAL) FM", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "PixelView PlayTv-USB PRO (PAL) FM", }, [ZT_721] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "ZTV ZT-721 2.4GHz USB A/V Receiver", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "ZTV ZT-721 2.4GHz USB A/V Receiver", }, [HPG_WINTV_NTSC_MN] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = 20, - .ModelString = "Hauppauge WinTV USB (NTSC M/N)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = 20, + .model_string = "Hauppauge WinTV USB (NTSC M/N)", }, [HPG_WINTV_PAL_BG] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL B/G)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL B/G)", }, [HPG_WINTV_PAL_I] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL I)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL I)", }, [HPG_WINTV_PAL_SECAM_L] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0x80, - .Y_Offset = 0x16, - .ModelString = "Hauppauge WinTV USB (PAL/SECAM L)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0x80, + .y_offset = 0x16, + .model_string = "Hauppauge WinTV USB (PAL/SECAM L)", }, [HPG_WINTV_PAL_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL D/K)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL D/K)", }, [HPG_WINTV_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (NTSC FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (NTSC FM)", }, [HPG_WINTV_PAL_BG_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL B/G FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL B/G FM)", }, [HPG_WINTV_PAL_I_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL I FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL I FM)", }, [HPG_WINTV_PAL_D_K_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL D/K FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL D/K FM)", }, [HPG_WINTV_PRO_NTSC_MN] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N)", }, [HPG_WINTV_PRO_NTSC_MN_V2] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N) V2", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N) V2", }, [HPG_WINTV_PRO_PAL] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_FM1216ME_MK3, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)", }, [HPG_WINTV_PRO_NTSC_MN_V3] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N) V3", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N) V3", }, [HPG_WINTV_PRO_PAL_BG] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G)", }, [HPG_WINTV_PRO_PAL_I] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL I)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL I)", }, [HPG_WINTV_PRO_PAL_SECAM_L] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM L)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM L)", }, [HPG_WINTV_PRO_PAL_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL D/K)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL D/K)", }, [HPG_WINTV_PRO_PAL_SECAM] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)", }, [HPG_WINTV_PRO_PAL_SECAM_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2", }, [HPG_WINTV_PRO_PAL_BG_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_ALPS_TSBE1_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G) V2", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_ALPS_TSBE1_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G) V2", }, [HPG_WINTV_PRO_PAL_BG_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_ALPS_TSBE1_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G,D/K)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_ALPS_TSBE1_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G,D/K)", }, [HPG_WINTV_PRO_PAL_I_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_LG_PAL_NEW_TAPC, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL I,D/K)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL I,D/K)", }, [HPG_WINTV_PRO_NTSC_MN_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N FM)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N FM)", }, [HPG_WINTV_PRO_PAL_BG_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G FM)", }, [HPG_WINTV_PRO_PAL_I_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL I FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL I FM)", }, [HPG_WINTV_PRO_PAL_D_K_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL D/K FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL D/K FM)", }, [HPG_WINTV_PRO_TEMIC_PAL_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)", }, [HPG_WINTV_PRO_TEMIC_PAL_BG_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)", }, [HPG_WINTV_PRO_PAL_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_FM1216ME_MK3, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)", }, [HPG_WINTV_PRO_NTSC_MN_FM_V2] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2", }, [CAMTEL_TVB330] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 5, - .Y_Offset = 5, - .ModelString = "Camtel Technology USB TV Genie Pro FM Model TVB330", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 5, + .y_offset = 5, + .model_string = "Camtel Technology USB TV Genie Pro FM Model TVB330", }, [DIGITAL_VIDEO_CREATOR_I] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Digital Video Creator I", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Digital Video Creator I", }, [GLOBAL_VILLAGE_GV_007_NTSC] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 82, - .Y_Offset = 20, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Global Village GV-007 (NTSC)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 82, + .y_offset = 20, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Global Village GV-007 (NTSC)", }, [DAZZLE_DVC_50_REV_1_NTSC] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)", }, [DAZZLE_DVC_80_REV_1_PAL] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)", }, [DAZZLE_DVC_90_REV_1_SECAM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)", }, [ESKAPE_LABS_MYTV2GO] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_FM1216ME_MK3, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Eskape Labs MyTV2Go", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Eskape Labs MyTV2Go", }, [PINNA_PCTV_USB_PAL] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 0, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4066FY5_PAL_I, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (PAL)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 0, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4066FY5_PAL_I, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (PAL)", }, [PINNA_PCTV_USB_SECAM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (SECAM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (SECAM)", }, [PINNA_PCTV_USB_PAL_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 128, - .Y_Offset = 23, - .ModelString = "Pinnacle Studio PCTV USB (PAL) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 128, + .y_offset = 23, + .model_string = "Pinnacle Studio PCTV USB (PAL) FM", }, [MIRO_PCTV_USB] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Miro PCTV USB", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Miro PCTV USB", }, [PINNA_PCTV_USB_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (NTSC) FM", }, [PINNA_PCTV_USB_NTSC_FM_V3] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM V3", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (NTSC) FM V3", }, [PINNA_PCTV_USB_PAL_FM_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4009FR5_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio PCTV USB (PAL) FM V2", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio PCTV USB (PAL) FM V2", }, [PINNA_PCTV_USB_NTSC_FM_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4039FR5_NTSC, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM V2", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4039FR5_NTSC, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio PCTV USB (NTSC) FM V2", }, [PINNA_PCTV_USB_PAL_FM_V3] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4009FR5_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio PCTV USB (PAL) FM V3", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio PCTV USB (PAL) FM V3", }, [PINNA_LINX_VD_IN_CAB_NTSC] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio Linx Video input cable (NTSC)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio Linx Video input cable (NTSC)", }, [PINNA_LINX_VD_IN_CAB_PAL] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio Linx Video input cable (PAL)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio Linx Video input cable (PAL)", }, [PINNA_PCTV_BUNGEE_PAL_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4009FR5_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle PCTV Bungee USB (PAL) FM", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle PCTV Bungee USB (PAL) FM", }, [HPG_WINTV] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTv-USB", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTv-USB", }, }; -const int usbvision_device_data_size=ARRAY_SIZE(usbvision_device_data); +const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); /* Supported Devices */ -struct usb_device_id usbvision_table [] = { - { USB_DEVICE(0x0a6f, 0x0400), .driver_info=XANBOO }, - { USB_DEVICE(0x050d, 0x0106), .driver_info=BELKIN_VIDEOBUS_II }, - { USB_DEVICE(0x050d, 0x0207), .driver_info=BELKIN_VIDEOBUS }, - { USB_DEVICE(0x050d, 0x0208), .driver_info=BELKIN_USB_VIDEOBUS_II }, - { USB_DEVICE(0x0571, 0x0002), .driver_info=ECHOFX_INTERVIEW_LITE }, - { USB_DEVICE(0x0573, 0x0003), .driver_info=USBGEAR_USBG_V1 }, - { USB_DEVICE(0x0573, 0x0400), .driver_info=D_LINK_V100 }, - { USB_DEVICE(0x0573, 0x2000), .driver_info=X10_USB_CAMERA }, - { USB_DEVICE(0x0573, 0x2d00), .driver_info=HPG_WINTV_LIVE_PAL_BG }, - { USB_DEVICE(0x0573, 0x2d01), .driver_info=HPG_WINTV_LIVE_PRO_NTSC_MN }, - { USB_DEVICE(0x0573, 0x2101), .driver_info=ZORAN_PMD_NOGATECH }, - { USB_DEVICE(0x0573, 0x4100), .driver_info=NOGATECH_USB_TV_NTSC_FM }, - { USB_DEVICE(0x0573, 0x4110), .driver_info=PNY_USB_TV_NTSC_FM }, - { USB_DEVICE(0x0573, 0x4450), .driver_info=PV_PLAYTV_USB_PRO_PAL_FM }, - { USB_DEVICE(0x0573, 0x4550), .driver_info=ZT_721 }, - { USB_DEVICE(0x0573, 0x4d00), .driver_info=HPG_WINTV_NTSC_MN }, - { USB_DEVICE(0x0573, 0x4d01), .driver_info=HPG_WINTV_PAL_BG }, - { USB_DEVICE(0x0573, 0x4d02), .driver_info=HPG_WINTV_PAL_I }, - { USB_DEVICE(0x0573, 0x4d03), .driver_info=HPG_WINTV_PAL_SECAM_L }, - { USB_DEVICE(0x0573, 0x4d04), .driver_info=HPG_WINTV_PAL_D_K }, - { USB_DEVICE(0x0573, 0x4d10), .driver_info=HPG_WINTV_NTSC_FM }, - { USB_DEVICE(0x0573, 0x4d11), .driver_info=HPG_WINTV_PAL_BG_FM }, - { USB_DEVICE(0x0573, 0x4d12), .driver_info=HPG_WINTV_PAL_I_FM }, - { USB_DEVICE(0x0573, 0x4d14), .driver_info=HPG_WINTV_PAL_D_K_FM }, - { USB_DEVICE(0x0573, 0x4d2a), .driver_info=HPG_WINTV_PRO_NTSC_MN }, - { USB_DEVICE(0x0573, 0x4d2b), .driver_info=HPG_WINTV_PRO_NTSC_MN_V2 }, - { USB_DEVICE(0x0573, 0x4d2c), .driver_info=HPG_WINTV_PRO_PAL }, +struct usb_device_id usbvision_table[] = { + { USB_DEVICE(0x0a6f, 0x0400), .driver_info = XANBOO }, + { USB_DEVICE(0x050d, 0x0106), .driver_info = BELKIN_VIDEOBUS_II }, + { USB_DEVICE(0x050d, 0x0207), .driver_info = BELKIN_VIDEOBUS }, + { USB_DEVICE(0x050d, 0x0208), .driver_info = BELKIN_USB_VIDEOBUS_II }, + { USB_DEVICE(0x0571, 0x0002), .driver_info = ECHOFX_INTERVIEW_LITE }, + { USB_DEVICE(0x0573, 0x0003), .driver_info = USBGEAR_USBG_V1 }, + { USB_DEVICE(0x0573, 0x0400), .driver_info = D_LINK_V100 }, + { USB_DEVICE(0x0573, 0x2000), .driver_info = X10_USB_CAMERA }, + { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, + { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, + { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, + { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM }, + { USB_DEVICE(0x0573, 0x4550), .driver_info = ZT_721 }, + { USB_DEVICE(0x0573, 0x4d00), .driver_info = HPG_WINTV_NTSC_MN }, + { USB_DEVICE(0x0573, 0x4d01), .driver_info = HPG_WINTV_PAL_BG }, + { USB_DEVICE(0x0573, 0x4d02), .driver_info = HPG_WINTV_PAL_I }, + { USB_DEVICE(0x0573, 0x4d03), .driver_info = HPG_WINTV_PAL_SECAM_L }, + { USB_DEVICE(0x0573, 0x4d04), .driver_info = HPG_WINTV_PAL_D_K }, + { USB_DEVICE(0x0573, 0x4d10), .driver_info = HPG_WINTV_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4d11), .driver_info = HPG_WINTV_PAL_BG_FM }, + { USB_DEVICE(0x0573, 0x4d12), .driver_info = HPG_WINTV_PAL_I_FM }, + { USB_DEVICE(0x0573, 0x4d14), .driver_info = HPG_WINTV_PAL_D_K_FM }, + { USB_DEVICE(0x0573, 0x4d2a), .driver_info = HPG_WINTV_PRO_NTSC_MN }, + { USB_DEVICE(0x0573, 0x4d2b), .driver_info = HPG_WINTV_PRO_NTSC_MN_V2 }, + { USB_DEVICE(0x0573, 0x4d2c), .driver_info = HPG_WINTV_PRO_PAL }, { USB_DEVICE(0x0573, 0x4d20), .driver_info = HPG_WINTV_PRO_NTSC_MN_V3 }, - { USB_DEVICE(0x0573, 0x4d21), .driver_info=HPG_WINTV_PRO_PAL_BG }, - { USB_DEVICE(0x0573, 0x4d22), .driver_info=HPG_WINTV_PRO_PAL_I }, - { USB_DEVICE(0x0573, 0x4d23), .driver_info=HPG_WINTV_PRO_PAL_SECAM_L }, - { USB_DEVICE(0x0573, 0x4d24), .driver_info=HPG_WINTV_PRO_PAL_D_K }, - { USB_DEVICE(0x0573, 0x4d25), .driver_info=HPG_WINTV_PRO_PAL_SECAM }, - { USB_DEVICE(0x0573, 0x4d26), .driver_info=HPG_WINTV_PRO_PAL_SECAM_V2 }, - { USB_DEVICE(0x0573, 0x4d27), .driver_info=HPG_WINTV_PRO_PAL_BG_V2 }, - { USB_DEVICE(0x0573, 0x4d28), .driver_info=HPG_WINTV_PRO_PAL_BG_D_K }, - { USB_DEVICE(0x0573, 0x4d29), .driver_info=HPG_WINTV_PRO_PAL_I_D_K }, - { USB_DEVICE(0x0573, 0x4d30), .driver_info=HPG_WINTV_PRO_NTSC_MN_FM }, - { USB_DEVICE(0x0573, 0x4d31), .driver_info=HPG_WINTV_PRO_PAL_BG_FM }, - { USB_DEVICE(0x0573, 0x4d32), .driver_info=HPG_WINTV_PRO_PAL_I_FM }, - { USB_DEVICE(0x0573, 0x4d34), .driver_info=HPG_WINTV_PRO_PAL_D_K_FM }, - { USB_DEVICE(0x0573, 0x4d35), .driver_info=HPG_WINTV_PRO_TEMIC_PAL_FM }, - { USB_DEVICE(0x0573, 0x4d36), .driver_info=HPG_WINTV_PRO_TEMIC_PAL_BG_FM }, - { USB_DEVICE(0x0573, 0x4d37), .driver_info=HPG_WINTV_PRO_PAL_FM }, - { USB_DEVICE(0x0573, 0x4d38), .driver_info=HPG_WINTV_PRO_NTSC_MN_FM_V2 }, - { USB_DEVICE(0x0768, 0x0006), .driver_info=CAMTEL_TVB330 }, - { USB_DEVICE(0x07d0, 0x0001), .driver_info=DIGITAL_VIDEO_CREATOR_I }, - { USB_DEVICE(0x07d0, 0x0002), .driver_info=GLOBAL_VILLAGE_GV_007_NTSC }, - { USB_DEVICE(0x07d0, 0x0003), .driver_info=DAZZLE_DVC_50_REV_1_NTSC }, - { USB_DEVICE(0x07d0, 0x0004), .driver_info=DAZZLE_DVC_80_REV_1_PAL }, - { USB_DEVICE(0x07d0, 0x0005), .driver_info=DAZZLE_DVC_90_REV_1_SECAM }, - { USB_DEVICE(0x07f8, 0x9104), .driver_info=ESKAPE_LABS_MYTV2GO }, - { USB_DEVICE(0x2304, 0x010d), .driver_info=PINNA_PCTV_USB_PAL }, - { USB_DEVICE(0x2304, 0x0109), .driver_info=PINNA_PCTV_USB_SECAM }, - { USB_DEVICE(0x2304, 0x0110), .driver_info=PINNA_PCTV_USB_PAL_FM }, - { USB_DEVICE(0x2304, 0x0111), .driver_info=MIRO_PCTV_USB }, - { USB_DEVICE(0x2304, 0x0112), .driver_info=PINNA_PCTV_USB_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4d21), .driver_info = HPG_WINTV_PRO_PAL_BG }, + { USB_DEVICE(0x0573, 0x4d22), .driver_info = HPG_WINTV_PRO_PAL_I }, + { USB_DEVICE(0x0573, 0x4d23), .driver_info = HPG_WINTV_PRO_PAL_SECAM_L }, + { USB_DEVICE(0x0573, 0x4d24), .driver_info = HPG_WINTV_PRO_PAL_D_K }, + { USB_DEVICE(0x0573, 0x4d25), .driver_info = HPG_WINTV_PRO_PAL_SECAM }, + { USB_DEVICE(0x0573, 0x4d26), .driver_info = HPG_WINTV_PRO_PAL_SECAM_V2 }, + { USB_DEVICE(0x0573, 0x4d27), .driver_info = HPG_WINTV_PRO_PAL_BG_V2 }, + { USB_DEVICE(0x0573, 0x4d28), .driver_info = HPG_WINTV_PRO_PAL_BG_D_K }, + { USB_DEVICE(0x0573, 0x4d29), .driver_info = HPG_WINTV_PRO_PAL_I_D_K }, + { USB_DEVICE(0x0573, 0x4d30), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM }, + { USB_DEVICE(0x0573, 0x4d31), .driver_info = HPG_WINTV_PRO_PAL_BG_FM }, + { USB_DEVICE(0x0573, 0x4d32), .driver_info = HPG_WINTV_PRO_PAL_I_FM }, + { USB_DEVICE(0x0573, 0x4d34), .driver_info = HPG_WINTV_PRO_PAL_D_K_FM }, + { USB_DEVICE(0x0573, 0x4d35), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_FM }, + { USB_DEVICE(0x0573, 0x4d36), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_BG_FM }, + { USB_DEVICE(0x0573, 0x4d37), .driver_info = HPG_WINTV_PRO_PAL_FM }, + { USB_DEVICE(0x0573, 0x4d38), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM_V2 }, + { USB_DEVICE(0x0768, 0x0006), .driver_info = CAMTEL_TVB330 }, + { USB_DEVICE(0x07d0, 0x0001), .driver_info = DIGITAL_VIDEO_CREATOR_I }, + { USB_DEVICE(0x07d0, 0x0002), .driver_info = GLOBAL_VILLAGE_GV_007_NTSC }, + { USB_DEVICE(0x07d0, 0x0003), .driver_info = DAZZLE_DVC_50_REV_1_NTSC }, + { USB_DEVICE(0x07d0, 0x0004), .driver_info = DAZZLE_DVC_80_REV_1_PAL }, + { USB_DEVICE(0x07d0, 0x0005), .driver_info = DAZZLE_DVC_90_REV_1_SECAM }, + { USB_DEVICE(0x07f8, 0x9104), .driver_info = ESKAPE_LABS_MYTV2GO }, + { USB_DEVICE(0x2304, 0x010d), .driver_info = PINNA_PCTV_USB_PAL }, + { USB_DEVICE(0x2304, 0x0109), .driver_info = PINNA_PCTV_USB_SECAM }, + { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM }, + { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB }, + { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM }, { USB_DEVICE(0x2304, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, - { USB_DEVICE(0x2304, 0x0210), .driver_info=PINNA_PCTV_USB_PAL_FM_V2 }, - { USB_DEVICE(0x2304, 0x0212), .driver_info=PINNA_PCTV_USB_NTSC_FM_V2 }, - { USB_DEVICE(0x2304, 0x0214), .driver_info=PINNA_PCTV_USB_PAL_FM_V3 }, - { USB_DEVICE(0x2304, 0x0300), .driver_info=PINNA_LINX_VD_IN_CAB_NTSC }, - { USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL }, - { USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM }, - { USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV }, + { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, + { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, + { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, + { USB_DEVICE(0x2304, 0x0300), .driver_info = PINNA_LINX_VD_IN_CAB_NTSC }, + { USB_DEVICE(0x2304, 0x0301), .driver_info = PINNA_LINX_VD_IN_CAB_PAL }, + { USB_DEVICE(0x2304, 0x0419), .driver_info = PINNA_PCTV_BUNGEE_PAL_FM }, + { USB_DEVICE(0x2400, 0x4200), .driver_info = HPG_WINTV }, { }, /* terminate list */ }; -MODULE_DEVICE_TABLE (usb, usbvision_table); +MODULE_DEVICE_TABLE(usb, usbvision_table); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index b9dd74fde21..c8feb0d6fcc 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -33,7 +33,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/spinlock.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/videodev2.h> #include <linux/i2c.h> @@ -46,30 +46,30 @@ #include "usbvision.h" static unsigned int core_debug; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); +module_param(core_debug, int, 0644); +MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); static unsigned int force_testpattern; -module_param(force_testpattern,int,0644); -MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); +module_param(force_testpattern, int, 0644); +MODULE_PARM_DESC(force_testpattern, "enable test pattern display [core]"); -static int adjustCompression = 1; /* Set the compression to be adaptive */ -module_param(adjustCompression, int, 0444); -MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); +static int adjust_compression = 1; /* Set the compression to be adaptive */ +module_param(adjust_compression, int, 0444); +MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device. Default: 1 (On)"); /* To help people with Black and White output with using s-video input. * Some cables and input device are wired differently. */ -static int SwitchSVideoInput; -module_param(SwitchSVideoInput, int, 0444); -MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); +static int switch_svideo_input; +module_param(switch_svideo_input, int, 0444); +MODULE_PARM_DESC(switch_svideo_input, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); -static unsigned int adjust_X_Offset = -1; -module_param(adjust_X_Offset, int, 0644); -MODULE_PARM_DESC(adjust_X_Offset, "adjust X offset display [core]"); +static unsigned int adjust_x_offset = -1; +module_param(adjust_x_offset, int, 0644); +MODULE_PARM_DESC(adjust_x_offset, "adjust X offset display [core]"); -static unsigned int adjust_Y_Offset = -1; -module_param(adjust_Y_Offset, int, 0644); -MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); +static unsigned int adjust_y_offset = -1; +module_param(adjust_y_offset, int, 0644); +MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]"); #define ENABLE_HEXDUMP 0 /* Enable if you need it */ @@ -82,15 +82,15 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); __func__, __LINE__ , ## args); \ } #else - #define PDEBUG(level, fmt, args...) do {} while(0) + #define PDEBUG(level, fmt, args...) do {} while (0) #endif -#define DBG_HEADER 1<<0 -#define DBG_IRQ 1<<1 -#define DBG_ISOC 1<<2 -#define DBG_PARSE 1<<3 -#define DBG_SCRATCH 1<<4 -#define DBG_FUNC 1<<5 +#define DBG_HEADER (1 << 0) +#define DBG_IRQ (1 << 1) +#define DBG_ISOC (1 << 2) +#define DBG_PARSE (1 << 3) +#define DBG_SCRATCH (1 << 4) +#define DBG_FUNC (1 << 5) static const int max_imgwidth = MAX_FRAME_WIDTH; static const int max_imgheight = MAX_FRAME_HEIGHT; @@ -103,14 +103,14 @@ static const int min_imgheight = MIN_FRAME_HEIGHT; * to work with. This setting can be adjusted, but the default value * should be OK for most desktop users. */ -#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer +#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) /* 128kB memory scratch buffer */ static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; -// Function prototypes -static int usbvision_request_intra (struct usb_usbvision *usbvision); -static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); -static int usbvision_adjust_compression (struct usb_usbvision *usbvision); -static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); +/* Function prototypes */ +static int usbvision_request_intra(struct usb_usbvision *usbvision); +static int usbvision_unrequest_intra(struct usb_usbvision *usbvision); +static int usbvision_adjust_compression(struct usb_usbvision *usbvision); +static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision); /*******************************/ /* Memory management functions */ @@ -176,19 +176,19 @@ static void usbvision_hexdump(const unsigned char *data, int len) k += sprintf(&tmp[k], "%02x ", data[i]); } if (k > 0) - printk("%s\n", tmp); + printk(KERN_CONT "%s\n", tmp); } #endif /******************************** * scratch ring buffer handling ********************************/ -static int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */ +static int scratch_len(struct usb_usbvision *usbvision) /* This returns the amount of data actually in the buffer */ { int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; - if (len < 0) { + + if (len < 0) len += scratch_buf_size; - } PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); return len; @@ -199,9 +199,8 @@ static int scratch_len(struct usb_usbvision *usbvision) /*This returns the am static int scratch_free(struct usb_usbvision *usbvision) { int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; - if (free <= 0) { + if (free <= 0) free += scratch_buf_size; - } if (free) { free -= 1; /* at least one byte in the buffer must */ /* left blank, otherwise there is no chance to differ between full and empty */ @@ -221,14 +220,12 @@ static int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, if (usbvision->scratch_write_ptr + len < scratch_buf_size) { memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); usbvision->scratch_write_ptr += len; - } - else { + } else { len_part = scratch_buf_size - usbvision->scratch_write_ptr; memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); if (len == len_part) { usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ - } - else { + } else { memcpy(usbvision->scratch, data + len_part, len - len_part); usbvision->scratch_write_ptr = len - len_part; } @@ -255,17 +252,16 @@ static int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len) { int len_part; + if (*ptr + len < scratch_buf_size) { memcpy(data, usbvision->scratch + *ptr, len); *ptr += len; - } - else { + } else { len_part = scratch_buf_size - *ptr; memcpy(data, usbvision->scratch + *ptr, len_part); if (len == len_part) { *ptr = 0; /* just set the y_ptr to zero */ - } - else { + } else { memcpy(data + len_part, usbvision->scratch, len - len_part); *ptr = len - len_part; } @@ -281,13 +277,13 @@ static int scratch_get_extra(struct usb_usbvision *usbvision, static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len) { - *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size; + *ptr = (usbvision->scratch_read_ptr + len) % scratch_buf_size; PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); } -/*This increments the scratch extra read pointer */ +/* This increments the scratch extra read pointer */ static void scratch_inc_extra_ptr(int *ptr, int len) { *ptr = (*ptr + len) % scratch_buf_size; @@ -301,17 +297,16 @@ static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len) { int len_part; + if (usbvision->scratch_read_ptr + len < scratch_buf_size) { memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); usbvision->scratch_read_ptr += len; - } - else { + } else { len_part = scratch_buf_size - usbvision->scratch_read_ptr; memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); if (len == len_part) { usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ - } - else { + } else { memcpy(data + len_part, usbvision->scratch, len - len_part); usbvision->scratch_read_ptr = len - len_part; } @@ -327,7 +322,7 @@ static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, static int scratch_get_header(struct usb_usbvision *usbvision, struct usbvision_frame_header *header) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); @@ -340,29 +335,28 @@ static int scratch_get_header(struct usb_usbvision *usbvision, scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); if ((header->magic_1 == USBVISION_MAGIC_1) && (header->magic_2 == USBVISION_MAGIC_2) - && (header->headerLength == USBVISION_HEADER_LENGTH)) { - errCode = USBVISION_HEADER_LENGTH; - header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8); - header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8); + && (header->header_length == USBVISION_HEADER_LENGTH)) { + err_code = USBVISION_HEADER_LENGTH; + header->frame_width = header->frame_width_lo + (header->frame_width_hi << 8); + header->frame_height = header->frame_height_lo + (header->frame_height_hi << 8); break; } } - return errCode; + return err_code; } -/*This removes len bytes of old data from the buffer */ +/* This removes len bytes of old data from the buffer */ static void scratch_rm_old(struct usb_usbvision *usbvision, int len) { - usbvision->scratch_read_ptr += len; usbvision->scratch_read_ptr %= scratch_buf_size; PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); } -/*This resets the buffer - kills all data in it too */ +/* This resets the buffer - kills all data in it too */ static void scratch_reset(struct usb_usbvision *usbvision) { PDEBUG(DBG_SCRATCH, "\n"); @@ -371,14 +365,14 @@ static void scratch_reset(struct usb_usbvision *usbvision) usbvision->scratch_write_ptr = 0; usbvision->scratch_headermarker_read_ptr = 0; usbvision->scratch_headermarker_write_ptr = 0; - usbvision->isocstate = IsocState_NoFrame; + usbvision->isocstate = isoc_state_no_frame; } int usbvision_scratch_alloc(struct usb_usbvision *usbvision) { usbvision->scratch = vmalloc_32(scratch_buf_size); scratch_reset(usbvision); - if(usbvision->scratch == NULL) { + if (usbvision->scratch == NULL) { dev_err(&usbvision->dev->dev, "%s: unable to allocate %d bytes for scratch\n", __func__, scratch_buf_size); @@ -391,7 +385,6 @@ void usbvision_scratch_free(struct usb_usbvision *usbvision) { vfree(usbvision->scratch); usbvision->scratch = NULL; - } /* @@ -420,13 +413,13 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, printk(KERN_ERR "%s: usbvision == NULL\n", proc); return; } - if (usbvision->curFrame == NULL) { - printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); + if (usbvision->cur_frame == NULL) { + printk(KERN_ERR "%s: usbvision->cur_frame is NULL.\n", proc); return; } /* Grab the current frame */ - frame = usbvision->curFrame; + frame = usbvision->cur_frame; /* Optionally start at the beginning */ if (fullframe) { @@ -473,10 +466,9 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, } } - frame->grabstate = FrameState_Done; + frame->grabstate = frame_state_done; frame->scanlength += scan_length; ++num_pass; - } /* @@ -487,8 +479,9 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, int usbvision_decompress_alloc(struct usb_usbvision *usbvision) { int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; - usbvision->IntraFrameBuffer = vmalloc_32(IFB_size); - if (usbvision->IntraFrameBuffer == NULL) { + + usbvision->intra_frame_buffer = vmalloc_32(IFB_size); + if (usbvision->intra_frame_buffer == NULL) { dev_err(&usbvision->dev->dev, "%s: unable to allocate %d for compr. frame buffer\n", __func__, IFB_size); @@ -504,8 +497,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision) */ void usbvision_decompress_free(struct usb_usbvision *usbvision) { - vfree(usbvision->IntraFrameBuffer); - usbvision->IntraFrameBuffer = NULL; + vfree(usbvision->intra_frame_buffer); + usbvision->intra_frame_buffer = NULL; } @@ -517,117 +510,111 @@ void usbvision_decompress_free(struct usb_usbvision *usbvision) * * Locate one of supported header markers in the scratch buffer. */ -static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) +static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) { struct usbvision_frame *frame; - int foundHeader = 0; + int found_header = 0; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; - while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { - // found header in scratch + while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) { + /* found header in scratch */ PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", - frame->isocHeader.magic_2, - frame->isocHeader.magic_1, - frame->isocHeader.headerLength, - frame->isocHeader.frameNum, - frame->isocHeader.framePhase, - frame->isocHeader.frameLatency, - frame->isocHeader.dataFormat, - frame->isocHeader.formatParam, - frame->isocHeader.frameWidth, - frame->isocHeader.frameHeight); - - if (usbvision->requestIntra) { - if (frame->isocHeader.formatParam & 0x80) { - foundHeader = 1; - usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time + frame->isoc_header.magic_2, + frame->isoc_header.magic_1, + frame->isoc_header.header_length, + frame->isoc_header.frame_num, + frame->isoc_header.frame_phase, + frame->isoc_header.frame_latency, + frame->isoc_header.data_format, + frame->isoc_header.format_param, + frame->isoc_header.frame_width, + frame->isoc_header.frame_height); + + if (usbvision->request_intra) { + if (frame->isoc_header.format_param & 0x80) { + found_header = 1; + usbvision->last_isoc_frame_num = -1; /* do not check for lost frames this time */ usbvision_unrequest_intra(usbvision); break; } - } - else { - foundHeader = 1; + } else { + found_header = 1; break; } } - if (foundHeader) { - frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; - frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; - frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; - } - else { // no header found + if (found_header) { + frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width; + frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height; + frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth) >> 3; + } else { /* no header found */ PDEBUG(DBG_HEADER, "skipping scratch data, no header"); scratch_reset(usbvision); - return ParseState_EndParse; + return parse_state_end_parse; } - // found header - if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) { - //check isocHeader.frameNum for lost frames - if (usbvision->lastIsocFrameNum >= 0) { - if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) { - // unexpected frame drop: need to request new intra frame - PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum); + /* found header */ + if (frame->isoc_header.data_format == ISOC_MODE_COMPRESS) { + /* check isoc_header.frame_num for lost frames */ + if (usbvision->last_isoc_frame_num >= 0) { + if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) { + /* unexpected frame drop: need to request new intra frame */ + PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num); usbvision_request_intra(usbvision); - return ParseState_NextFrame; + return parse_state_next_frame; } } - usbvision->lastIsocFrameNum = frame->isocHeader.frameNum; + usbvision->last_isoc_frame_num = frame->isoc_header.frame_num; } usbvision->header_count++; - frame->scanstate = ScanState_Lines; + frame->scanstate = scan_state_lines; frame->curline = 0; if (force_testpattern) { usbvision_testpattern(usbvision, 1, 1); - return ParseState_NextFrame; + return parse_state_next_frame; } - return ParseState_Continue; + return parse_state_continue; } -static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision, +static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvision, long *pcopylen) { volatile struct usbvision_frame *frame; unsigned char *f; int len; int i; - unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components - unsigned char rv, gv, bv; // RGB components + unsigned char yuyv[4] = { 180, 128, 10, 128 }; /* YUV components */ + unsigned char rv, gv, bv; /* RGB components */ int clipmask_index, bytes_per_pixel; int stretch_bytes, clipmask_add; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; f = frame->data + (frame->v4l2_linesize * frame->curline); /* Make sure there's enough data for the entire line */ - len = (frame->isocHeader.frameWidth * 2)+5; + len = (frame->isoc_header.frame_width * 2) + 5; if (scratch_len(usbvision) < len) { PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); - return ParseState_Out; + return parse_state_out; } - if ((frame->curline + 1) >= frame->frmheight) { - return ParseState_NextFrame; - } + if ((frame->curline + 1) >= frame->frmheight) + return parse_state_next_frame; bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; clipmask_index = frame->curline * MAX_FRAME_WIDTH; clipmask_add = usbvision->stretch_width; - for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) { - + for (i = 0; i < frame->frmwidth; i += (2 * usbvision->stretch_width)) { scratch_get(usbvision, &yuyv[0], 4); if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[0]; // Y - *f++ = yuyv[3]; // U - } - else { - + *f++ = yuyv[0]; /* Y */ + *f++ = yuyv[3]; /* U */ + } else { YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); switch (frame->v4l2_format.format) { case V4L2_PIX_FMT_RGB565: @@ -659,11 +646,9 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision f += stretch_bytes; if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[2]; // Y - *f++ = yuyv[1]; // V - } - else { - + *f++ = yuyv[2]; /* Y */ + *f++ = yuyv[1]; /* V */ + } else { YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); switch (frame->v4l2_format.format) { case V4L2_PIX_FMT_RGB565: @@ -698,100 +683,94 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision frame->curline += usbvision->stretch_height; *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; - if (frame->curline >= frame->frmheight) { - return ParseState_NextFrame; - } - else { - return ParseState_Continue; - } + if (frame->curline >= frame->frmheight) + return parse_state_next_frame; + return parse_state_continue; } /* The decompression routine */ -static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed, - unsigned char *Decompressed, int *StartPos, - int *BlockTypeStartPos, int Len) +static int usbvision_decompress(struct usb_usbvision *usbvision, unsigned char *compressed, + unsigned char *decompressed, int *start_pos, + int *block_typestart_pos, int len) { - int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen; - unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator; - - Integrator = 0; - Pos = *StartPos; - BlockTypePos = *BlockTypeStartPos; - MaxPos = 396; //Pos + Len; - ExtraPos = Pos; - BlockLen = 0; - BlockByte = 0; - BlockCode = 0; - BlockType = 0; - BlockTypeByte = 0; - BlockTypeLen = 0; - RestPixel = Len; - - for (Idx = 0; Idx < Len; Idx++) { - - if (BlockLen == 0) { - if (BlockTypeLen==0) { - BlockTypeByte = Compressed[BlockTypePos]; - BlockTypePos++; - BlockTypeLen = 4; + int rest_pixel, idx, max_pos, pos, extra_pos, block_len, block_type_pos, block_type_len; + unsigned char block_byte, block_code, block_type, block_type_byte, integrator; + + integrator = 0; + pos = *start_pos; + block_type_pos = *block_typestart_pos; + max_pos = 396; /* pos + len; */ + extra_pos = pos; + block_len = 0; + block_byte = 0; + block_code = 0; + block_type = 0; + block_type_byte = 0; + block_type_len = 0; + rest_pixel = len; + + for (idx = 0; idx < len; idx++) { + if (block_len == 0) { + if (block_type_len == 0) { + block_type_byte = compressed[block_type_pos]; + block_type_pos++; + block_type_len = 4; } - BlockType = (BlockTypeByte & 0xC0) >> 6; + block_type = (block_type_byte & 0xC0) >> 6; - //statistic: - usbvision->ComprBlockTypes[BlockType]++; + /* statistic: */ + usbvision->compr_block_types[block_type]++; - Pos = ExtraPos; - if (BlockType == 0) { - if(RestPixel >= 24) { - Idx += 23; - RestPixel -= 24; - Integrator = Decompressed[Idx]; + pos = extra_pos; + if (block_type == 0) { + if (rest_pixel >= 24) { + idx += 23; + rest_pixel -= 24; + integrator = decompressed[idx]; } else { - Idx += RestPixel - 1; - RestPixel = 0; + idx += rest_pixel - 1; + rest_pixel = 0; } } else { - BlockCode = Compressed[Pos]; - Pos++; - if (RestPixel >= 24) { - BlockLen = 24; - } else { - BlockLen = RestPixel; - } - RestPixel -= BlockLen; - ExtraPos = Pos + (BlockLen / 4); + block_code = compressed[pos]; + pos++; + if (rest_pixel >= 24) + block_len = 24; + else + block_len = rest_pixel; + rest_pixel -= block_len; + extra_pos = pos + (block_len / 4); } - BlockTypeByte <<= 2; - BlockTypeLen -= 1; + block_type_byte <<= 2; + block_type_len -= 1; } - if (BlockLen > 0) { - if ((BlockLen%4) == 0) { - BlockByte = Compressed[Pos]; - Pos++; + if (block_len > 0) { + if ((block_len % 4) == 0) { + block_byte = compressed[pos]; + pos++; } - if (BlockType == 1) { //inter Block - Integrator = Decompressed[Idx]; - } - switch (BlockByte & 0xC0) { - case 0x03<<6: - Integrator += Compressed[ExtraPos]; - ExtraPos++; - break; - case 0x02<<6: - Integrator += BlockCode; - break; - case 0x00: - Integrator -= BlockCode; - break; + if (block_type == 1) /* inter Block */ + integrator = decompressed[idx]; + switch (block_byte & 0xC0) { + case 0x03 << 6: + integrator += compressed[extra_pos]; + extra_pos++; + break; + case 0x02 << 6: + integrator += block_code; + break; + case 0x00: + integrator -= block_code; + break; } - Decompressed[Idx] = Integrator; - BlockByte <<= 2; - BlockLen -= 1; + decompressed[idx] = integrator; + block_byte <<= 2; + block_len -= 1; } } - *StartPos = ExtraPos; - *BlockTypeStartPos = BlockTypePos; - return Idx; + *start_pos = extra_pos; + *block_typestart_pos = block_type_pos; + return idx; } @@ -803,7 +782,7 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *C * number of bytes (RGB) to the *pcopylen. * */ -static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, +static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision, long *pcopylen) { #define USBVISION_STRIP_MAGIC 0x5A @@ -811,191 +790,165 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, #define USBVISION_STRIP_HEADER_LEN 3 struct usbvision_frame *frame; - unsigned char *f,*u = NULL ,*v = NULL; - unsigned char StripData[USBVISION_STRIP_LEN_MAX]; - unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN]; - int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos; + unsigned char *f, *u = NULL, *v = NULL; + unsigned char strip_data[USBVISION_STRIP_LEN_MAX]; + unsigned char strip_header[USBVISION_STRIP_HEADER_LEN]; + int idx, idx_end, strip_len, strip_ptr, startblock_pos, block_pos, block_type_pos; int clipmask_index, bytes_per_pixel, rc; - int imageSize; + int image_size; unsigned char rv, gv, bv; static unsigned char *Y, *U, *V; - frame = usbvision->curFrame; - imageSize = frame->frmwidth * frame->frmheight; - if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || - (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format - //... v4l2_linesize not used here. + frame = usbvision->cur_frame; + image_size = frame->frmwidth * frame->frmheight; + if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || + (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420)) { /* this is a planar format */ + /* ... v4l2_linesize not used here. */ f = frame->data + (frame->width * frame->curline); } else f = frame->data + (frame->v4l2_linesize * frame->curline); - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers - // get base of u and b planes add halfoffset - + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { /* initialise u and v pointers */ + /* get base of u and b planes add halfoffset */ u = frame->data - + imageSize - + (frame->frmwidth >>1) * frame->curline ; - v = u + (imageSize >>1 ); - - } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ - - v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ; - u = v + (imageSize >>2) ; + + image_size + + (frame->frmwidth >> 1) * frame->curline; + v = u + (image_size >> 1); + } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { + v = frame->data + image_size + ((frame->curline * (frame->width)) >> 2); + u = v + (image_size >> 2); } - if (frame->curline == 0) { + if (frame->curline == 0) usbvision_adjust_compression(usbvision); - } - if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { - return ParseState_Out; - } + if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) + return parse_state_out; - //get strip header without changing the scratch_read_ptr - scratch_set_extra_ptr(usbvision, &StripPtr, 0); - scratch_get_extra(usbvision, &StripHeader[0], &StripPtr, + /* get strip header without changing the scratch_read_ptr */ + scratch_set_extra_ptr(usbvision, &strip_ptr, 0); + scratch_get_extra(usbvision, &strip_header[0], &strip_ptr, USBVISION_STRIP_HEADER_LEN); - if (StripHeader[0] != USBVISION_STRIP_MAGIC) { - // wrong strip magic - usbvision->stripMagicErrors++; - return ParseState_NextFrame; + if (strip_header[0] != USBVISION_STRIP_MAGIC) { + /* wrong strip magic */ + usbvision->strip_magic_errors++; + return parse_state_next_frame; } - if (frame->curline != (int)StripHeader[2]) { - //line number missmatch error - usbvision->stripLineNumberErrors++; + if (frame->curline != (int)strip_header[2]) { + /* line number mismatch error */ + usbvision->strip_line_number_errors++; } - StripLen = 2 * (unsigned int)StripHeader[1]; - if (StripLen > USBVISION_STRIP_LEN_MAX) { - // strip overrun - // I think this never happens + strip_len = 2 * (unsigned int)strip_header[1]; + if (strip_len > USBVISION_STRIP_LEN_MAX) { + /* strip overrun */ + /* I think this never happens */ usbvision_request_intra(usbvision); } - if (scratch_len(usbvision) < StripLen) { - //there is not enough data for the strip - return ParseState_Out; + if (scratch_len(usbvision) < strip_len) { + /* there is not enough data for the strip */ + return parse_state_out; } - if (usbvision->IntraFrameBuffer) { - Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline; - U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2); - V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); - } - else { - return ParseState_NextFrame; + if (usbvision->intra_frame_buffer) { + Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline; + U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2); + V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); + } else { + return parse_state_next_frame; } bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; clipmask_index = frame->curline * MAX_FRAME_WIDTH; - scratch_get(usbvision, StripData, StripLen); + scratch_get(usbvision, strip_data, strip_len); - IdxEnd = frame->frmwidth; - BlockTypePos = USBVISION_STRIP_HEADER_LEN; - StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2; - BlockPos = StartBlockPos; + idx_end = frame->frmwidth; + block_type_pos = USBVISION_STRIP_HEADER_LEN; + startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2; + block_pos = startblock_pos; - usbvision->BlockPos = BlockPos; + usbvision->block_pos = block_pos; - if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) { - //return ParseState_Continue; - } - if (StripLen > usbvision->maxStripLen) { - usbvision->maxStripLen = StripLen; - } + rc = usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end); + if (strip_len > usbvision->max_strip_len) + usbvision->max_strip_len = strip_len; - if (frame->curline%2) { - if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { - //return ParseState_Continue; - } - } - else { - if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { - //return ParseState_Continue; - } - } + if (frame->curline % 2) + rc = usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end / 2); + else + rc = usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end / 2); - if (BlockPos > usbvision->comprBlockPos) { - usbvision->comprBlockPos = BlockPos; - } - if (BlockPos > StripLen) { - usbvision->stripLenErrors++; - } + if (block_pos > usbvision->comprblock_pos) + usbvision->comprblock_pos = block_pos; + if (block_pos > strip_len) + usbvision->strip_len_errors++; - for (Idx = 0; Idx < IdxEnd; Idx++) { - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = Y[Idx]; - *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2]; - } - else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { - *f++ = Y[Idx]; - if ( Idx & 0x01) - *u++ = U[Idx>>1] ; + for (idx = 0; idx < idx_end; idx++) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + *f++ = Y[idx]; + *f++ = idx & 0x01 ? U[idx / 2] : V[idx / 2]; + } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { + *f++ = Y[idx]; + if (idx & 0x01) + *u++ = U[idx >> 1]; else - *v++ = V[Idx>>1]; - } - else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { - *f++ = Y [Idx]; - if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){ - -/* only need do this for 1 in 4 pixels */ -/* intraframe buffer is YUV420 format */ - - *u++ = U[Idx >>1]; - *v++ = V[Idx >>1]; + *v++ = V[idx >> 1]; + } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { + *f++ = Y[idx]; + if (!((idx & 0x01) | (frame->curline & 0x01))) { + /* only need do this for 1 in 4 pixels */ + /* intraframe buffer is YUV420 format */ + *u++ = U[idx >> 1]; + *v++ = V[idx >> 1]; } - - } - else { - YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv); + } else { + YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx / 2], V[idx / 2], rv, gv, bv); switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_GREY: - *f++ = Y[Idx]; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x03 & (gv >> 3)) | - (0x7C & (bv << 2)); - break; - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x07 & (gv >> 3)) | - (0xF8 & bv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = rv; - *f++ = gv; - *f++ = bv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = rv; - *f++ = gv; - *f++ = bv; - f++; - break; + case V4L2_PIX_FMT_GREY: + *f++ = Y[idx]; + break; + case V4L2_PIX_FMT_RGB555: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x03 & (gv >> 3)) | + (0x7C & (bv << 2)); + break; + case V4L2_PIX_FMT_RGB565: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x07 & (gv >> 3)) | + (0xF8 & bv); + break; + case V4L2_PIX_FMT_RGB24: + *f++ = rv; + *f++ = gv; + *f++ = bv; + break; + case V4L2_PIX_FMT_RGB32: + *f++ = rv; + *f++ = gv; + *f++ = bv; + f++; + break; } } clipmask_index++; } /* Deal with non-integer no. of bytes for YUV420P */ - if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 ) + if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420) *pcopylen += frame->v4l2_linesize; else *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; frame->curline += 1; - if (frame->curline >= frame->frmheight) { - return ParseState_NextFrame; - } - else { - return ParseState_Continue; - } + if (frame->curline >= frame->frmheight) + return parse_state_next_frame; + return parse_state_continue; } @@ -1008,7 +961,7 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, * number of bytes (RGB) to the *pcopylen. * */ -static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision, +static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvision, long *pcopylen) { struct usbvision_frame *frame; @@ -1016,11 +969,11 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision unsigned int pixel_per_line, block; int pixel, block_split; int y_ptr, u_ptr, v_ptr, y_odd_offset; - const int y_block_size = 128; - const int uv_block_size = 64; + const int y_block_size = 128; + const int uv_block_size = 64; const int sub_block_size = 32; - const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; - const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4; + const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; + const int uv_step[] = { 0, 0, 0, 4 }, uv_step_size = 4; unsigned char y[2], u, v; /* YUV components */ int y_, u_, v_, vb, uvg, ur; int r_, g_, b_; /* RGB components */ @@ -1028,7 +981,7 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; int clipmask_add, stretch_bytes; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; f_even = frame->data + (frame->v4l2_linesize * frame->curline); f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; @@ -1040,18 +993,17 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; clipmask_add = usbvision->stretch_width; - pixel_per_line = frame->isocHeader.frameWidth; + pixel_per_line = frame->isoc_header.frame_width; if (scratch_len(usbvision) < (int)pixel_per_line * 3) { - //printk(KERN_DEBUG "out of data, need %d\n", len); - return ParseState_Out; + /* printk(KERN_DEBUG "out of data, need %d\n", len); */ + return parse_state_out; } - if ((frame->curline + 1) >= frame->frmheight) { - return ParseState_NextFrame; - } + if ((frame->curline + 1) >= frame->frmheight) + return parse_state_next_frame; - block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? + block_split = (pixel_per_line%y_block_size) ? 1 : 0; /* are some blocks splitted into different lines? */ y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) + block_split * uv_block_size; @@ -1061,31 +1013,27 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset + (4 - block_split) * sub_block_size); - for (block = 0; block < (pixel_per_line / sub_block_size); - block++) { - - - for (pixel = 0; pixel < sub_block_size; pixel +=2) { + for (block = 0; block < (pixel_per_line / sub_block_size); block++) { + for (pixel = 0; pixel < sub_block_size; pixel += 2) { scratch_get(usbvision, &y[0], 2); scratch_get_extra(usbvision, &u, &u_ptr, 1); scratch_get_extra(usbvision, &v, &v_ptr, 1); - //I don't use the YUV_TO_RGB macro for better performance + /* I don't use the YUV_TO_RGB macro for better performance */ v_ = v - 128; u_ = u - 128; - vb = 132252 * v_; - uvg= -53281 * u_ - 25625 * v_; + vb = 132252 * v_; + uvg = -53281 * u_ - 25625 * v_; ur = 104595 * u_; - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_even++ = y[0]; *f_even++ = v; - } - else { + } else { y_ = 76284 * (y[0] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1121,15 +1069,14 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision clipmask_even_index += clipmask_add; f_even += stretch_bytes; - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_even++ = y[1]; *f_even++ = u; - } - else { + } else { y_ = 76284 * (y[1] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1167,15 +1114,14 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision scratch_get_extra(usbvision, &y[0], &y_ptr, 2); - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_odd++ = y[0]; *f_odd++ = v; - } - else { + } else { y_ = 76284 * (y[0] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1211,15 +1157,14 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision clipmask_odd_index += clipmask_add; f_odd += stretch_bytes; - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_odd++ = y[1]; *f_odd++ = u; - } - else { + } else { y_ = 76284 * (y[1] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1256,7 +1201,7 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision f_odd += stretch_bytes; } - scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size); + scratch_rm_old(usbvision, y_step[block % y_step_size] * sub_block_size); scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] * sub_block_size); scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] @@ -1272,9 +1217,8 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; if (frame->curline >= frame->frmheight) - return ParseState_NextFrame; - else - return ParseState_Continue; + return parse_state_next_frame; + return parse_state_continue; } /* @@ -1288,53 +1232,43 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision static void usbvision_parse_data(struct usb_usbvision *usbvision) { struct usbvision_frame *frame; - enum ParseState newstate; + enum parse_state newstate; long copylen = 0; unsigned long lock_flags; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); while (1) { - - newstate = ParseState_Out; + newstate = parse_state_out; if (scratch_len(usbvision)) { - if (frame->scanstate == ScanState_Scanning) { + if (frame->scanstate == scan_state_scanning) { newstate = usbvision_find_header(usbvision); - } - else if (frame->scanstate == ScanState_Lines) { - if (usbvision->isocMode == ISOC_MODE_YUV420) { + } else if (frame->scanstate == scan_state_lines) { + if (usbvision->isoc_mode == ISOC_MODE_YUV420) newstate = usbvision_parse_lines_420(usbvision, ©len); - } - else if (usbvision->isocMode == ISOC_MODE_YUV422) { + else if (usbvision->isoc_mode == ISOC_MODE_YUV422) newstate = usbvision_parse_lines_422(usbvision, ©len); - } - else if (usbvision->isocMode == ISOC_MODE_COMPRESS) { + else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) newstate = usbvision_parse_compress(usbvision, ©len); - } - } } - if (newstate == ParseState_Continue) { + if (newstate == parse_state_continue) continue; - } - else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) { + if ((newstate == parse_state_next_frame) || (newstate == parse_state_out)) break; - } - else { - return; /* ParseState_EndParse */ - } + return; /* parse_state_end_parse */ } - if (newstate == ParseState_NextFrame) { - frame->grabstate = FrameState_Done; + if (newstate == parse_state_next_frame) { + frame->grabstate = frame_state_done; do_gettimeofday(&(frame->timestamp)); frame->sequence = usbvision->frame_num; spin_lock_irqsave(&usbvision->queue_lock, lock_flags); list_move_tail(&(frame->frame), &usbvision->outqueue); - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); usbvision->frame_num++; @@ -1344,10 +1278,9 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) PDEBUG(DBG_PARSE, "Wake up !"); wake_up_interruptible(&usbvision->wait_frame); } + } else { + frame->grabstate = frame_state_grabbing; } - else - frame->grabstate = FrameState_Grabbing; - /* Update the frame's uncompressed length. */ frame->scanlength += copylen; @@ -1370,34 +1303,32 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; /* Detect and ignore errored packets */ - if (packet_stat) { // packet_stat != 0 ????????????? + if (packet_stat) { /* packet_stat != 0 ????????????? */ PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); - usbvision->isocErrCount++; + usbvision->isoc_err_count++; continue; } /* Detect and ignore empty packets */ if (packet_len < 0) { PDEBUG(DBG_ISOC, "error packet [%d]", i); - usbvision->isocSkipCount++; + usbvision->isoc_skip_count++; continue; - } - else if (packet_len == 0) { /* Frame end ????? */ + } else if (packet_len == 0) { /* Frame end ????? */ PDEBUG(DBG_ISOC, "null packet [%d]", i); - usbvision->isocstate=IsocState_NoFrame; - usbvision->isocSkipCount++; + usbvision->isocstate = isoc_state_no_frame; + usbvision->isoc_skip_count++; continue; - } - else if (packet_len > usbvision->isocPacketSize) { - PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i); - usbvision->isocSkipCount++; + } else if (packet_len > usbvision->isoc_packet_size) { + PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i); + usbvision->isoc_skip_count++; continue; } PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); - if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins - usbvision->isocstate=IsocState_InFrame; + if (usbvision->isocstate == isoc_state_no_frame) { /* new frame begins */ + usbvision->isocstate = isoc_state_in_frame; scratch_mark_header(usbvision); usbvision_measure_bandwidth(usbvision); PDEBUG(DBG_ISOC, "packet with header"); @@ -1412,7 +1343,6 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, * your favorite evil here. */ if (scratch_free(usbvision) < packet_len) { - usbvision->scratch_ovf_count++; PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", scratch_len(usbvision), packet_len); @@ -1422,12 +1352,13 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, /* Now we know that there is enough room in scratch buffer */ scratch_put(usbvision, packet_data, packet_len); totlen += packet_len; - usbvision->isocDataCount += packet_len; - usbvision->isocPacketCount++; + usbvision->isoc_data_count += packet_len; + usbvision->isoc_packet_count++; } #if ENABLE_HEXDUMP if (totlen > 0) { static int foo; + if (foo < 1) { printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); @@ -1435,16 +1366,16 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, } } #endif - return totlen; + return totlen; } -static void usbvision_isocIrq(struct urb *urb) +static void usbvision_isoc_irq(struct urb *urb) { - int errCode = 0; + int err_code = 0; int len; struct usb_usbvision *usbvision = urb->context; int i; - unsigned long startTime = jiffies; + unsigned long start_time = jiffies; struct usbvision_frame **f; /* We don't want to do anything if we are about to be removed! */ @@ -1452,18 +1383,17 @@ static void usbvision_isocIrq(struct urb *urb) return; /* any urb with wrong status is ignored without acknowledgement */ - if (urb->status == -ENOENT) { + if (urb->status == -ENOENT) return; - } - f = &usbvision->curFrame; + f = &usbvision->cur_frame; /* Manage streaming interruption */ - if (usbvision->streaming == Stream_Interrupt) { - usbvision->streaming = Stream_Idle; + if (usbvision->streaming == stream_interrupt) { + usbvision->streaming = stream_idle; if ((*f)) { - (*f)->grabstate = FrameState_Ready; - (*f)->scanstate = ScanState_Scanning; + (*f)->grabstate = frame_state_ready; + (*f)->scanstate = scan_state_scanning; } PDEBUG(DBG_IRQ, "stream interrupted"); wake_up_interruptible(&usbvision->wait_stream); @@ -1472,35 +1402,32 @@ static void usbvision_isocIrq(struct urb *urb) /* Copy the data received into our scratch buffer */ len = usbvision_compress_isochronous(usbvision, urb); - usbvision->isocUrbCount++; + usbvision->isoc_urb_count++; usbvision->urb_length = len; - if (usbvision->streaming == Stream_On) { - + if (usbvision->streaming == stream_on) { /* If we collected enough data let's parse! */ - if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) && - (!list_empty(&(usbvision->inqueue))) ) { + if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH && + !list_empty(&(usbvision->inqueue))) { if (!(*f)) { (*f) = list_entry(usbvision->inqueue.next, struct usbvision_frame, frame); } usbvision_parse_data(usbvision); - } - else { - /*If we don't have a frame + } else { + /* If we don't have a frame we're current working on, complain */ PDEBUG(DBG_IRQ, "received data, but no one needs it"); scratch_reset(usbvision); } - } - else { + } else { PDEBUG(DBG_IRQ, "received data, but no one needs it"); scratch_reset(usbvision); } - usbvision->timeInIrq += jiffies - startTime; + usbvision->time_in_irq += jiffies - start_time; for (i = 0; i < USBVISION_URB_FRAMES; i++) { urb->iso_frame_desc[i].status = 0; @@ -1509,12 +1436,12 @@ static void usbvision_isocIrq(struct urb *urb) urb->status = 0; urb->dev = usbvision->dev; - errCode = usb_submit_urb (urb, GFP_ATOMIC); + err_code = usb_submit_urb(urb, GFP_ATOMIC); - if(errCode) { + if (err_code) { dev_err(&usbvision->dev->dev, "%s: usb_submit_urb failed: error %d\n", - __func__, errCode); + __func__, err_code); } return; @@ -1533,21 +1460,21 @@ static void usbvision_isocIrq(struct urb *urb) int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) { - int errCode = 0; + int err_code = 0; unsigned char buffer[1]; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -1; - errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), + err_code = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) reg, buffer, 1, HZ); - if (errCode < 0) { + if (err_code < 0) { dev_err(&usbvision->dev->dev, - "%s: failed: error %d\n", __func__, errCode); - return errCode; + "%s: failed: error %d\n", __func__, err_code); + return err_code; } return buffer[0]; } @@ -1563,179 +1490,176 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, unsigned char value) { - int errCode = 0; + int err_code = 0; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; - errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), + err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); - if (errCode < 0) { + if (err_code < 0) { dev_err(&usbvision->dev->dev, - "%s: failed: error %d\n", __func__, errCode); + "%s: failed: error %d\n", __func__, err_code); } - return errCode; + return err_code; } -static void usbvision_ctrlUrb_complete(struct urb *urb) +static void usbvision_ctrl_urb_complete(struct urb *urb) { struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; PDEBUG(DBG_IRQ, ""); - usbvision->ctrlUrbBusy = 0; - if (waitqueue_active(&usbvision->ctrlUrb_wq)) { - wake_up_interruptible(&usbvision->ctrlUrb_wq); - } + usbvision->ctrl_urb_busy = 0; + if (waitqueue_active(&usbvision->ctrl_urb_wq)) + wake_up_interruptible(&usbvision->ctrl_urb_wq); } -static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, - unsigned char *data, int len) +static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address, + unsigned char *data, int len) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IRQ, ""); - if (len > 8) { + if (len > 8) return -EFAULT; - } - if (usbvision->ctrlUrbBusy) { + if (usbvision->ctrl_urb_busy) return -EBUSY; - } - usbvision->ctrlUrbBusy = 1; - - usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; - usbvision->ctrlUrbSetup.wValue = 0; - usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); - usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); - usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, + usbvision->ctrl_urb_busy = 1; + + usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + usbvision->ctrl_urb_setup.bRequest = USBVISION_OP_CODE; + usbvision->ctrl_urb_setup.wValue = 0; + usbvision->ctrl_urb_setup.wIndex = cpu_to_le16(address); + usbvision->ctrl_urb_setup.wLength = cpu_to_le16(len); + usb_fill_control_urb(usbvision->ctrl_urb, usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - (unsigned char *)&usbvision->ctrlUrbSetup, - (void *)usbvision->ctrlUrbBuffer, len, - usbvision_ctrlUrb_complete, + (unsigned char *)&usbvision->ctrl_urb_setup, + (void *)usbvision->ctrl_urb_buffer, len, + usbvision_ctrl_urb_complete, (void *)usbvision); - memcpy(usbvision->ctrlUrbBuffer, data, len); + memcpy(usbvision->ctrl_urb_buffer, data, len); - errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); - if (errCode < 0) { - // error in usb_submit_urb() - usbvision->ctrlUrbBusy = 0; + err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC); + if (err_code < 0) { + /* error in usb_submit_urb() */ + usbvision->ctrl_urb_busy = 0; } - PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); - return errCode; + PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code); + return err_code; } static int usbvision_init_compression(struct usb_usbvision *usbvision) { - int errCode = 0; - - usbvision->lastIsocFrameNum = -1; - usbvision->isocDataCount = 0; - usbvision->isocPacketCount = 0; - usbvision->isocSkipCount = 0; - usbvision->comprLevel = 50; - usbvision->lastComprLevel = -1; - usbvision->isocUrbCount = 0; - usbvision->requestIntra = 1; - usbvision->isocMeasureBandwidthCount = 0; - - return errCode; + int err_code = 0; + + usbvision->last_isoc_frame_num = -1; + usbvision->isoc_data_count = 0; + usbvision->isoc_packet_count = 0; + usbvision->isoc_skip_count = 0; + usbvision->compr_level = 50; + usbvision->last_compr_level = -1; + usbvision->isoc_urb_count = 0; + usbvision->request_intra = 1; + usbvision->isoc_measure_bandwidth_count = 0; + + return err_code; } /* this function measures the used bandwidth since last call * return: 0 : no error - * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize + * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size */ -static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) +static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision) { - int errCode = 0; - - if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames - usbvision->isocMeasureBandwidthCount++; - return errCode; - } - if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { - usbvision->usedBandwidth = usbvision->isocDataCount / - (usbvision->isocPacketCount + usbvision->isocSkipCount) * - 100 / usbvision->isocPacketSize; - } - usbvision->isocMeasureBandwidthCount = 0; - usbvision->isocDataCount = 0; - usbvision->isocPacketCount = 0; - usbvision->isocSkipCount = 0; - return errCode; + int err_code = 0; + + if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */ + usbvision->isoc_measure_bandwidth_count++; + return err_code; + } + if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) { + usbvision->used_bandwidth = usbvision->isoc_data_count / + (usbvision->isoc_packet_count + usbvision->isoc_skip_count) * + 100 / usbvision->isoc_packet_size; + } + usbvision->isoc_measure_bandwidth_count = 0; + usbvision->isoc_data_count = 0; + usbvision->isoc_packet_count = 0; + usbvision->isoc_skip_count = 0; + return err_code; } -static int usbvision_adjust_compression (struct usb_usbvision *usbvision) +static int usbvision_adjust_compression(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; unsigned char buffer[6]; PDEBUG(DBG_IRQ, ""); - if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { - usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; - RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); - if (usbvision->comprLevel != usbvision->lastComprLevel) { - int distorsion; - if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { - buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 - distorsion = 7 + 248 * usbvision->comprLevel / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) - buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) - distorsion = 1 + 42 * usbvision->comprLevel / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) - buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) - } - else { //BRIDGE_NT1003 - buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 - distorsion = 2 + 253 * usbvision->comprLevel / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 - buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 - distorsion = 0 + 43 * usbvision->comprLevel / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 - buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 + if ((adjust_compression) && (usbvision->used_bandwidth > 0)) { + usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2; + RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100); + if (usbvision->compr_level != usbvision->last_compr_level) { + int distortion; + + if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) { + buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM Threshold 1 */ + buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM Threshold 2 */ + distortion = 7 + 248 * usbvision->compr_level / 100; + buffer[2] = (unsigned char)(distortion & 0xFF); /* Average distortion Threshold (inter) */ + buffer[3] = (unsigned char)(distortion & 0xFF); /* Average distortion Threshold (intra) */ + distortion = 1 + 42 * usbvision->compr_level / 100; + buffer[4] = (unsigned char)(distortion & 0xFF); /* Maximum distortion Threshold (inter) */ + buffer[5] = (unsigned char)(distortion & 0xFF); /* Maximum distortion Threshold (intra) */ + } else { /* BRIDGE_NT1003 */ + buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM threshold 1 */ + buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM threshold 2 */ + distortion = 2 + 253 * usbvision->compr_level / 100; + buffer[2] = (unsigned char)(distortion & 0xFF); /* distortion threshold bit0-7 */ + buffer[3] = 0; /* (unsigned char)((distortion >> 8) & 0x0F); distortion threshold bit 8-11 */ + distortion = 0 + 43 * usbvision->compr_level / 100; + buffer[4] = (unsigned char)(distortion & 0xFF); /* maximum distortion bit0-7 */ + buffer[5] = 0; /* (unsigned char)((distortion >> 8) & 0x01); maximum distortion bit 8 */ } - errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); - if (errCode == 0){ + err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); + if (err_code == 0) { PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - usbvision->lastComprLevel = usbvision->comprLevel; + usbvision->last_compr_level = usbvision->compr_level; } } } - return errCode; + return err_code; } -static int usbvision_request_intra (struct usb_usbvision *usbvision) +static int usbvision_request_intra(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; unsigned char buffer[1]; PDEBUG(DBG_IRQ, ""); - usbvision->requestIntra = 1; + usbvision->request_intra = 1; buffer[0] = 1; usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return errCode; + return err_code; } -static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) +static int usbvision_unrequest_intra(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; unsigned char buffer[1]; PDEBUG(DBG_IRQ, ""); - usbvision->requestIntra = 0; + usbvision->request_intra = 0; buffer[0] = 0; usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return errCode; + return err_code; } /******************************* @@ -1744,16 +1668,15 @@ static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) int usbvision_power_off(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_FUNC, ""); - errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - if (errCode == 1) { + err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); + if (err_code == 1) usbvision->power = 0; - } - PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); - return errCode; + PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code != 1) ? "ERROR" : "power is off", err_code); + return err_code; } /* @@ -1769,7 +1692,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; - PDEBUG(DBG_FUNC, "isocMode %#02x", format); + PDEBUG(DBG_FUNC, "isoc_mode %#02x", format); if ((format != ISOC_MODE_YUV422) && (format != ISOC_MODE_YUV420) @@ -1778,8 +1701,8 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma format); format = ISOC_MODE_YUV420; } - value[0] = 0x0A; //TODO: See the effect of the filter - value[1] = format; // Sets the VO_MODE register which follows FILT_CONT + value[0] = 0x0A; /* TODO: See the effect of the filter */ + value[1] = format; /* Sets the VO_MODE register which follows FILT_CONT */ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | @@ -1790,7 +1713,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); } - usbvision->isocMode = format; + usbvision->isoc_mode = format; return rc; } @@ -1802,96 +1725,88 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height) { - int errCode = 0; - int UsbWidth, UsbHeight; - unsigned int frameRate=0, frameDrop=0; + int err_code = 0; + int usb_width, usb_height; + unsigned int frame_rate = 0, frame_drop = 0; unsigned char value[4]; - if (!USBVISION_IS_OPERATIONAL(usbvision)) { + if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; - } if (width > MAX_USB_WIDTH) { - UsbWidth = width / 2; + usb_width = width / 2; usbvision->stretch_width = 2; - } - else { - UsbWidth = width; + } else { + usb_width = width; usbvision->stretch_width = 1; } if (height > MAX_USB_HEIGHT) { - UsbHeight = height / 2; + usb_height = height / 2; usbvision->stretch_height = 2; - } - else { - UsbHeight = height; + } else { + usb_height = height; usbvision->stretch_height = 1; } - RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); - UsbWidth &= ~(MIN_FRAME_WIDTH-1); - RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); - UsbHeight &= ~(1); + RESTRICT_TO_RANGE(usb_width, MIN_FRAME_WIDTH, MAX_USB_WIDTH); + usb_width &= ~(MIN_FRAME_WIDTH-1); + RESTRICT_TO_RANGE(usb_height, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); + usb_height &= ~(1); PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", - UsbWidth, UsbHeight, width, height, + usb_width, usb_height, width, height, usbvision->stretch_width, usbvision->stretch_height); /* I'll not rewrite the same values */ - if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { - value[0] = UsbWidth & 0xff; //LSB - value[1] = (UsbWidth >> 8) & 0x03; //MSB - value[2] = UsbHeight & 0xff; //LSB - value[3] = (UsbHeight >> 8) & 0x03; //MSB + if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) { + value[0] = usb_width & 0xff; /* LSB */ + value[1] = (usb_width >> 8) & 0x03; /* MSB */ + value[2] = usb_height & 0xff; /* LSB */ + value[3] = (usb_height >> 8) & 0x03; /* MSB */ - errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), + err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); - if (errCode < 0) { + if (err_code < 0) { dev_err(&usbvision->dev->dev, - "%s failed: error %d\n", __func__, errCode); - return errCode; + "%s failed: error %d\n", __func__, err_code); + return err_code; } - usbvision->curwidth = usbvision->stretch_width * UsbWidth; - usbvision->curheight = usbvision->stretch_height * UsbHeight; + usbvision->curwidth = usbvision->stretch_width * usb_width; + usbvision->curheight = usbvision->stretch_height * usb_height; } - if (usbvision->isocMode == ISOC_MODE_YUV422) { - frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); - } - else if (usbvision->isocMode == ISOC_MODE_YUV420) { - frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); - } - else { - frameRate = FRAMERATE_MAX; - } + if (usbvision->isoc_mode == ISOC_MODE_YUV422) + frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2); + else if (usbvision->isoc_mode == ISOC_MODE_YUV420) + frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8); + else + frame_rate = FRAMERATE_MAX; - if (usbvision->tvnormId & V4L2_STD_625_50) { - frameDrop = frameRate * 32 / 25 - 1; - } - else if (usbvision->tvnormId & V4L2_STD_525_60) { - frameDrop = frameRate * 32 / 30 - 1; - } + if (usbvision->tvnorm_id & V4L2_STD_625_50) + frame_drop = frame_rate * 32 / 25 - 1; + else if (usbvision->tvnorm_id & V4L2_STD_525_60) + frame_drop = frame_rate * 32 / 30 - 1; - RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); + RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX); - PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); + PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop); - frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled + frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ - /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... - => frameSkip = 4; - => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; + /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... + => frame_skip = 4; + => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; - frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... - => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... - => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; + frame_drop = 9; => frame_phase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... + => frame_skip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... + => frame_rate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; */ - errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); - return errCode; + err_code = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frame_drop); + return err_code; } @@ -1903,8 +1818,8 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames { int i; - /*needs to be page aligned cause the buffers can be mapped individually! */ - usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * + /* needs to be page aligned cause the buffers can be mapped individually! */ + usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * usbvision->curheight * usbvision->palette.bytes_per_pixel); @@ -1912,9 +1827,9 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames usbvision->num_frames = number_of_frames; while (usbvision->num_frames > 0) { usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size; - if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) { + usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); + if (usbvision->fbuf) break; - } usbvision->num_frames--; } @@ -1925,7 +1840,7 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames /* Allocate all buffers */ for (i = 0; i < usbvision->num_frames; i++) { usbvision->frame[i].index = i; - usbvision->frame[i].grabstate = FrameState_Unused; + usbvision->frame[i].grabstate = frame_state_unused; usbvision->frame[i].data = usbvision->fbuf + i * usbvision->max_frame_size; /* @@ -1937,7 +1852,8 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames usbvision->frame[i].height = usbvision->curheight; usbvision->frame[i].bytes_read = 0; } - PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size); + PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)", + usbvision->num_frames, usbvision->max_frame_size); return usbvision->num_frames; } @@ -1948,7 +1864,7 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames void usbvision_frames_free(struct usb_usbvision *usbvision) { /* Have to free all that memory */ - PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames); + PDEBUG(DBG_FUNC, "free %d frames", usbvision->num_frames); if (usbvision->fbuf != NULL) { usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); @@ -1969,7 +1885,7 @@ void usbvision_empty_framequeues(struct usb_usbvision *usbvision) INIT_LIST_HEAD(&(usbvision->outqueue)); for (i = 0; i < USBVISION_NUMFRAMES; i++) { - usbvision->frame[i].grabstate = FrameState_Unused; + usbvision->frame[i].grabstate = frame_state_unused; usbvision->frame[i].bytes_read = 0; } } @@ -1984,9 +1900,9 @@ int usbvision_stream_interrupt(struct usb_usbvision *usbvision) /* stop reading from the device */ - usbvision->streaming = Stream_Interrupt; + usbvision->streaming = stream_interrupt; ret = wait_event_timeout(usbvision->wait_stream, - (usbvision->streaming == Stream_Idle), + (usbvision->streaming == stream_idle), msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); return ret; } @@ -2002,19 +1918,19 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) int rc; unsigned char value[6]; - value[0] = 0x0F; // Intra-Compression cycle - value[1] = 0x01; // Reg.45 one line per strip - value[2] = 0x00; // Reg.46 Force intra mode on all new frames - value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) - value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. - value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression - - //catched values for NT1004 - // value[0] = 0xFF; // Never apply intra mode automatically - // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip - // value[2] = 0x01; // Force intra mode on all new frames - // value[3] = 0x00; // Strip size 400 Bytes; do not force up - // value[4] = 0xA2; // + value[0] = 0x0F; /* Intra-Compression cycle */ + value[1] = 0x01; /* Reg.45 one line per strip */ + value[2] = 0x00; /* Reg.46 Force intra mode on all new frames */ + value[3] = 0x00; /* Reg.47 FORCE_UP <- 0 normal operation (not force) */ + value[4] = 0xA2; /* Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. */ + value[5] = 0x00; /* Reg.49 DVI_YUV This has nothing to do with compression */ + + /* catched values for NT1004 */ + /* value[0] = 0xFF; Never apply intra mode automatically */ + /* value[1] = 0xF1; Use full frame height for virtual strip width; One line per strip */ + /* value[2] = 0x01; Force intra mode on all new frames */ + /* value[3] = 0x00; Strip size 400 Bytes; do not force up */ + /* value[4] = 0xA2; */ if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; @@ -2030,21 +1946,20 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) return rc; } - if (usbvision->bridgeType == BRIDGE_NT1004) { - value[0] = 20; // PCM Threshold 1 - value[1] = 12; // PCM Threshold 2 - value[2] = 255; // Distorsion Threshold inter - value[3] = 255; // Distorsion Threshold intra - value[4] = 43; // Max Distorsion inter - value[5] = 43; // Max Distorsion intra - } - else { - value[0] = 20; // PCM Threshold 1 - value[1] = 12; // PCM Threshold 2 - value[2] = 255; // Distorsion Threshold d7-d0 - value[3] = 0; // Distorsion Threshold d11-d8 - value[4] = 43; // Max Distorsion d7-d0 - value[5] = 0; // Max Distorsion d8 + if (usbvision->bridge_type == BRIDGE_NT1004) { + value[0] = 20; /* PCM Threshold 1 */ + value[1] = 12; /* PCM Threshold 2 */ + value[2] = 255; /* Distortion Threshold inter */ + value[3] = 255; /* Distortion Threshold intra */ + value[4] = 43; /* Max Distortion inter */ + value[5] = 43; /* Max Distortion intra */ + } else { + value[0] = 20; /* PCM Threshold 1 */ + value[1] = 12; /* PCM Threshold 2 */ + value[2] = 255; /* Distortion Threshold d7-d0 */ + value[3] = 0; /* Distortion Threshold d11-d8 */ + value[4] = 43; /* Max Distortion d7-d0 */ + value[5] = 0; /* Max Distortion d8 */ } if (!USBVISION_IS_OPERATIONAL(usbvision)) @@ -2059,10 +1974,7 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) if (rc < 0) { printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); - return rc; } - - return rc; } @@ -2085,9 +1997,9 @@ int usbvision_set_input(struct usb_usbvision *usbvision) return 0; /* Set input format expected from decoder*/ - if (usbvision_device_data[usbvision->DevModel].Vin_Reg1_override) { - value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1; - } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { + if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) { + value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1; + } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { /* SAA7113 uses 8 bit output */ value[0] = USBVISION_8_422_SYNC; } else { @@ -2105,53 +2017,53 @@ int usbvision_set_input(struct usb_usbvision *usbvision) } - if (usbvision->tvnormId & V4L2_STD_PAL) { + if (usbvision->tvnorm_id & V4L2_STD_PAL) { value[0] = 0xC0; - value[1] = 0x02; //0x02C0 -> 704 Input video line length + value[1] = 0x02; /* 0x02C0 -> 704 Input video line length */ value[2] = 0x20; - value[3] = 0x01; //0x0120 -> 288 Input video n. of lines + value[3] = 0x01; /* 0x0120 -> 288 Input video n. of lines */ value[4] = 0x60; - value[5] = 0x00; //0x0060 -> 96 Input video h offset + value[5] = 0x00; /* 0x0060 -> 96 Input video h offset */ value[6] = 0x16; - value[7] = 0x00; //0x0016 -> 22 Input video v offset - } else if (usbvision->tvnormId & V4L2_STD_SECAM) { + value[7] = 0x00; /* 0x0016 -> 22 Input video v offset */ + } else if (usbvision->tvnorm_id & V4L2_STD_SECAM) { value[0] = 0xC0; - value[1] = 0x02; //0x02C0 -> 704 Input video line length + value[1] = 0x02; /* 0x02C0 -> 704 Input video line length */ value[2] = 0x20; - value[3] = 0x01; //0x0120 -> 288 Input video n. of lines + value[3] = 0x01; /* 0x0120 -> 288 Input video n. of lines */ value[4] = 0x01; - value[5] = 0x00; //0x0001 -> 01 Input video h offset + value[5] = 0x00; /* 0x0001 -> 01 Input video h offset */ value[6] = 0x01; - value[7] = 0x00; //0x0001 -> 01 Input video v offset + value[7] = 0x00; /* 0x0001 -> 01 Input video v offset */ } else { /* V4L2_STD_NTSC */ value[0] = 0xD0; - value[1] = 0x02; //0x02D0 -> 720 Input video line length + value[1] = 0x02; /* 0x02D0 -> 720 Input video line length */ value[2] = 0xF0; - value[3] = 0x00; //0x00F0 -> 240 Input video number of lines + value[3] = 0x00; /* 0x00F0 -> 240 Input video number of lines */ value[4] = 0x50; - value[5] = 0x00; //0x0050 -> 80 Input video h offset + value[5] = 0x00; /* 0x0050 -> 80 Input video h offset */ value[6] = 0x10; - value[7] = 0x00; //0x0010 -> 16 Input video v offset + value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ } - if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { - value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; - value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; + if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { + value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; + value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; } - if (adjust_X_Offset != -1) { - value[4] = adjust_X_Offset & 0xff; - value[5] = (adjust_X_Offset & 0x0300) >> 8; + if (adjust_x_offset != -1) { + value[4] = adjust_x_offset & 0xff; + value[5] = (adjust_x_offset & 0x0300) >> 8; } - if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { - value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; - value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; + if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) { + value[6] = usbvision_device_data[usbvision->dev_model].y_offset & 0xff; + value[7] = (usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8; } - if (adjust_Y_Offset != -1) { - value[6] = adjust_Y_Offset & 0xff; - value[7] = (adjust_Y_Offset & 0x0300) >> 8; + if (adjust_y_offset != -1) { + value[6] = adjust_y_offset & 0xff; + value[7] = (adjust_y_offset & 0x0300) >> 8; } rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), @@ -2167,15 +2079,14 @@ int usbvision_set_input(struct usb_usbvision *usbvision) dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ - if(usbvision_device_data[usbvision->DevModel].Dvi_yuv_override){ - dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv; - } - else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { - /* This changes as the fine sync control changes. Further investigation necessary */ + if (usbvision_device_data[usbvision->dev_model].dvi_yuv_override) { + dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv; + } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { + /* This changes as the fine sync control changes. Further investigation necessary */ dvi_yuv_value = 0x06; } - return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value)); + return usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value); } @@ -2192,7 +2103,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) int rc; unsigned char value[8]; - if (usbvision->isocMode == ISOC_MODE_COMPRESS) { + if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { value[0] = 0x42; value[1] = 0x71; value[2] = 0xff; @@ -2201,11 +2112,10 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) value[5] = 0xe0; value[6] = 0x71; value[7] = 0xff; - // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) - // FDL: 0x00000-0x0E099 = 57498 Words - // VDW: 0x0E3FF-0x3FFFF - } - else { + /* UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */ + /* FDL: 0x00000-0x0E099 = 57498 Words */ + /* VDW: 0x0E3FF-0x3FFFF */ + } else { value[0] = 0x42; value[1] = 0x00; value[2] = 0xff; @@ -2218,14 +2128,14 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) /* These are the values of the address of the video buffer, * they have to be loaded into the USBVISION_DRM_PRM1-8 * - * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 - * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff - * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 + * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 + * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff + * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 * Only used in compressed mode - * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff + * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff * Only used in compressed mode - * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 - * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff + * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 + * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff */ if (!USBVISION_IS_OPERATIONAL(usbvision)) @@ -2243,8 +2153,9 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) } /* Restart the video buffer logic */ - if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | - USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) + rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | + USBVISION_RES_FDL | USBVISION_RES_VDW); + if (rc < 0) return rc; rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); @@ -2261,23 +2172,22 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) int usbvision_power_on(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_FUNC, ""); usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_RES2); + USBVISION_SSPND_EN | USBVISION_RES2); usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID); - errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); - if (errCode == 1) { + USBVISION_SSPND_EN | USBVISION_PWR_VID); + err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, + USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); + if (err_code == 1) usbvision->power = 1; - } - PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); - return errCode; + PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code < 0) ? "ERROR" : "power is on", err_code); + return err_code; } @@ -2285,53 +2195,50 @@ int usbvision_power_on(struct usb_usbvision *usbvision) * usbvision timer stuff */ -// to call usbvision_power_off from task queue +/* to call usbvision_power_off from task queue */ static void call_usbvision_power_off(struct work_struct *work) { - struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); + struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work); PDEBUG(DBG_FUNC, ""); - if(mutex_lock_interruptible(&usbvision->lock)) { + if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return; - } - - if(usbvision->user == 0) { + if (usbvision->user == 0) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; } - mutex_unlock(&usbvision->lock); + mutex_unlock(&usbvision->v4l2_lock); } -static void usbvision_powerOffTimer(unsigned long data) +static void usbvision_power_off_timer(unsigned long data) { - struct usb_usbvision *usbvision = (void *) data; + struct usb_usbvision *usbvision = (void *)data; PDEBUG(DBG_FUNC, ""); - del_timer(&usbvision->powerOffTimer); - INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); - (void) schedule_work(&usbvision->powerOffWork); + del_timer(&usbvision->power_off_timer); + INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off); + (void) schedule_work(&usbvision->power_off_work); } -void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) +void usbvision_init_power_off_timer(struct usb_usbvision *usbvision) { - init_timer(&usbvision->powerOffTimer); - usbvision->powerOffTimer.data = (long) usbvision; - usbvision->powerOffTimer.function = usbvision_powerOffTimer; + init_timer(&usbvision->power_off_timer); + usbvision->power_off_timer.data = (long)usbvision; + usbvision->power_off_timer.function = usbvision_power_off_timer; } -void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision) +void usbvision_set_power_off_timer(struct usb_usbvision *usbvision) { - mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME); + mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME); } -void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) +void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision) { - if (timer_pending(&usbvision->powerOffTimer)) { - del_timer(&usbvision->powerOffTimer); - } + if (timer_pending(&usbvision->power_off_timer)) + del_timer(&usbvision->power_off_timer); } /* @@ -2341,14 +2248,10 @@ void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) */ int usbvision_begin_streaming(struct usb_usbvision *usbvision) { - int errCode = 0; - - if (usbvision->isocMode == ISOC_MODE_COMPRESS) { + if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) usbvision_init_compression(usbvision); - } - errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | - usbvision->Vin_Reg2_Preset); - return errCode; + return usbvision_write_reg(usbvision, USBVISION_VIN_REG2, + USBVISION_NOHVALID | usbvision->vin_reg2_preset); } /* @@ -2360,25 +2263,24 @@ int usbvision_restart_isoc(struct usb_usbvision *usbvision) { int ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0) + ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG, + USBVISION_SSPND_EN | USBVISION_PWR_VID); + if (ret < 0) return ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_PWR_REG, + ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID | - USBVISION_RES2)) < 0) + USBVISION_RES2); + if (ret < 0) return ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_VIN_REG2, + ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_KEEP_BLANK | USBVISION_NOHVALID | - usbvision->Vin_Reg2_Preset)) < 0) return ret; + usbvision->vin_reg2_preset); + if (ret < 0) + return ret; /* TODO: schedule timeout */ - while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1); + while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1) + ; return 0; } @@ -2386,27 +2288,27 @@ int usbvision_restart_isoc(struct usb_usbvision *usbvision) int usbvision_audio_off(struct usb_usbvision *usbvision) { if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { - printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); + printk(KERN_ERR "usbvision_audio_off: can't write reg\n"); return -1; } - usbvision->AudioMute = 0; - usbvision->AudioChannel = USBVISION_AUDIO_MUTE; + usbvision->audio_mute = 0; + usbvision->audio_channel = USBVISION_AUDIO_MUTE; return 0; } -int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel) +int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) { - if (!usbvision->AudioMute) { - if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) { + if (!usbvision->audio_mute) { + if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, audio_channel) < 0) { printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); return -1; } } - usbvision->AudioChannel = AudioChannel; + usbvision->audio_channel = audio_channel; return 0; } -int usbvision_setup(struct usb_usbvision *usbvision,int format) +int usbvision_setup(struct usb_usbvision *usbvision, int format) { usbvision_set_video_format(usbvision, format); usbvision_set_dram_settings(usbvision); @@ -2421,27 +2323,28 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format) int usbvision_set_alternate(struct usb_usbvision *dev) { - int errCode, prev_alt = dev->ifaceAlt; + int err_code, prev_alt = dev->iface_alt; int i; - dev->ifaceAlt=0; - for(i=0;i< dev->num_alt; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt]) - dev->ifaceAlt=i; - - if (dev->ifaceAlt != prev_alt) { - dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt]; - PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize); - errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt); - if (errCode < 0) { + dev->iface_alt = 0; + for (i = 0; i < dev->num_alt; i++) + if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->iface_alt]) + dev->iface_alt = i; + + if (dev->iface_alt != prev_alt) { + dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt]; + PDEBUG(DBG_FUNC, "setting alternate %d with max_packet_size=%u", + dev->iface_alt, dev->isoc_packet_size); + err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt); + if (err_code < 0) { dev_err(&dev->dev->dev, "cannot change alternate number to %d (error=%i)\n", - dev->ifaceAlt, errCode); - return errCode; + dev->iface_alt, err_code); + return err_code; } } - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize); + PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isoc_packet_size); return 0; } @@ -2453,27 +2356,27 @@ int usbvision_set_alternate(struct usb_usbvision *dev) int usbvision_init_isoc(struct usb_usbvision *usbvision) { struct usb_device *dev = usbvision->dev; - int bufIdx, errCode, regValue; + int buf_idx, err_code, reg_value; int sb_size; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -EFAULT; - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; scratch_reset(usbvision); /* Alternate interface 1 is is the biggest frame size */ - errCode = usbvision_set_alternate(usbvision); - if (errCode < 0) { - usbvision->last_error = errCode; + err_code = usbvision_set_alternate(usbvision); + if (err_code < 0) { + usbvision->last_error = err_code; return -EBUSY; } - sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize; + sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size; - regValue = (16 - usbvision_read_reg(usbvision, + reg_value = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->usb_bandwidth = regValue >> 1; + usbvision->usb_bandwidth = reg_value >> 1; PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); @@ -2481,7 +2384,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) /* We double buffer the Iso lists */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { + for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { int j, k; struct urb *urb; @@ -2491,8 +2394,8 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) "%s: usb_alloc_urb() failed\n", __func__); return -ENOMEM; } - usbvision->sbuf[bufIdx].urb = urb; - usbvision->sbuf[bufIdx].data = + usbvision->sbuf[buf_idx].urb = urb; + usbvision->sbuf[buf_idx].data = usb_alloc_coherent(usbvision->dev, sb_size, GFP_KERNEL, @@ -2502,31 +2405,31 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = 1; - urb->transfer_buffer = usbvision->sbuf[bufIdx].data; - urb->complete = usbvision_isocIrq; + urb->transfer_buffer = usbvision->sbuf[buf_idx].data; + urb->complete = usbvision_isoc_irq; urb->number_of_packets = USBVISION_URB_FRAMES; urb->transfer_buffer_length = - usbvision->isocPacketSize * USBVISION_URB_FRAMES; + usbvision->isoc_packet_size * USBVISION_URB_FRAMES; for (j = k = 0; j < USBVISION_URB_FRAMES; j++, - k += usbvision->isocPacketSize) { + k += usbvision->isoc_packet_size) { urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = - usbvision->isocPacketSize; + usbvision->isoc_packet_size; } } /* Submit all URBs */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, + for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { + err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb, GFP_KERNEL); - if (errCode) { + if (err_code) { dev_err(&usbvision->dev->dev, "%s: usb_submit_urb(%d) failed: error %d\n", - __func__, bufIdx, errCode); + __func__, buf_idx, err_code); } } - usbvision->streaming = Stream_Idle; + usbvision->streaming = stream_idle; PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __func__, usbvision->video_endp); @@ -2542,47 +2445,46 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) */ void usbvision_stop_isoc(struct usb_usbvision *usbvision) { - int bufIdx, errCode, regValue; - int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize; + int buf_idx, err_code, reg_value; + int sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size; - if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) + if ((usbvision->streaming == stream_off) || (usbvision->dev == NULL)) return; /* Unschedule all of the iso td's */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - usb_kill_urb(usbvision->sbuf[bufIdx].urb); - if (usbvision->sbuf[bufIdx].data){ + for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { + usb_kill_urb(usbvision->sbuf[buf_idx].urb); + if (usbvision->sbuf[buf_idx].data) { usb_free_coherent(usbvision->dev, sb_size, - usbvision->sbuf[bufIdx].data, - usbvision->sbuf[bufIdx].urb->transfer_dma); + usbvision->sbuf[buf_idx].data, + usbvision->sbuf[buf_idx].urb->transfer_dma); } - usb_free_urb(usbvision->sbuf[bufIdx].urb); - usbvision->sbuf[bufIdx].urb = NULL; + usb_free_urb(usbvision->sbuf[buf_idx].urb); + usbvision->sbuf[buf_idx].urb = NULL; } - PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__); - usbvision->streaming = Stream_Off; + PDEBUG(DBG_ISOC, "%s: streaming=stream_off\n", __func__); + usbvision->streaming = stream_off; if (!usbvision->remove_pending) { - /* Set packet size to 0 */ - usbvision->ifaceAlt=0; - errCode = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->ifaceAlt); - if (errCode < 0) { + usbvision->iface_alt = 0; + err_code = usb_set_interface(usbvision->dev, usbvision->iface, + usbvision->iface_alt); + if (err_code < 0) { dev_err(&usbvision->dev->dev, "%s: usb_set_interface() failed: error %d\n", - __func__, errCode); - usbvision->last_error = errCode; + __func__, err_code); + usbvision->last_error = err_code; } - regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->isocPacketSize = - (regValue == 0) ? 0 : (regValue * 64) - 1; + reg_value = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; + usbvision->isoc_packet_size = + (reg_value == 0) ? 0 : (reg_value * 64) - 1; PDEBUG(DBG_ISOC, "ISO Packet Length:%d", - usbvision->isocPacketSize); + usbvision->isoc_packet_size); - usbvision->usb_bandwidth = regValue >> 1; + usbvision->usb_bandwidth = reg_value >> 1; PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); } @@ -2592,39 +2494,38 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) { /* inputs #0 and #3 are constant for every SAA711x. */ /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */ - int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3}; - int audio[]= {1, 0, 0, 0}; - //channel 0 is TV with audiochannel 1 (tuner mono) - //channel 1 is Composite with audio channel 0 (line in) - //channel 2 is S-Video with audio channel 0 (line in) - //channel 3 is additional video inputs to the device with audio channel 0 (line in) + int mode[4] = { SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3 }; + int audio[] = { 1, 0, 0, 0 }; + /* channel 0 is TV with audiochannel 1 (tuner mono) */ + /* channel 1 is Composite with audio channel 0 (line in) */ + /* channel 2 is S-Video with audio channel 0 (line in) */ + /* channel 3 is additional video inputs to the device with audio channel 0 (line in) */ RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); usbvision->ctl_input = channel; - // set the new channel - // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video - // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red - - switch (usbvision_device_data[usbvision->DevModel].Codec) { - case CODEC_SAA7113: - mode[1] = SAA7115_COMPOSITE2; - if (SwitchSVideoInput) { - /* To handle problems with S-Video Input for - * some devices. Use SwitchSVideoInput - * parameter when loading the module.*/ - mode[2] = SAA7115_COMPOSITE1; - } - else { - mode[2] = SAA7115_SVIDEO1; - } - break; - case CODEC_SAA7111: - default: - /* modes for saa7111 */ - mode[1] = SAA7115_COMPOSITE1; + /* set the new channel */ + /* Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video */ + /* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */ + + switch (usbvision_device_data[usbvision->dev_model].codec) { + case CODEC_SAA7113: + mode[1] = SAA7115_COMPOSITE2; + if (switch_svideo_input) { + /* To handle problems with S-Video Input for + * some devices. Use switch_svideo_input + * parameter when loading the module.*/ + mode[2] = SAA7115_COMPOSITE1; + } else { mode[2] = SAA7115_SVIDEO1; - break; + } + break; + case CODEC_SAA7111: + default: + /* modes for saa7111 */ + mode[1] = SAA7115_COMPOSITE1; + mode[2] = SAA7115_SVIDEO1; + break; } call_all(usbvision, video, s_routing, mode[channel], 0, 0); usbvision_set_audio(usbvision, audio[channel]); diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index e3bbae26e3c..05b1344181c 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -28,18 +28,18 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/init.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/ioport.h> #include <linux/errno.h> #include <linux/usb.h> #include <linux/i2c.h> #include "usbvision.h" -#define DBG_I2C 1<<0 +#define DBG_I2C (1 << 0) static int i2c_debug; -module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver +module_param(i2c_debug, int, 0644); /* debug_i2c_usb mode of the device driver */ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define PDEBUG(level, fmt, args...) { \ @@ -72,8 +72,8 @@ static inline int try_write_address(struct i2c_adapter *i2c_adap, udelay(10); } if (i) { - PDEBUG(DBG_I2C,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_I2C,"Maybe there's no device at this address"); + PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr); + PDEBUG(DBG_I2C, "Maybe there's no device at this address"); } return ret; } @@ -96,8 +96,8 @@ static inline int try_read_address(struct i2c_adapter *i2c_adap, udelay(10); } if (i) { - PDEBUG(DBG_I2C,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_I2C,"Maybe there's no device at this address"); + PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr); + PDEBUG(DBG_I2C, "Maybe there's no device at this address"); } return ret; } @@ -143,9 +143,8 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, else ret = try_write_address(i2c_adap, addr, retries); - if (ret != 1) { + if (ret != 1) return -EREMOTEIO; - } } return 0; } @@ -164,22 +163,20 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) pmsg = &msgs[i]; ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); if (ret != 0) { - PDEBUG(DBG_I2C,"got NAK from device, message #%d", i); + PDEBUG(DBG_I2C, "got NAK from device, message #%d", i); return (ret < 0) ? ret : -EREMOTEIO; } if (pmsg->flags & I2C_M_RD) { /* read bytes into buffer */ ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) { + if (ret < pmsg->len) return (ret < 0) ? ret : -EREMOTEIO; - } } else { /* write bytes from buffer */ ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) { + if (ret < pmsg->len) return (ret < 0) ? ret : -EREMOTEIO; - } } } return num; @@ -219,7 +216,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name, usbvision->dev->bus->busnum, usbvision->dev->devpath); - PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); + PDEBUG(DBG_I2C, "Adaptername: %s", usbvision->i2c_adap.name); usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); @@ -244,31 +241,31 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name); /* Request the load of the i2c modules we need */ - switch (usbvision_device_data[usbvision->DevModel].Codec) { + switch (usbvision_device_data[usbvision->dev_model].codec) { case CODEC_SAA7113: case CODEC_SAA7111: /* Without this delay the detection of the saa711x is hit-and-miss. */ mdelay(10); v4l2_i2c_new_subdev(&usbvision->v4l2_dev, - &usbvision->i2c_adap, NULL, + &usbvision->i2c_adap, "saa7115_auto", 0, saa711x_addrs); break; } - if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { + if (usbvision_device_data[usbvision->dev_model].tuner == 1) { struct v4l2_subdev *sd; enum v4l2_i2c_tuner_type type; struct tuner_setup tun_setup; sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, - &usbvision->i2c_adap, NULL, + &usbvision->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); /* depending on whether we found a demod or not, select the tuner type. */ type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, - &usbvision->i2c_adap, NULL, + &usbvision->i2c_adap, "tuner", 0, v4l2_i2c_tuner_addrs(type)); if (sd == NULL) @@ -293,7 +290,7 @@ int usbvision_i2c_unregister(struct usb_usbvision *usbvision) i2c_del_adapter(&(usbvision->i2c_adap)); usbvision->registered_i2c = 0; - PDEBUG(DBG_I2C,"i2c bus for %s unregistered", usbvision->i2c_adap.name); + PDEBUG(DBG_I2C, "i2c bus for %s unregistered", usbvision->i2c_adap.name); return 0; } @@ -355,9 +352,9 @@ usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, if (i2c_debug & DBG_I2C) { int idx; - for (idx = 0; idx < len; idx++) { - PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); - } + + for (idx = 0; idx < len; idx++) + PDEBUG(DBG_I2C, "read %x from address %x", (unsigned char)buf[idx], addr); } return len; } @@ -416,9 +413,9 @@ static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, if (i2c_debug & DBG_I2C) { int idx; - for (idx = 0; idx < len; idx++) { - PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); - } + + for (idx = 0; idx < len; idx++) + PDEBUG(DBG_I2C, "wrote %x at address %x", (unsigned char)buf[idx], addr); } return len; } @@ -426,18 +423,18 @@ static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len) { - char *bufPtr = buf; + char *buf_ptr = buf; int retval; int wrcount = 0; int count; - int maxLen = 4; + int max_len = 4; while (len > 0) { - count = (len > maxLen) ? maxLen : len; - retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); + count = (len > max_len) ? max_len : len; + retval = usbvision_i2c_write_max4(usbvision, addr, buf_ptr, count); if (retval > 0) { len -= count; - bufPtr += count; + buf_ptr += count; wrcount += count; } else return (retval < 0) ? retval : -EFAULT; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 011c0c38699..6083137f0bf 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -56,7 +56,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/spinlock.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/videodev2.h> #include <linux/i2c.h> @@ -70,8 +70,8 @@ #include "usbvision.h" #include "usbvision-cards.h" -#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>,\ - Dwaine Garden <DwaineGarden@rogers.com>" +#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, \ +Dwaine Garden <DwaineGarden@rogers.com>" #define DRIVER_NAME "usbvision" #define DRIVER_ALIAS "USBVision" #define DRIVER_DESC "USBVision USB Video Device Driver for Linux" @@ -82,9 +82,9 @@ #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\ USBVISION_DRIVER_VERSION_MINOR,\ USBVISION_DRIVER_VERSION_PATCHLEVEL) -#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR)\ - "." __stringify(USBVISION_DRIVER_VERSION_MINOR)\ - "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) +#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) \ +"." __stringify(USBVISION_DRIVER_VERSION_MINOR) \ +"." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) #define ENABLE_HEXDUMP 0 /* Enable if you need it */ @@ -96,16 +96,16 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) __func__, __LINE__ , ## args); \ } #else - #define PDEBUG(level, fmt, args...) do {} while(0) + #define PDEBUG(level, fmt, args...) do {} while (0) #endif -#define DBG_IO 1<<1 -#define DBG_PROBE 1<<2 -#define DBG_MMAP 1<<3 +#define DBG_IO (1 << 1) +#define DBG_PROBE (1 << 2) +#define DBG_MMAP (1 << 3) -//String operations -#define rmspace(str) while(*str==' ') str++; -#define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; +/* String operations */ +#define rmspace(str) while (*str == ' ') str++; +#define goto2next(str) while (*str != ' ') str++; while (*str == ' ') str++; /* sequential number of usbvision device */ @@ -118,7 +118,7 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, - { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 ! + { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, /* 1.5 ! */ { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } }; @@ -127,11 +127,11 @@ static void usbvision_release(struct usb_usbvision *usbvision); /* Default initialization of device driver parameters */ /* Set the default format for ISOC endpoint */ -static int isocMode = ISOC_MODE_COMPRESS; +static int isoc_mode = ISOC_MODE_COMPRESS; /* Set the default Debug Mode of the device driver */ static int video_debug; /* Set the default device to power on at startup */ -static int PowerOnAtOpen = 1; +static int power_on_at_open = 1; /* Sequential Number of Video Device */ static int video_nr = -1; /* Sequential Number of Radio Device */ @@ -140,20 +140,20 @@ static int radio_nr = -1; /* Grab parameters for the device driver */ /* Showing parameters under SYSFS */ -module_param(isocMode, int, 0444); +module_param(isoc_mode, int, 0444); module_param(video_debug, int, 0444); -module_param(PowerOnAtOpen, int, 0444); +module_param(power_on_at_open, int, 0444); module_param(video_nr, int, 0444); module_param(radio_nr, int, 0444); -MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); +MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); -MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); +MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened. Default: 1 (On)"); MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); -// Misc stuff +/* Misc stuff */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE(DRIVER_LICENSE); @@ -192,7 +192,7 @@ static ssize_t show_model(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - usbvision_device_data[usbvision->DevModel].ModelString); + usbvision_device_data[usbvision->dev_model].model_string); } static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); @@ -205,7 +205,7 @@ static ssize_t show_hue(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -220,7 +220,7 @@ static ssize_t show_contrast(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -235,7 +235,7 @@ static ssize_t show_brightness(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -250,7 +250,7 @@ static ssize_t show_saturation(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -263,7 +263,7 @@ static ssize_t show_streaming(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - YES_NO(usbvision->streaming==Stream_On?1:0)); + YES_NO(usbvision->streaming == stream_on ? 1 : 0)); } static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); @@ -274,7 +274,7 @@ static ssize_t show_compression(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); + YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS)); } static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); @@ -284,42 +284,43 @@ static ssize_t show_device_bridge(struct device *cd, struct video_device *vdev = container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%d\n", usbvision->bridgeType); + return sprintf(buf, "%d\n", usbvision->bridge_type); } static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); static void usbvision_create_sysfs(struct video_device *vdev) { int res; + if (!vdev) return; do { res = device_create_file(&vdev->dev, &dev_attr_version); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_model); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_hue); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_contrast); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_brightness); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_saturation); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_streaming); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_compression); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_bridge); - if (res>=0) + if (res >= 0) return; } while (0); @@ -352,24 +353,23 @@ static void usbvision_remove_sysfs(struct video_device *vdev) static int usbvision_v4l2_open(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IO, "open"); - mutex_lock(&usbvision->lock); - usbvision_reset_powerOffTimer(usbvision); + usbvision_reset_power_off_timer(usbvision); if (usbvision->user) - errCode = -EBUSY; + err_code = -EBUSY; else { /* Allocate memory for the scratch ring buffer */ - errCode = usbvision_scratch_alloc(usbvision); - if (isocMode==ISOC_MODE_COMPRESS) { + err_code = usbvision_scratch_alloc(usbvision); + if (isoc_mode == ISOC_MODE_COMPRESS) { /* Allocate intermediate decompression buffers only if needed */ - errCode = usbvision_decompress_alloc(usbvision); + err_code = usbvision_decompress_alloc(usbvision); } - if (errCode) { + if (err_code) { /* Deallocate all buffers if trouble */ usbvision_scratch_free(usbvision); usbvision_decompress_free(usbvision); @@ -377,7 +377,7 @@ static int usbvision_v4l2_open(struct file *file) } /* If so far no errors then we shall start the camera */ - if (!errCode) { + if (!err_code) { if (usbvision->power == 0) { usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); @@ -386,21 +386,21 @@ static int usbvision_v4l2_open(struct file *file) /* Send init sequence only once, it's large! */ if (!usbvision->initialized) { int setup_ok = 0; - setup_ok = usbvision_setup(usbvision,isocMode); + setup_ok = usbvision_setup(usbvision, isoc_mode); if (setup_ok) usbvision->initialized = 1; else - errCode = -EBUSY; + err_code = -EBUSY; } - if (!errCode) { + if (!err_code) { usbvision_begin_streaming(usbvision); - errCode = usbvision_init_isoc(usbvision); + err_code = usbvision_init_isoc(usbvision); /* device must be initialized before isoc transfer */ - usbvision_muxsel(usbvision,0); + usbvision_muxsel(usbvision, 0); usbvision->user++; } else { - if (PowerOnAtOpen) { + if (power_on_at_open) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; @@ -412,8 +412,7 @@ static int usbvision_v4l2_open(struct file *file) usbvision_empty_framequeues(usbvision); PDEBUG(DBG_IO, "success"); - mutex_unlock(&usbvision->lock); - return errCode; + return err_code; } /* @@ -429,7 +428,6 @@ static int usbvision_v4l2_close(struct file *file) struct usb_usbvision *usbvision = video_drvdata(file); PDEBUG(DBG_IO, "close"); - mutex_lock(&usbvision->lock); usbvision_audio_off(usbvision); usbvision_restart_isoc(usbvision); @@ -442,15 +440,13 @@ static int usbvision_v4l2_close(struct file *file) usbvision->user--; - if (PowerOnAtOpen) { + if (power_on_at_open) { /* power off in a little while to avoid off/on every close/open short sequences */ - usbvision_set_powerOffTimer(usbvision); + usbvision_set_power_off_timer(usbvision); usbvision->initialized = 0; } - mutex_unlock(&usbvision->lock); - if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); @@ -468,55 +464,55 @@ static int usbvision_v4l2_close(struct file *file) * */ #ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register (struct file *file, void *priv, +static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode; + int err_code; if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - if (errCode < 0) { + err_code = usbvision_read_reg(usbvision, reg->reg&0xff); + if (err_code < 0) { dev_err(&usbvision->vdev->dev, "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n", - __func__, errCode); - return errCode; + __func__, err_code); + return err_code; } - reg->val = errCode; + reg->val = err_code; reg->size = 1; return 0; } -static int vidioc_s_register (struct file *file, void *priv, +static int vidioc_s_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode; + int err_code; if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (errCode < 0) { + err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val); + if (err_code < 0) { dev_err(&usbvision->vdev->dev, "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n", - __func__, errCode); - return errCode; + __func__, err_code); + return err_code; } return 0; } #endif -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *vc) { struct usb_usbvision *usbvision = video_drvdata(file); strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); strlcpy(vc->card, - usbvision_device_data[usbvision->DevModel].ModelString, + usbvision_device_data[usbvision->dev_model].model_string, sizeof(vc->card)); usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info)); vc->version = USBVISION_DRIVER_VERSION; @@ -528,7 +524,7 @@ static int vidioc_querycap (struct file *file, void *priv, return 0; } -static int vidioc_enum_input (struct file *file, void *priv, +static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *vi) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -536,16 +532,16 @@ static int vidioc_enum_input (struct file *file, void *priv, if (vi->index >= usbvision->video_inputs) return -EINVAL; - if (usbvision->have_tuner) { + if (usbvision->have_tuner) chan = vi->index; - } else { - chan = vi->index + 1; /*skip Television string*/ - } + else + chan = vi->index + 1; /* skip Television string*/ + /* Determine the requested input characteristics specific for each usbvision card model */ - switch(chan) { + switch (chan) { case 0: - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { strcpy(vi->name, "White Video Input"); } else { strcpy(vi->name, "Television"); @@ -557,20 +553,18 @@ static int vidioc_enum_input (struct file *file, void *priv, break; case 1: vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) strcpy(vi->name, "Green Video Input"); - } else { + else strcpy(vi->name, "Composite Video Input"); - } vi->std = V4L2_STD_PAL; break; case 2: vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) strcpy(vi->name, "Yellow Video Input"); - } else { + else strcpy(vi->name, "S-Video Input"); - } vi->std = V4L2_STD_PAL; break; case 3: @@ -582,7 +576,7 @@ static int vidioc_enum_input (struct file *file, void *priv, return 0; } -static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) +static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -590,46 +584,42 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) return 0; } -static int vidioc_s_input (struct file *file, void *priv, unsigned int input) +static int vidioc_s_input(struct file *file, void *priv, unsigned int input) { struct usb_usbvision *usbvision = video_drvdata(file); if (input >= usbvision->video_inputs) return -EINVAL; - mutex_lock(&usbvision->lock); usbvision_muxsel(usbvision, input); usbvision_set_input(usbvision); usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); - mutex_unlock(&usbvision->lock); return 0; } -static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) { struct usb_usbvision *usbvision = video_drvdata(file); - usbvision->tvnormId=*id; + usbvision->tvnorm_id = *id; - mutex_lock(&usbvision->lock); - call_all(usbvision, core, s_std, usbvision->tvnormId); - mutex_unlock(&usbvision->lock); + call_all(usbvision, core, s_std, usbvision->tvnorm_id); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct usb_usbvision *usbvision = video_drvdata(file); - if (!usbvision->have_tuner || vt->index) // Only tuner 0 + if (!usbvision->have_tuner || vt->index) /* Only tuner 0 */ return -EINVAL; - if(usbvision->radio) { + if (usbvision->radio) { strcpy(vt->name, "Radio"); vt->type = V4L2_TUNER_RADIO; } else { @@ -641,12 +631,12 @@ static int vidioc_g_tuner (struct file *file, void *priv, return 0; } -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct usb_usbvision *usbvision = video_drvdata(file); - // Only no or one tuner for now + /* Only no or one tuner for now */ if (!usbvision->have_tuner || vt->index) return -EINVAL; /* let clients handle this */ @@ -655,28 +645,27 @@ static int vidioc_s_tuner (struct file *file, void *priv, return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { struct usb_usbvision *usbvision = video_drvdata(file); - freq->tuner = 0; // Only one tuner - if(usbvision->radio) { + freq->tuner = 0; /* Only one tuner */ + if (usbvision->radio) freq->type = V4L2_TUNER_RADIO; - } else { + else freq->type = V4L2_TUNER_ANALOG_TV; - } freq->frequency = usbvision->freq; return 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { struct usb_usbvision *usbvision = video_drvdata(file); - // Only no or one tuner for now + /* Only no or one tuner for now */ if (!usbvision->have_tuner || freq->tuner) return -EINVAL; @@ -686,30 +675,27 @@ static int vidioc_s_frequency (struct file *file, void *priv, return 0; } -static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { struct usb_usbvision *usbvision = video_drvdata(file); - if(usbvision->radio) { - strcpy(a->name,"Radio"); - } else { + if (usbvision->radio) + strcpy(a->name, "Radio"); + else strcpy(a->name, "TV"); - } return 0; } -static int vidioc_s_audio (struct file *file, void *fh, +static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { - if(a->index) { + if (a->index) return -EINVAL; - } - return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -722,52 +708,53 @@ static int vidioc_queryctrl (struct file *file, void *priv, return 0; } -static int vidioc_g_ctrl (struct file *file, void *priv, +static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_all(usbvision, core, g_ctrl, ctrl); + call_all(usbvision, core, g_ctrl, ctrl); return 0; } -static int vidioc_s_ctrl (struct file *file, void *priv, +static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_all(usbvision, core, s_ctrl, ctrl); + call_all(usbvision, core, s_ctrl, ctrl); return 0; } -static int vidioc_reqbufs (struct file *file, +static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *vr) { struct usb_usbvision *usbvision = video_drvdata(file); int ret; - RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); + RESTRICT_TO_RANGE(vr->count, 1, USBVISION_NUMFRAMES); /* Check input validity: the user must do a VIDEO CAPTURE and MMAP method. */ if (vr->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) + if (usbvision->streaming == stream_on) { + ret = usbvision_stream_interrupt(usbvision); + if (ret) return ret; } usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); - vr->count = usbvision_frames_alloc(usbvision,vr->count); + vr->count = usbvision_frames_alloc(usbvision, vr->count); - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; return 0; } -static int vidioc_querybuf (struct file *file, +static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *vb) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -775,52 +762,49 @@ static int vidioc_querybuf (struct file *file, /* FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) */ - if(vb->index>=usbvision->num_frames) { + if (vb->index >= usbvision->num_frames) return -EINVAL; - } /* Updating the corresponding frame state */ vb->flags = 0; frame = &usbvision->frame[vb->index]; - if(frame->grabstate >= FrameState_Ready) + if (frame->grabstate >= frame_state_ready) vb->flags |= V4L2_BUF_FLAG_QUEUED; - if(frame->grabstate >= FrameState_Done) + if (frame->grabstate >= frame_state_done) vb->flags |= V4L2_BUF_FLAG_DONE; - if(frame->grabstate == FrameState_Unused) + if (frame->grabstate == frame_state_unused) vb->flags |= V4L2_BUF_FLAG_MAPPED; vb->memory = V4L2_MEMORY_MMAP; - vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); + vb->m.offset = vb->index * PAGE_ALIGN(usbvision->max_frame_size); vb->memory = V4L2_MEMORY_MMAP; vb->field = V4L2_FIELD_NONE; - vb->length = usbvision->curwidth* - usbvision->curheight* + vb->length = usbvision->curwidth * + usbvision->curheight * usbvision->palette.bytes_per_pixel; vb->timestamp = usbvision->frame[vb->index].timestamp; vb->sequence = usbvision->frame[vb->index].sequence; return 0; } -static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *vb) { struct usb_usbvision *usbvision = video_drvdata(file); struct usbvision_frame *frame; unsigned long lock_flags; /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ - if(vb->index>=usbvision->num_frames) { + if (vb->index >= usbvision->num_frames) return -EINVAL; - } frame = &usbvision->frame[vb->index]; - if (frame->grabstate != FrameState_Unused) { + if (frame->grabstate != frame_state_unused) return -EAGAIN; - } /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; + frame->grabstate = frame_state_ready; + frame->scanstate = scan_state_scanning; frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ vb->flags &= ~V4L2_BUF_FLAG_DONE; @@ -835,7 +819,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) return 0; } -static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb) { struct usb_usbvision *usbvision = video_drvdata(file); int ret; @@ -843,7 +827,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) unsigned long lock_flags; if (list_empty(&(usbvision->outqueue))) { - if (usbvision->streaming == Stream_Idle) + if (usbvision->streaming == stream_idle) return -EINVAL; ret = wait_event_interruptible (usbvision->wait_frame, @@ -858,7 +842,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) list_del(usbvision->outqueue.next); spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - f->grabstate = FrameState_Unused; + f->grabstate = frame_state_unused; vb->memory = V4L2_MEMORY_MMAP; vb->flags = V4L2_BUF_FLAG_MAPPED | @@ -877,7 +861,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct usb_usbvision *usbvision = video_drvdata(file); - usbvision->streaming = Stream_On; + usbvision->streaming = stream_on; call_all(usbvision, video, s_stream, 1); return 0; @@ -891,7 +875,7 @@ static int vidioc_streamoff(struct file *file, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if(usbvision->streaming == Stream_On) { + if (usbvision->streaming == stream_on) { usbvision_stream_interrupt(usbvision); /* Stop all video streamings */ call_all(usbvision, video, s_stream, 0); @@ -901,18 +885,17 @@ static int vidioc_streamoff(struct file *file, return 0; } -static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *vfd) { - if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { + if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1) return -EINVAL; - } - strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); + strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; return 0; } -static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -920,32 +903,31 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, vf->fmt.pix.height = usbvision->curheight; vf->fmt.pix.pixelformat = usbvision->palette.format; vf->fmt.pix.bytesperline = - usbvision->curwidth*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; + usbvision->curwidth * usbvision->palette.bytes_per_pixel; + vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline * usbvision->curheight; vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ return 0; } -static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { struct usb_usbvision *usbvision = video_drvdata(file); - int formatIdx; + int format_idx; /* Find requested format in available ones */ - for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) { - if(vf->fmt.pix.pixelformat == - usbvision_v4l2_format[formatIdx].format) { - usbvision->palette = usbvision_v4l2_format[formatIdx]; + for (format_idx = 0; format_idx < USBVISION_SUPPORTED_PALETTES; format_idx++) { + if (vf->fmt.pix.pixelformat == + usbvision_v4l2_format[format_idx].format) { + usbvision->palette = usbvision_v4l2_format[format_idx]; break; } } /* robustness */ - if(formatIdx == USBVISION_SUPPORTED_PALETTES) { + if (format_idx == USBVISION_SUPPORTED_PALETTES) return -EINVAL; - } RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); @@ -962,24 +944,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int ret; - if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { + ret = vidioc_try_fmt_vid_cap(file, priv, vf); + if (ret) return ret; - } /* stop io in case it is already in progress */ - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) + if (usbvision->streaming == stream_on) { + ret = usbvision_stream_interrupt(usbvision); + if (ret) return ret; } usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; /* by now we are committed to the new data... */ - mutex_lock(&usbvision->lock); usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); - mutex_unlock(&usbvision->lock); return 0; } @@ -990,8 +971,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, struct usb_usbvision *usbvision = video_drvdata(file); int noblock = file->f_flags & O_NONBLOCK; unsigned long lock_flags; - - int ret,i; + int ret, i; struct usbvision_frame *frame; PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__, @@ -1003,28 +983,28 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, /* This entry point is compatible with the mmap routines so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */ - if(!usbvision->num_frames) { + if (!usbvision->num_frames) { /* First, allocate some frames to work with if this has not been done with VIDIOC_REQBUF */ usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); - usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES); + usbvision_frames_alloc(usbvision, USBVISION_NUMFRAMES); } - if(usbvision->streaming != Stream_On) { + if (usbvision->streaming != stream_on) { /* no stream is running, make it running ! */ - usbvision->streaming = Stream_On; + usbvision->streaming = stream_on; call_all(usbvision, video, s_stream, 1); } /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ - for(i=0;i<usbvision->num_frames;i++) { + for (i = 0; i < usbvision->num_frames; i++) { frame = &usbvision->frame[i]; - if(frame->grabstate == FrameState_Unused) { + if (frame->grabstate == frame_state_unused) { /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; + frame->grabstate = frame_state_ready; + frame->scanstate = scan_state_scanning; /* Accumulated in usbvision_parse_data() */ frame->scanlength = 0; @@ -1040,7 +1020,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ if (list_empty(&(usbvision->outqueue))) { - if(noblock) + if (noblock) return -EAGAIN; ret = wait_event_interruptible @@ -1057,7 +1037,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); /* An error returns an empty frame */ - if (frame->grabstate == FrameState_Error) { + if (frame->grabstate == frame_state_error) { frame->bytes_read = 0; return 0; } @@ -1070,9 +1050,8 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) count = frame->scanlength - frame->bytes_read; - if (copy_to_user(buf, frame->data + frame->bytes_read, count)) { + if (copy_to_user(buf, frame->data + frame->bytes_read, count)) return -EFAULT; - } frame->bytes_read += count; PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", @@ -1080,12 +1059,12 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, (unsigned long)count, frame->bytes_read); /* For now, forget the frame if it has not been read in one shot. */ -/* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ +/* if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */ frame->bytes_read = 0; /* Mark it as available to be used again. */ - frame->grabstate = FrameState_Unused; -/* } */ + frame->grabstate = frame_state_unused; +/* } */ return count; } @@ -1100,16 +1079,11 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) PDEBUG(DBG_MMAP, "mmap"); - mutex_lock(&usbvision->lock); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) { - mutex_unlock(&usbvision->lock); + if (!USBVISION_IS_OPERATIONAL(usbvision)) return -EFAULT; - } if (!(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(usbvision->max_frame_size)) { - mutex_unlock(&usbvision->lock); return -EINVAL; } @@ -1121,7 +1095,6 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) if (i == usbvision->num_frames) { PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); - mutex_unlock(&usbvision->lock); return -EINVAL; } @@ -1131,10 +1104,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) pos = usbvision->frame[i].data; while (size > 0) { - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); - mutex_unlock(&usbvision->lock); return -EAGAIN; } start += PAGE_SIZE; @@ -1142,7 +1113,6 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) size -= PAGE_SIZE; } - mutex_unlock(&usbvision->lock); return 0; } @@ -1154,21 +1124,18 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) static int usbvision_radio_open(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IO, "%s:", __func__); - mutex_lock(&usbvision->lock); - if (usbvision->user) { dev_err(&usbvision->rdev->dev, "%s: Someone tried to open an already opened USBVision Radio!\n", __func__); - errCode = -EBUSY; - } - else { - if(PowerOnAtOpen) { - usbvision_reset_powerOffTimer(usbvision); + err_code = -EBUSY; + } else { + if (power_on_at_open) { + usbvision_reset_power_off_timer(usbvision); if (usbvision->power == 0) { usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); @@ -1176,80 +1143,73 @@ static int usbvision_radio_open(struct file *file) } /* Alternate interface 1 is is the biggest frame size */ - errCode = usbvision_set_alternate(usbvision); - if (errCode < 0) { - usbvision->last_error = errCode; - errCode = -EBUSY; + err_code = usbvision_set_alternate(usbvision); + if (err_code < 0) { + usbvision->last_error = err_code; + err_code = -EBUSY; goto out; } - // If so far no errors then we shall start the radio + /* If so far no errors then we shall start the radio */ usbvision->radio = 1; call_all(usbvision, tuner, s_radio); usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); usbvision->user++; } - if (errCode) { - if (PowerOnAtOpen) { + if (err_code) { + if (power_on_at_open) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; } } out: - mutex_unlock(&usbvision->lock); - return errCode; + return err_code; } static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IO, ""); - mutex_lock(&usbvision->lock); - /* Set packet size to 0 */ - usbvision->ifaceAlt=0; - errCode = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->ifaceAlt); + usbvision->iface_alt = 0; + err_code = usb_set_interface(usbvision->dev, usbvision->iface, + usbvision->iface_alt); usbvision_audio_off(usbvision); - usbvision->radio=0; + usbvision->radio = 0; usbvision->user--; - if (PowerOnAtOpen) { - usbvision_set_powerOffTimer(usbvision); + if (power_on_at_open) { + usbvision_set_power_off_timer(usbvision); usbvision->initialized = 0; } - mutex_unlock(&usbvision->lock); - if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); } PDEBUG(DBG_IO, "success"); - return errCode; + return err_code; } -// -// Video registration stuff -// +/* Video registration stuff */ -// Video template +/* Video template */ static const struct v4l2_file_operations usbvision_fops = { .owner = THIS_MODULE, .open = usbvision_v4l2_open, .release = usbvision_v4l2_close, .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, - .ioctl = video_ioctl2, -/* .poll = video_poll, */ + .unlocked_ioctl = video_ioctl2, +/* .poll = video_poll, */ }; static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { @@ -1273,9 +1233,6 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* .vidiocgmbuf = vidiocgmbuf, */ -#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, @@ -1288,20 +1245,20 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { static struct video_device usbvision_video_template = { .fops = &usbvision_fops, - .ioctl_ops = &usbvision_ioctl_ops, + .ioctl_ops = &usbvision_ioctl_ops, .name = "usbvision-video", .release = video_device_release, - .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL + .tvnorms = USBVISION_NORMS, + .current_norm = V4L2_STD_PAL }; -// Radio template +/* Radio template */ static const struct v4l2_file_operations usbvision_radio_fops = { .owner = THIS_MODULE, .open = usbvision_radio_open, .release = usbvision_radio_close, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { @@ -1322,9 +1279,9 @@ static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { static struct video_device usbvision_radio_template = { .fops = &usbvision_radio_fops, - .name = "usbvision-radio", + .name = "usbvision-radio", .release = video_device_release, - .ioctl_ops = &usbvision_radio_ioctl_ops, + .ioctl_ops = &usbvision_radio_ioctl_ops, .tvnorms = USBVISION_NORMS, .current_norm = V4L2_STD_PAL @@ -1345,80 +1302,70 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, } vdev = video_device_alloc(); - if (NULL == vdev) { + if (NULL == vdev) return NULL; - } *vdev = *vdev_template; + vdev->lock = &usbvision->v4l2_lock; vdev->v4l2_dev = &usbvision->v4l2_dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); video_set_drvdata(vdev, usbvision); return vdev; } -// unregister video4linux devices +/* unregister video4linux devices */ static void usbvision_unregister_video(struct usb_usbvision *usbvision) { - // Radio Device: + /* Radio Device: */ if (usbvision->rdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->rdev)); - if (video_is_registered(usbvision->rdev)) { + if (video_is_registered(usbvision->rdev)) video_unregister_device(usbvision->rdev); - } else { + else video_device_release(usbvision->rdev); - } usbvision->rdev = NULL; } - // Video Device: + /* Video Device: */ if (usbvision->vdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->vdev)); - if (video_is_registered(usbvision->vdev)) { + if (video_is_registered(usbvision->vdev)) video_unregister_device(usbvision->vdev); - } else { + else video_device_release(usbvision->vdev); - } usbvision->vdev = NULL; } } -// register video4linux devices +/* register video4linux devices */ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) { - // Video Device: + /* Video Device: */ usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); - if (usbvision->vdev == NULL) { + if (usbvision->vdev == NULL) goto err_exit; - } - if (video_register_device(usbvision->vdev, - VFL_TYPE_GRABBER, - video_nr)<0) { + if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0) goto err_exit; - } printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->vdev)); - // Radio Device: - if (usbvision_device_data[usbvision->DevModel].Radio) { - // usbvision has radio + /* Radio Device: */ + if (usbvision_device_data[usbvision->dev_model].radio) { + /* usbvision has radio */ usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); - if (usbvision->rdev == NULL) { + if (usbvision->rdev == NULL) goto err_exit; - } - if (video_register_device(usbvision->rdev, - VFL_TYPE_RADIO, - radio_nr)<0) { + if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0) goto err_exit; - } printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->rdev)); } - // all done + /* all done */ return 0; err_exit: @@ -1451,15 +1398,15 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev)) goto err_free; - mutex_init(&usbvision->lock); /* available */ + mutex_init(&usbvision->v4l2_lock); - // prepare control urb for control messages during interrupts - usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (usbvision->ctrlUrb == NULL) + /* prepare control urb for control messages during interrupts */ + usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); + if (usbvision->ctrl_urb == NULL) goto err_unreg; - init_waitqueue_head(&usbvision->ctrlUrb_wq); + init_waitqueue_head(&usbvision->ctrl_urb_wq); - usbvision_init_powerOffTimer(usbvision); + usbvision_init_power_off_timer(usbvision); return usbvision; @@ -1481,20 +1428,14 @@ static void usbvision_release(struct usb_usbvision *usbvision) { PDEBUG(DBG_PROBE, ""); - mutex_lock(&usbvision->lock); - - usbvision_reset_powerOffTimer(usbvision); + usbvision_reset_power_off_timer(usbvision); usbvision->initialized = 0; - mutex_unlock(&usbvision->lock); - usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); - if (usbvision->ctrlUrb) { - usb_free_urb(usbvision->ctrlUrb); - } + usb_free_urb(usbvision->ctrl_urb); v4l2_device_unregister(&usbvision->v4l2_dev); kfree(usbvision); @@ -1512,25 +1453,25 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) if (usbvision == NULL) return; - model = usbvision->DevModel; - usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; + model = usbvision->dev_model; + usbvision->palette = usbvision_v4l2_format[2]; /* V4L2_PIX_FMT_RGB24; */ - if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) { - usbvision->Vin_Reg2_Preset = - usbvision_device_data[usbvision->DevModel].Vin_Reg2; + if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) { + usbvision->vin_reg2_preset = + usbvision_device_data[usbvision->dev_model].vin_reg2; } else { - usbvision->Vin_Reg2_Preset = 0; + usbvision->vin_reg2_preset = 0; } - usbvision->tvnormId = usbvision_device_data[model].VideoNorm; + usbvision->tvnorm_id = usbvision_device_data[model].video_norm; - usbvision->video_inputs = usbvision_device_data[model].VideoChannels; + usbvision->video_inputs = usbvision_device_data[model].video_channels; usbvision->ctl_input = 0; /* This should be here to make i2c clients to be able to register */ /* first switch off audio */ usbvision_audio_off(usbvision); - if (!PowerOnAtOpen) { + if (!power_on_at_open) { /* and then power up the noisy tuner */ usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); @@ -1553,25 +1494,24 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_host_interface *interface; struct usb_usbvision *usbvision = NULL; const struct usb_endpoint_descriptor *endpoint; - int model,i; + int model, i; PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); model = devid->driver_info; - if ( (model<0) || (model>=usbvision_device_data_size) ) { - PDEBUG(DBG_PROBE, "model out of bounds %d",model); + if (model < 0 || model >= usbvision_device_data_size) { + PDEBUG(DBG_PROBE, "model out of bounds %d", model); return -ENODEV; } printk(KERN_INFO "%s: %s found\n", __func__, - usbvision_device_data[model].ModelString); + usbvision_device_data[model].model_string); - if (usbvision_device_data[model].Interface >= 0) { - interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; - } else { + if (usbvision_device_data[model].interface >= 0) + interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0]; + else interface = &dev->actconfig->interface[ifnum]->altsetting[0]; - } endpoint = &interface->endpoint[1].desc; if (!usb_endpoint_xfer_isoc(endpoint)) { dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n", @@ -1592,59 +1532,52 @@ static int __devinit usbvision_probe(struct usb_interface *intf, return -ENOMEM; } - if (dev->descriptor.bNumConfigurations > 1) { - usbvision->bridgeType = BRIDGE_NT1004; - } else if (model == DAZZLE_DVC_90_REV_1_SECAM) { - usbvision->bridgeType = BRIDGE_NT1005; - } else { - usbvision->bridgeType = BRIDGE_NT1003; - } - PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); - - mutex_lock(&usbvision->lock); + if (dev->descriptor.bNumConfigurations > 1) + usbvision->bridge_type = BRIDGE_NT1004; + else if (model == DAZZLE_DVC_90_REV_1_SECAM) + usbvision->bridge_type = BRIDGE_NT1005; + else + usbvision->bridge_type = BRIDGE_NT1003; + PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type); /* compute alternate max packet sizes */ uif = dev->actconfig->interface[0]; - usbvision->num_alt=uif->num_altsetting; - PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt); - usbvision->alt_max_pkt_size = kmalloc(32* - usbvision->num_alt,GFP_KERNEL); + usbvision->num_alt = uif->num_altsetting; + PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt); + usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { dev_err(&intf->dev, "usbvision: out of memory!\n"); - mutex_unlock(&usbvision->lock); return -ENOMEM; } - for (i = 0; i < usbvision->num_alt ; i++) { + for (i = 0; i < usbvision->num_alt; i++) { u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); usbvision->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i, + PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i", i, usbvision->alt_max_pkt_size[i]); } usbvision->nr = usbvision_nr++; - usbvision->have_tuner = usbvision_device_data[model].Tuner; - if (usbvision->have_tuner) { - usbvision->tuner_type = usbvision_device_data[model].TunerType; - } + usbvision->have_tuner = usbvision_device_data[model].tuner; + if (usbvision->have_tuner) + usbvision->tuner_type = usbvision_device_data[model].tuner_type; - usbvision->DevModel = model; + usbvision->dev_model = model; usbvision->remove_pending = 0; usbvision->iface = ifnum; - usbvision->ifaceAlt = 0; + usbvision->iface_alt = 0; usbvision->video_endp = endpoint->bEndpointAddress; - usbvision->isocPacketSize = 0; + usbvision->isoc_packet_size = 0; usbvision->usb_bandwidth = 0; usbvision->user = 0; - usbvision->streaming = Stream_Off; + usbvision->streaming = stream_off; usbvision_configure_video(usbvision); usbvision_register_video(usbvision); - mutex_unlock(&usbvision->lock); usbvision_create_sysfs(usbvision->vdev); @@ -1672,9 +1605,9 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) return; } - mutex_lock(&usbvision->lock); + mutex_lock(&usbvision->v4l2_lock); - // At this time we ask to cancel outstanding URBs + /* At this time we ask to cancel outstanding URBs */ usbvision_stop_isoc(usbvision); v4l2_device_disconnect(&usbvision->v4l2_dev); @@ -1683,12 +1616,12 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); } - usbvision->remove_pending = 1; // Now all ISO data will be ignored + usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ usb_put_dev(usbvision->dev); - usbvision->dev = NULL; // USB device is no more + usbvision->dev = NULL; /* USB device is no more */ - mutex_unlock(&usbvision->lock); + mutex_unlock(&usbvision->v4l2_lock); if (usbvision->user) { printk(KERN_INFO "%s: In use, disconnect pending\n", @@ -1717,7 +1650,7 @@ static struct usb_driver usbvision_driver = { */ static int __init usbvision_init(void) { - int errCode; + int err_code; PDEBUG(DBG_PROBE, ""); @@ -1726,27 +1659,27 @@ static int __init usbvision_init(void) PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); /* disable planar mode support unless compression enabled */ - if (isocMode != ISOC_MODE_COMPRESS ) { - // FIXME : not the right way to set supported flag - usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 - usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P + if (isoc_mode != ISOC_MODE_COMPRESS) { + /* FIXME : not the right way to set supported flag */ + usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */ + usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */ } - errCode = usb_register(&usbvision_driver); + err_code = usb_register(&usbvision_driver); - if (errCode == 0) { + if (err_code == 0) { printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n"); PDEBUG(DBG_PROBE, "success"); } - return errCode; + return err_code; } static void __exit usbvision_exit(void) { - PDEBUG(DBG_PROBE, ""); + PDEBUG(DBG_PROBE, ""); - usb_deregister(&usbvision_driver); - PDEBUG(DBG_PROBE, "success"); + usb_deregister(&usbvision_driver); + PDEBUG(DBG_PROBE, "success"); } module_init(usbvision_init); diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index cc4e96c8cd6..8074787fd1a 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -132,15 +132,15 @@ #define MAX_BYTES_PER_PIXEL 4 #define MIN_FRAME_WIDTH 64 -#define MAX_USB_WIDTH 320 //384 -#define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/ +#define MAX_USB_WIDTH 320 /* 384 */ +#define MAX_FRAME_WIDTH 320 /* 384 */ /* streching sometimes causes crashes*/ #define MIN_FRAME_HEIGHT 48 -#define MAX_USB_HEIGHT 240 //288 -#define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/ +#define MAX_USB_HEIGHT 240 /* 288 */ +#define MAX_FRAME_HEIGHT 240 /* 288 */ /* Streching sometimes causes crashes*/ -#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) -#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask +#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) +#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */ #define USBVISION_URB_FRAMES 32 @@ -148,7 +148,7 @@ #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ #define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ -#define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds +#define USBVISION_POWEROFF_TIME (3 * HZ) /* 3 seconds */ #define FRAMERATE_MIN 0 @@ -161,7 +161,8 @@ enum { }; /* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } +#define RESTRICT_TO_RANGE(v, mi, ma) \ + { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } /* * We use macros to do YUV -> RGB conversion because this is @@ -183,18 +184,18 @@ enum { * Make sure the output values are within [0..255] range. */ #define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc= mm_y * 76284; \ - mm_b = (mm_yc + 132252*mm_v ) >> 16; \ - mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ - mm_r = (mm_yc + 104595*mm_u ) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ +#define YUV_TO_RGB_BY_THE_BOOK(my, mu, mv, mr, mg, mb) { \ + int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ + mm_y = (my) - 16; \ + mm_u = (mu) - 128; \ + mm_v = (mv) - 128; \ + mm_yc = mm_y * 76284; \ + mm_b = (mm_yc + 132252 * mm_v) >> 16; \ + mm_g = (mm_yc - 53281 * mm_u - 25625 * mm_v) >> 16; \ + mm_r = (mm_yc + 104595 * mm_u) >> 16; \ + mb = LIMIT_RGB(mm_b); \ + mg = LIMIT_RGB(mm_g); \ + mr = LIMIT_RGB(mm_r); \ } /* Debugging aid */ @@ -202,7 +203,7 @@ enum { wait_queue_head_t wq; \ init_waitqueue_head(&wq); \ printk(KERN_INFO "Say: %s\n", what); \ - interruptible_sleep_on_timeout (&wq, HZ*3); \ + interruptible_sleep_on_timeout(&wq, HZ * 3); \ } /* @@ -223,39 +224,39 @@ enum { /* ----------------------------------------------------------------- */ /* usbvision video structures */ /* ----------------------------------------------------------------- */ -enum ScanState { - ScanState_Scanning, /* Scanning for header */ - ScanState_Lines /* Parsing lines */ +enum scan_state { + scan_state_scanning, /* Scanning for header */ + scan_state_lines /* Parsing lines */ }; /* Completion states of the data parser */ -enum ParseState { - ParseState_Continue, /* Just parse next item */ - ParseState_NextFrame, /* Frame done, send it to V4L */ - ParseState_Out, /* Not enough data for frame */ - ParseState_EndParse /* End parsing */ +enum parse_state { + parse_state_continue, /* Just parse next item */ + parse_state_next_frame, /* Frame done, send it to V4L */ + parse_state_out, /* Not enough data for frame */ + parse_state_end_parse /* End parsing */ }; -enum FrameState { - FrameState_Unused, /* Unused (no MCAPTURE) */ - FrameState_Ready, /* Ready to start grabbing */ - FrameState_Grabbing, /* In the process of being grabbed into */ - FrameState_Done, /* Finished grabbing, but not been synced yet */ - FrameState_DoneHold, /* Are syncing or reading */ - FrameState_Error, /* Something bad happened while processing */ +enum frame_state { + frame_state_unused, /* Unused (no MCAPTURE) */ + frame_state_ready, /* Ready to start grabbing */ + frame_state_grabbing, /* In the process of being grabbed into */ + frame_state_done, /* Finished grabbing, but not been synced yet */ + frame_state_done_hold, /* Are syncing or reading */ + frame_state_error, /* Something bad happened while processing */ }; /* stream states */ -enum StreamState { - Stream_Off, /* Driver streaming is completely OFF */ - Stream_Idle, /* Driver streaming is ready to be put ON by the application */ - Stream_Interrupt, /* Driver streaming must be interrupted */ - Stream_On, /* Driver streaming is put ON by the application */ +enum stream_state { + stream_off, /* Driver streaming is completely OFF */ + stream_idle, /* Driver streaming is ready to be put ON by the application */ + stream_interrupt, /* Driver streaming must be interrupted */ + stream_on, /* Driver streaming is put ON by the application */ }; -enum IsocState { - IsocState_InFrame, /* Isoc packet is member of frame */ - IsocState_NoFrame, /* Isoc packet is not member of any frame */ +enum isoc_state { + isoc_state_in_frame, /* Isoc packet is member of frame */ + isoc_state_no_frame, /* Isoc packet is not member of any frame */ }; struct usb_device; @@ -265,8 +266,8 @@ struct usbvision_sbuf { struct urb *urb; }; -#define USBVISION_MAGIC_1 0x55 -#define USBVISION_MAGIC_2 0xAA +#define USBVISION_MAGIC_1 0x55 +#define USBVISION_MAGIC_2 0xAA #define USBVISION_HEADER_LENGTH 0x0c #define USBVISION_SAA7111_ADDR 0x48 #define USBVISION_SAA7113_ADDR 0x4a @@ -286,23 +287,23 @@ struct usbvision_v4l2_format_st { struct usbvision_frame_header { unsigned char magic_1; /* 0 magic */ unsigned char magic_2; /* 1 magic */ - unsigned char headerLength; /* 2 */ - unsigned char frameNum; /* 3 */ - unsigned char framePhase; /* 4 */ - unsigned char frameLatency; /* 5 */ - unsigned char dataFormat; /* 6 */ - unsigned char formatParam; /* 7 */ - unsigned char frameWidthLo; /* 8 */ - unsigned char frameWidthHi; /* 9 */ - unsigned char frameHeightLo; /* 10 */ - unsigned char frameHeightHi; /* 11 */ - __u16 frameWidth; /* 8 - 9 after endian correction*/ - __u16 frameHeight; /* 10 - 11 after endian correction*/ + unsigned char header_length; /* 2 */ + unsigned char frame_num; /* 3 */ + unsigned char frame_phase; /* 4 */ + unsigned char frame_latency; /* 5 */ + unsigned char data_format; /* 6 */ + unsigned char format_param; /* 7 */ + unsigned char frame_width_lo; /* 8 */ + unsigned char frame_width_hi; /* 9 */ + unsigned char frame_height_lo; /* 10 */ + unsigned char frame_height_hi; /* 11 */ + __u16 frame_width; /* 8 - 9 after endian correction*/ + __u16 frame_height; /* 10 - 11 after endian correction*/ }; struct usbvision_frame { char *data; /* Frame buffer */ - struct usbvision_frame_header isocHeader; /* Header from stream */ + struct usbvision_frame_header isoc_header; /* Header from stream */ int width; /* Width application is expecting */ int height; /* Height */ @@ -322,7 +323,7 @@ struct usbvision_frame { struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ int v4l2_linesize; /* bytes for one videoline*/ struct timeval timestamp; - int sequence; // How many video frames we send to user + int sequence; /* How many video frames we send to user */ }; #define CODEC_SAA7113 7113 @@ -332,24 +333,24 @@ struct usbvision_frame { #define BRIDGE_NT1005 1005 struct usbvision_device_data_st { - __u64 VideoNorm; - const char *ModelString; - int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ - __u16 Codec; - unsigned VideoChannels:3; - unsigned AudioChannels:2; - unsigned Radio:1; + __u64 video_norm; + const char *model_string; + int interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ + __u16 codec; + unsigned video_channels:3; + unsigned audio_channels:2; + unsigned radio:1; unsigned vbi:1; - unsigned Tuner:1; - unsigned Vin_Reg1_override:1; /* Override default value with */ - unsigned Vin_Reg2_override:1; /* Vin_Reg1, Vin_Reg2, etc. */ - unsigned Dvi_yuv_override:1; - __u8 Vin_Reg1; - __u8 Vin_Reg2; - __u8 Dvi_yuv; - __u8 TunerType; - __s16 X_Offset; - __s16 Y_Offset; + unsigned tuner:1; + unsigned vin_reg1_override:1; /* Override default value with */ + unsigned vin_reg2_override:1; /* vin_reg1, vin_reg2, etc. */ + unsigned dvi_yuv_override:1; + __u8 vin_reg1; + __u8 vin_reg2; + __u8 dvi_yuv; + __u8 tuner_type; + __s16 x_offset; + __s16 y_offset; }; /* Declared on usbvision-cards.c */ @@ -358,50 +359,50 @@ extern struct usb_device_id usbvision_table[]; struct usb_usbvision { struct v4l2_device v4l2_dev; - struct video_device *vdev; /* Video Device */ - struct video_device *rdev; /* Radio Device */ + struct video_device *vdev; /* Video Device */ + struct video_device *rdev; /* Radio Device */ /* i2c Declaration Section*/ struct i2c_adapter i2c_adap; int registered_i2c; - struct urb *ctrlUrb; - unsigned char ctrlUrbBuffer[8]; - int ctrlUrbBusy; - struct usb_ctrlrequest ctrlUrbSetup; - wait_queue_head_t ctrlUrb_wq; // Processes waiting + struct urb *ctrl_urb; + unsigned char ctrl_urb_buffer[8]; + int ctrl_urb_busy; + struct usb_ctrlrequest ctrl_urb_setup; + wait_queue_head_t ctrl_urb_wq; /* Processes waiting */ /* configuration part */ int have_tuner; int tuner_type; - int bridgeType; // NT1003, NT1004, NT1005 + int bridge_type; /* NT1003, NT1004, NT1005 */ int radio; - int video_inputs; // # of inputs + int video_inputs; /* # of inputs */ unsigned long freq; - int AudioMute; - int AudioChannel; - int isocMode; // format of video data for the usb isoc-transfer - unsigned int nr; // Number of the device + int audio_mute; + int audio_channel; + int isoc_mode; /* format of video data for the usb isoc-transfer */ + unsigned int nr; /* Number of the device */ /* Device structure */ struct usb_device *dev; /* usb transfer */ int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + unsigned int *alt_max_pkt_size; /* array of max_packet_size */ unsigned char iface; /* Video interface number */ - unsigned char ifaceAlt; /* Alt settings */ - unsigned char Vin_Reg2_Preset; - struct mutex lock; - struct timer_list powerOffTimer; - struct work_struct powerOffWork; + unsigned char iface_alt; /* Alt settings */ + unsigned char vin_reg2_preset; + struct mutex v4l2_lock; + struct timer_list power_off_timer; + struct work_struct power_off_work; int power; /* is the device powered on? */ int user; /* user count for exclusive use */ int initialized; /* Had we already sent init sequence? */ - int DevModel; /* What type of USBVISION device we got? */ - enum StreamState streaming; /* Are we streaming Isochronous? */ + int dev_model; /* What type of USBVISION device we got? */ + enum stream_state streaming; /* Are we streaming Isochronous? */ int last_error; /* What calamity struck us? */ int curwidth; /* width of the frame the device is currently set to*/ - int curheight; /* height of the frame the device is currently set to*/ + int curheight; /* height of the frame the device is currently set to*/ int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ char *fbuf; /* Videodev buffer area for mmap*/ @@ -411,10 +412,10 @@ struct usb_usbvision { struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ wait_queue_head_t wait_frame; /* Processes waiting */ wait_queue_head_t wait_stream; /* Processes waiting */ - struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header - struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer - int num_frames; // number of frames allocated - struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering + struct usbvision_frame *cur_frame; /* pointer to current frame, set by usbvision_find_header */ + struct usbvision_frame frame[USBVISION_NUMFRAMES]; /* frame buffer */ + int num_frames; /* number of frames allocated */ + struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; /* S buffering */ volatile int remove_pending; /* If set then about to exit */ /* Scratch space from the Isochronous Pipe.*/ @@ -424,43 +425,43 @@ struct usb_usbvision { int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; int scratch_headermarker_read_ptr; int scratch_headermarker_write_ptr; - enum IsocState isocstate; + enum isoc_state isocstate; struct usbvision_v4l2_format_st palette; struct v4l2_capability vcap; /* Video capabilities */ unsigned int ctl_input; /* selected input */ - v4l2_std_id tvnormId; /* selected tv norm */ + v4l2_std_id tvnorm_id; /* selected tv norm */ unsigned char video_endp; /* 0x82 for USBVISION devices based */ - // Decompression stuff: - unsigned char *IntraFrameBuffer; /* Buffer for reference frame */ - int BlockPos; //for test only - int requestIntra; // 0 = normal; 1 = intra frame is requested; - int lastIsocFrameNum; // check for lost isoc frames - int isocPacketSize; // need to calculate usedBandwidth - int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel - int comprLevel; // How strong (100) or weak (0) is compression - int lastComprLevel; // How strong (100) or weak (0) was compression + /* Decompression stuff: */ + unsigned char *intra_frame_buffer; /* Buffer for reference frame */ + int block_pos; /* for test only */ + int request_intra; /* 0 = normal; 1 = intra frame is requested; */ + int last_isoc_frame_num; /* check for lost isoc frames */ + int isoc_packet_size; /* need to calculate used_bandwidth */ + int used_bandwidth; /* used bandwidth 0-100%, need to set compr_level */ + int compr_level; /* How strong (100) or weak (0) is compression */ + int last_compr_level; /* How strong (100) or weak (0) was compression */ int usb_bandwidth; /* Mbit/s */ /* Statistics that can be overlayed on the screen */ - unsigned long isocUrbCount; // How many URBs we received so far + unsigned long isoc_urb_count; /* How many URBs we received so far */ unsigned long urb_length; /* Length of last URB */ - unsigned long isocDataCount; /* How many bytes we received */ + unsigned long isoc_data_count; /* How many bytes we received */ unsigned long header_count; /* How many frame headers we found */ unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ - unsigned long isocSkipCount; /* How many empty ISO packets received */ - unsigned long isocErrCount; /* How many bad ISO packets received */ - unsigned long isocPacketCount; // How many packets we totally got - unsigned long timeInIrq; // How long do we need for interrupt - int isocMeasureBandwidthCount; - int frame_num; // How many video frames we send to user - int maxStripLen; // How big is the biggest strip - int comprBlockPos; - int stripLenErrors; // How many times was BlockPos greater than StripLen - int stripMagicErrors; - int stripLineNumberErrors; - int ComprBlockTypes[4]; + unsigned long isoc_skip_count; /* How many empty ISO packets received */ + unsigned long isoc_err_count; /* How many bad ISO packets received */ + unsigned long isoc_packet_count; /* How many packets we totally got */ + unsigned long time_in_irq; /* How long do we need for interrupt */ + int isoc_measure_bandwidth_count; + int frame_num; /* How many video frames we send to user */ + int max_strip_len; /* How big is the biggest strip */ + int comprblock_pos; + int strip_len_errors; /* How many times was block_pos greater than strip_len */ + int strip_magic_errors; + int strip_line_number_errors; + int compr_block_types[4]; }; static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev) @@ -494,13 +495,13 @@ void usbvision_scratch_free(struct usb_usbvision *usbvision); int usbvision_decompress_alloc(struct usb_usbvision *usbvision); void usbvision_decompress_free(struct usb_usbvision *usbvision); -int usbvision_setup(struct usb_usbvision *usbvision,int format); +int usbvision_setup(struct usb_usbvision *usbvision, int format); int usbvision_init_isoc(struct usb_usbvision *usbvision); int usbvision_restart_isoc(struct usb_usbvision *usbvision); void usbvision_stop_isoc(struct usb_usbvision *usbvision); int usbvision_set_alternate(struct usb_usbvision *dev); -int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); +int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel); int usbvision_audio_off(struct usb_usbvision *usbvision); int usbvision_begin_streaming(struct usb_usbvision *usbvision); @@ -511,9 +512,9 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); int usbvision_set_input(struct usb_usbvision *usbvision); int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); -void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision); -void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision); -void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision); +void usbvision_init_power_off_timer(struct usb_usbvision *usbvision); +void usbvision_set_power_off_timer(struct usb_usbvision *usbvision); +void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision); int usbvision_power_off(struct usb_usbvision *usbvision); int usbvision_power_on(struct usb_usbvision *usbvision); diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index f169f773667..59f8a9ad379 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, } } -struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, +static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, __u32 v4l2_id, struct uvc_control_mapping **mapping) { struct uvc_control *ctrl = NULL; @@ -944,6 +944,52 @@ done: return ret; } +/* + * Mapping V4L2 controls to UVC controls can be straighforward if done well. + * Most of the UVC controls exist in V4L2, and can be mapped directly. Some + * must be grouped (for instance the Red Balance, Blue Balance and Do White + * Balance V4L2 controls use the White Balance Component UVC control) or + * otherwise translated. The approach we take here is to use a translation + * table for the controls that can be mapped directly, and handle the others + * manually. + */ +int uvc_query_v4l2_menu(struct uvc_video_chain *chain, + struct v4l2_querymenu *query_menu) +{ + struct uvc_menu_info *menu_info; + struct uvc_control_mapping *mapping; + struct uvc_control *ctrl; + u32 index = query_menu->index; + u32 id = query_menu->id; + int ret; + + memset(query_menu, 0, sizeof(*query_menu)); + query_menu->id = id; + query_menu->index = index; + + ret = mutex_lock_interruptible(&chain->ctrl_mutex); + if (ret < 0) + return -ERESTARTSYS; + + ctrl = uvc_find_control(chain, query_menu->id, &mapping); + if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { + ret = -EINVAL; + goto done; + } + + if (query_menu->index >= mapping->menu_count) { + ret = -EINVAL; + goto done; + } + + menu_info = &mapping->menu_info[query_menu->index]; + strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); + +done: + mutex_unlock(&chain->ctrl_mutex); + return ret; +} + /* -------------------------------------------------------------------------- * Control transactions diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index ed6d5449741..f14581bd707 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -90,6 +90,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, } /* + * Free the video buffers. + * + * This function must be called with the queue lock held. + */ +static int __uvc_free_buffers(struct uvc_video_queue *queue) +{ + unsigned int i; + + for (i = 0; i < queue->count; ++i) { + if (queue->buffer[i].vma_use_count != 0) + return -EBUSY; + } + + if (queue->count) { + vfree(queue->mem); + queue->count = 0; + } + + return 0; +} + +int uvc_free_buffers(struct uvc_video_queue *queue) +{ + int ret; + + mutex_lock(&queue->mutex); + ret = __uvc_free_buffers(queue); + mutex_unlock(&queue->mutex); + + return ret; +} + +/* * Allocate the video buffers. * * Pages are reserved to make sure they will not be swapped, as they will be @@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, mutex_lock(&queue->mutex); - if ((ret = uvc_free_buffers(queue)) < 0) + if ((ret = __uvc_free_buffers(queue)) < 0) goto done; /* Bail out if no buffers should be allocated. */ @@ -152,28 +185,6 @@ done: } /* - * Free the video buffers. - * - * This function must be called with the queue lock held. - */ -int uvc_free_buffers(struct uvc_video_queue *queue) -{ - unsigned int i; - - for (i = 0; i < queue->count; ++i) { - if (queue->buffer[i].vma_use_count != 0) - return -EBUSY; - } - - if (queue->count) { - vfree(queue->mem); - queue->count = 0; - } - - return 0; -} - -/* * Check if buffers have been allocated. */ int uvc_queue_allocated(struct uvc_video_queue *queue) @@ -369,6 +380,82 @@ done: } /* + * VMA operations. + */ +static void uvc_vm_open(struct vm_area_struct *vma) +{ + struct uvc_buffer *buffer = vma->vm_private_data; + buffer->vma_use_count++; +} + +static void uvc_vm_close(struct vm_area_struct *vma) +{ + struct uvc_buffer *buffer = vma->vm_private_data; + buffer->vma_use_count--; +} + +static const struct vm_operations_struct uvc_vm_ops = { + .open = uvc_vm_open, + .close = uvc_vm_close, +}; + +/* + * Memory-map a video buffer. + * + * This function implements video buffers memory mapping and is intended to be + * used by the device mmap handler. + */ +int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) +{ + struct uvc_buffer *uninitialized_var(buffer); + struct page *page; + unsigned long addr, start, size; + unsigned int i; + int ret = 0; + + start = vma->vm_start; + size = vma->vm_end - vma->vm_start; + + mutex_lock(&queue->mutex); + + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; + if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) + break; + } + + if (i == queue->count || size != queue->buf_size) { + ret = -EINVAL; + goto done; + } + + /* + * VM_IO marks the area as being an mmaped region for I/O to a + * device. It also prevents the region from being core dumped. + */ + vma->vm_flags |= VM_IO; + + addr = (unsigned long)queue->mem + buffer->buf.m.offset; + while (size > 0) { + page = vmalloc_to_page((void *)addr); + if ((ret = vm_insert_page(vma, start, page)) < 0) + goto done; + + start += PAGE_SIZE; + addr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &uvc_vm_ops; + vma->vm_private_data = buffer; + uvc_vm_open(vma); + +done: + mutex_unlock(&queue->mutex); + return ret; +} + +/* * Poll the video queue. * * This function implements video queue polling and is intended to be used by diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 6d15de9b520..9005a8d9d5f 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -101,40 +101,6 @@ done: */ /* - * Mapping V4L2 controls to UVC controls can be straighforward if done well. - * Most of the UVC controls exist in V4L2, and can be mapped directly. Some - * must be grouped (for instance the Red Balance, Blue Balance and Do White - * Balance V4L2 controls use the White Balance Component UVC control) or - * otherwise translated. The approach we take here is to use a translation - * table for the controls that can be mapped directly, and handle the others - * manually. - */ -static int uvc_v4l2_query_menu(struct uvc_video_chain *chain, - struct v4l2_querymenu *query_menu) -{ - struct uvc_menu_info *menu_info; - struct uvc_control_mapping *mapping; - struct uvc_control *ctrl; - u32 index = query_menu->index; - u32 id = query_menu->id; - - ctrl = uvc_find_control(chain, query_menu->id, &mapping); - if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) - return -EINVAL; - - if (query_menu->index >= mapping->menu_count) - return -EINVAL; - - memset(query_menu, 0, sizeof(*query_menu)); - query_menu->id = id; - query_menu->index = index; - - menu_info = &mapping->menu_info[query_menu->index]; - strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); - return 0; -} - -/* * Find the frame interval closest to the requested frame interval for the * given frame format and size. This should be done by the device as part of * the Video Probe and Commit negotiation, but some hardware don't implement @@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * developers test their webcams with the Linux driver as well as with * the Windows driver). */ + mutex_lock(&stream->mutex); if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) probe->dwMaxVideoFrameSize = stream->ctrl.dwMaxVideoFrameSize; /* Probe the device. */ ret = uvc_probe_video(stream, probe); + mutex_unlock(&stream->mutex); if (ret < 0) goto done; @@ -289,14 +257,21 @@ done: static int uvc_v4l2_get_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { - struct uvc_format *format = stream->cur_format; - struct uvc_frame *frame = stream->cur_frame; + struct uvc_format *format; + struct uvc_frame *frame; + int ret = 0; if (fmt->type != stream->type) return -EINVAL; - if (format == NULL || frame == NULL) - return -EINVAL; + mutex_lock(&stream->mutex); + format = stream->cur_format; + frame = stream->cur_frame; + + if (format == NULL || frame == NULL) { + ret = -EINVAL; + goto done; + } fmt->fmt.pix.pixelformat = format->fcc; fmt->fmt.pix.width = frame->wWidth; @@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream, fmt->fmt.pix.colorspace = format->colorspace; fmt->fmt.pix.priv = 0; - return 0; +done: + mutex_unlock(&stream->mutex); + return ret; } static int uvc_v4l2_set_format(struct uvc_streaming *stream, @@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream, if (fmt->type != stream->type) return -EINVAL; - if (uvc_queue_allocated(&stream->queue)) - return -EBUSY; - ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); if (ret < 0) return ret; + mutex_lock(&stream->mutex); + + if (uvc_queue_allocated(&stream->queue)) { + ret = -EBUSY; + goto done; + } + memcpy(&stream->ctrl, &probe, sizeof probe); stream->cur_format = format; stream->cur_frame = frame; - return 0; +done: + mutex_unlock(&stream->mutex); + return ret; } static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, @@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, if (parm->type != stream->type) return -EINVAL; + mutex_lock(&stream->mutex); numerator = stream->ctrl.dwFrameInterval; + mutex_unlock(&stream->mutex); + denominator = 10000000; uvc_simplify_fraction(&numerator, &denominator, 8, 333); @@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, struct v4l2_streamparm *parm) { - struct uvc_frame *frame = stream->cur_frame; struct uvc_streaming_control probe; struct v4l2_fract timeperframe; uint32_t interval; @@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, if (parm->type != stream->type) return -EINVAL; - if (uvc_queue_streaming(&stream->queue)) - return -EBUSY; - if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) timeperframe = parm->parm.capture.timeperframe; else timeperframe = parm->parm.output.timeperframe; - memcpy(&probe, &stream->ctrl, sizeof probe); interval = uvc_fraction_to_interval(timeperframe.numerator, timeperframe.denominator); - uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", timeperframe.numerator, timeperframe.denominator, interval); - probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); + + mutex_lock(&stream->mutex); + + if (uvc_queue_streaming(&stream->queue)) { + mutex_unlock(&stream->mutex); + return -EBUSY; + } + + memcpy(&probe, &stream->ctrl, sizeof probe); + probe.dwFrameInterval = + uvc_try_frame_interval(stream->cur_frame, interval); /* Probe the device with the new settings. */ ret = uvc_probe_video(stream, &probe); - if (ret < 0) + if (ret < 0) { + mutex_unlock(&stream->mutex); return ret; + } memcpy(&stream->ctrl, &probe, sizeof probe); + mutex_unlock(&stream->mutex); /* Return the actual frame period. */ timeperframe.numerator = probe.dwFrameInterval; @@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file) if (uvc_has_privileges(handle)) { uvc_video_enable(stream, 0); - mutex_lock(&stream->queue.mutex); if (uvc_free_buffers(&stream->queue) < 0) uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " "free buffers.\n"); - mutex_unlock(&stream->queue.mutex); } /* Release the file handle. */ @@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } case VIDIOC_QUERYMENU: - return uvc_v4l2_query_menu(chain, arg); + return uvc_query_v4l2_menu(chain, arg); case VIDIOC_G_EXT_CTRLS: { @@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_CROPCAP: { struct v4l2_cropcap *ccap = arg; - struct uvc_frame *frame = stream->cur_frame; if (ccap->type != stream->type) return -EINVAL; ccap->bounds.left = 0; ccap->bounds.top = 0; - ccap->bounds.width = frame->wWidth; - ccap->bounds.height = frame->wHeight; + + mutex_lock(&stream->mutex); + ccap->bounds.width = stream->cur_frame->wWidth; + ccap->bounds.height = stream->cur_frame->wHeight; + mutex_unlock(&stream->mutex); ccap->defrect = ccap->bounds; @@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *rb = arg; - unsigned int bufsize = - stream->ctrl.dwMaxVideoFrameSize; if (rb->type != stream->type || rb->memory != V4L2_MEMORY_MMAP) @@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); + mutex_lock(&stream->mutex); + ret = uvc_alloc_buffers(&stream->queue, rb->count, + stream->ctrl.dwMaxVideoFrameSize); + mutex_unlock(&stream->mutex); if (ret < 0) return ret; @@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (!uvc_has_privileges(handle)) return -EBUSY; + mutex_lock(&stream->mutex); ret = uvc_video_enable(stream, 1); + mutex_unlock(&stream->mutex); if (ret < 0) return ret; break; @@ -1039,11 +1035,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return uvc_xu_ctrl_query(chain, arg, 1); default: - if ((ret = v4l_compat_translate_ioctl(file, cmd, arg, - uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD) - uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", - cmd); - return ret; + uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); + return -EINVAL; } return ret; @@ -1068,79 +1061,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data, return -EINVAL; } -/* - * VMA operations. - */ -static void uvc_vm_open(struct vm_area_struct *vma) -{ - struct uvc_buffer *buffer = vma->vm_private_data; - buffer->vma_use_count++; -} - -static void uvc_vm_close(struct vm_area_struct *vma) -{ - struct uvc_buffer *buffer = vma->vm_private_data; - buffer->vma_use_count--; -} - -static const struct vm_operations_struct uvc_vm_ops = { - .open = uvc_vm_open, - .close = uvc_vm_close, -}; - static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) { struct uvc_fh *handle = file->private_data; struct uvc_streaming *stream = handle->stream; - struct uvc_video_queue *queue = &stream->queue; - struct uvc_buffer *uninitialized_var(buffer); - struct page *page; - unsigned long addr, start, size; - unsigned int i; - int ret = 0; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); - start = vma->vm_start; - size = vma->vm_end - vma->vm_start; - - mutex_lock(&queue->mutex); - - for (i = 0; i < queue->count; ++i) { - buffer = &queue->buffer[i]; - if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) - break; - } - - if (i == queue->count || size != queue->buf_size) { - ret = -EINVAL; - goto done; - } - - /* - * VM_IO marks the area as being an mmaped region for I/O to a - * device. It also prevents the region from being core dumped. - */ - vma->vm_flags |= VM_IO; - - addr = (unsigned long)queue->mem + buffer->buf.m.offset; - while (size > 0) { - page = vmalloc_to_page((void *)addr); - if ((ret = vm_insert_page(vma, start, page)) < 0) - goto done; - - start += PAGE_SIZE; - addr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &uvc_vm_ops; - vma->vm_private_data = buffer; - uvc_vm_open(vma); - -done: - mutex_unlock(&queue->mutex); - return ret; + return uvc_queue_mmap(&stream->queue, vma); } static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) @@ -1157,7 +1085,7 @@ const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, - .ioctl = uvc_v4l2_ioctl, + .unlocked_ioctl = uvc_v4l2_ioctl, .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 5555f010283..5673d673504 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream, unsigned int i; int ret; - mutex_lock(&stream->mutex); - /* Perform probing. The device should adjust the requested values * according to its capabilities. However, some devices, namely the * first generation UVC Logitech webcams, don't implement the Video @@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream, } done: - mutex_unlock(&stream->mutex); return ret; } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index d97cf6d6a4f..45f01e7e13d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -436,7 +436,9 @@ struct uvc_streaming { struct uvc_streaming_control ctrl; struct uvc_format *cur_format; struct uvc_frame *cur_frame; - + /* Protect access to ctrl, cur_format, cur_frame and hardware video + * probe control. + */ struct mutex mutex; unsigned int frozen : 1; @@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable); extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf); +extern int uvc_queue_mmap(struct uvc_video_queue *queue, + struct vm_area_struct *vma); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); extern int uvc_queue_allocated(struct uvc_video_queue *queue); @@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev); extern int uvc_status_resume(struct uvc_device *dev); /* Controls */ -extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, - __u32 v4l2_id, struct uvc_control_mapping **mapping); extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, struct v4l2_queryctrl *v4l2_ctrl); +extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain, + struct v4l2_querymenu *query_menu); extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, const struct uvc_control_mapping *mapping); diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c deleted file mode 100644 index d4ac751036a..00000000000 --- a/drivers/media/video/v4l1-compat.c +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * - * Video for Linux Two - * Backward Compatibility Layer - * - * Support subroutines for providing V4L2 drivers with backward - * compatibility with applications using the old API. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Author: Bill Dirks <bill@thedirks.org> - * et al. - * - */ - - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/videodev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> - -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/pgtable.h> - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); -MODULE_AUTHOR("Bill Dirks"); -MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers."); -MODULE_LICENSE("GPL"); - -#define dprintk(fmt, arg...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\ - } while (0) - -/* - * I O C T L T R A N S L A T I O N - * - * From here on down is the code for translating the numerous - * ioctl commands from the old API to the new API. - */ - -static int -get_v4l_control(struct file *file, - int cid, - v4l2_kioctl drv) -{ - struct v4l2_queryctrl qctrl2; - struct v4l2_control ctrl2; - int err; - - qctrl2.id = cid; - err = drv(file, VIDIOC_QUERYCTRL, &qctrl2); - if (err < 0) - dprintk("VIDIOC_QUERYCTRL: %d\n", err); - if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl2.id = qctrl2.id; - err = drv(file, VIDIOC_G_CTRL, &ctrl2); - if (err < 0) { - dprintk("VIDIOC_G_CTRL: %d\n", err); - return 0; - } - return DIV_ROUND_CLOSEST((ctrl2.value-qctrl2.minimum) * 65535, - qctrl2.maximum - qctrl2.minimum); - } - return 0; -} - -static int -set_v4l_control(struct file *file, - int cid, - int value, - v4l2_kioctl drv) -{ - struct v4l2_queryctrl qctrl2; - struct v4l2_control ctrl2; - int err; - - qctrl2.id = cid; - err = drv(file, VIDIOC_QUERYCTRL, &qctrl2); - if (err < 0) - dprintk("VIDIOC_QUERYCTRL: %d\n", err); - if (err == 0 && - !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) && - !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) { - if (value < 0) - value = 0; - if (value > 65535) - value = 65535; - if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN) - value = 65535; - ctrl2.id = qctrl2.id; - ctrl2.value = - (value * (qctrl2.maximum - qctrl2.minimum) - + 32767) - / 65535; - ctrl2.value += qctrl2.minimum; - err = drv(file, VIDIOC_S_CTRL, &ctrl2); - if (err < 0) - dprintk("VIDIOC_S_CTRL: %d\n", err); - } - return 0; -} - -/* ----------------------------------------------------------------- */ - -static const unsigned int palette2pixelformat[] = { - [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, - [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, - [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, - [VIDEO_PALETTE_RGB24] = V4L2_PIX_FMT_BGR24, - [VIDEO_PALETTE_RGB32] = V4L2_PIX_FMT_BGR32, - /* yuv packed pixel */ - [VIDEO_PALETTE_YUYV] = V4L2_PIX_FMT_YUYV, - [VIDEO_PALETTE_YUV422] = V4L2_PIX_FMT_YUYV, - [VIDEO_PALETTE_UYVY] = V4L2_PIX_FMT_UYVY, - /* yuv planar */ - [VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410, - [VIDEO_PALETTE_YUV420] = V4L2_PIX_FMT_YUV420, - [VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420, - [VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P, - [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P, -}; - -static unsigned int __pure -palette_to_pixelformat(unsigned int palette) -{ - if (palette < ARRAY_SIZE(palette2pixelformat)) - return palette2pixelformat[palette]; - else - return 0; -} - -static unsigned int __attribute_const__ -pixelformat_to_palette(unsigned int pixelformat) -{ - int palette = 0; - switch (pixelformat) { - case V4L2_PIX_FMT_GREY: - palette = VIDEO_PALETTE_GREY; - break; - case V4L2_PIX_FMT_RGB555: - palette = VIDEO_PALETTE_RGB555; - break; - case V4L2_PIX_FMT_RGB565: - palette = VIDEO_PALETTE_RGB565; - break; - case V4L2_PIX_FMT_BGR24: - palette = VIDEO_PALETTE_RGB24; - break; - case V4L2_PIX_FMT_BGR32: - palette = VIDEO_PALETTE_RGB32; - break; - /* yuv packed pixel */ - case V4L2_PIX_FMT_YUYV: - palette = VIDEO_PALETTE_YUYV; - break; - case V4L2_PIX_FMT_UYVY: - palette = VIDEO_PALETTE_UYVY; - break; - /* yuv planar */ - case V4L2_PIX_FMT_YUV410: - palette = VIDEO_PALETTE_YUV420; - break; - case V4L2_PIX_FMT_YUV420: - palette = VIDEO_PALETTE_YUV420; - break; - case V4L2_PIX_FMT_YUV411P: - palette = VIDEO_PALETTE_YUV411P; - break; - case V4L2_PIX_FMT_YUV422P: - palette = VIDEO_PALETTE_YUV422P; - break; - } - return palette; -} - -/* ----------------------------------------------------------------- */ - -static int poll_one(struct file *file, struct poll_wqueues *pwq) -{ - int retval = 1; - poll_table *table; - - poll_initwait(pwq); - table = &pwq->pt; - for (;;) { - int mask; - mask = file->f_op->poll(file, table); - if (mask & POLLIN) - break; - table = NULL; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - poll_schedule(pwq, TASK_INTERRUPTIBLE); - } - poll_freewait(pwq); - return retval; -} - -static int count_inputs( - struct file *file, - v4l2_kioctl drv) -{ - struct v4l2_input input2; - int i; - - for (i = 0;; i++) { - memset(&input2, 0, sizeof(input2)); - input2.index = i; - if (0 != drv(file, VIDIOC_ENUMINPUT, &input2)) - break; - } - return i; -} - -static int check_size( - struct file *file, - v4l2_kioctl drv, - int *maxw, - int *maxh) -{ - struct v4l2_fmtdesc desc2; - struct v4l2_format fmt2; - - memset(&desc2, 0, sizeof(desc2)); - memset(&fmt2, 0, sizeof(fmt2)); - - desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2)) - goto done; - - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt2.fmt.pix.width = 10000; - fmt2.fmt.pix.height = 10000; - fmt2.fmt.pix.pixelformat = desc2.pixelformat; - if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2)) - goto done; - - *maxw = fmt2.fmt.pix.width; - *maxh = fmt2.fmt.pix.height; - -done: - return 0; -} - -/* ----------------------------------------------------------------- */ - -static noinline long v4l1_compat_get_capabilities( - struct video_capability *cap, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - struct v4l2_capability *cap2; - - cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); - if (!cap2) { - err = -ENOMEM; - return err; - } - memset(cap, 0, sizeof(*cap)); - memset(&fbuf, 0, sizeof(fbuf)); - - err = drv(file, VIDIOC_QUERYCAP, cap2); - if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err); - goto done; - } - if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { - err = drv(file, VIDIOC_G_FBUF, &fbuf); - if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err); - memset(&fbuf, 0, sizeof(fbuf)); - } - err = 0; - } - - memcpy(cap->name, cap2->card, - min(sizeof(cap->name), sizeof(cap2->card))); - cap->name[sizeof(cap->name) - 1] = 0; - if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) - cap->type |= VID_TYPE_CAPTURE; - if (cap2->capabilities & V4L2_CAP_TUNER) - cap->type |= VID_TYPE_TUNER; - if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) - cap->type |= VID_TYPE_TELETEXT; - if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) - cap->type |= VID_TYPE_OVERLAY; - if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING) - cap->type |= VID_TYPE_CLIPPING; - - cap->channels = count_inputs(file, drv); - check_size(file, drv, - &cap->maxwidth, &cap->maxheight); - cap->audios = 0; /* FIXME */ - cap->minwidth = 48; /* FIXME */ - cap->minheight = 32; /* FIXME */ - -done: - kfree(cap2); - return err; -} - -static noinline long v4l1_compat_get_frame_buffer( - struct video_buffer *buffer, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - - memset(buffer, 0, sizeof(*buffer)); - memset(&fbuf, 0, sizeof(fbuf)); - - err = drv(file, VIDIOC_G_FBUF, &fbuf); - if (err < 0) { - dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err); - goto done; - } - buffer->base = fbuf.base; - buffer->height = fbuf.fmt.height; - buffer->width = fbuf.fmt.width; - - switch (fbuf.fmt.pixelformat) { - case V4L2_PIX_FMT_RGB332: - buffer->depth = 8; - break; - case V4L2_PIX_FMT_RGB555: - buffer->depth = 15; - break; - case V4L2_PIX_FMT_RGB565: - buffer->depth = 16; - break; - case V4L2_PIX_FMT_BGR24: - buffer->depth = 24; - break; - case V4L2_PIX_FMT_BGR32: - buffer->depth = 32; - break; - default: - buffer->depth = 0; - } - if (fbuf.fmt.bytesperline) { - buffer->bytesperline = fbuf.fmt.bytesperline; - if (!buffer->depth && buffer->width) - buffer->depth = ((fbuf.fmt.bytesperline<<3) - + (buffer->width-1)) - / buffer->width; - } else { - buffer->bytesperline = - (buffer->width * buffer->depth + 7) & 7; - buffer->bytesperline >>= 3; - } -done: - return err; -} - -static noinline long v4l1_compat_set_frame_buffer( - struct video_buffer *buffer, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - - memset(&fbuf, 0, sizeof(fbuf)); - fbuf.base = buffer->base; - fbuf.fmt.height = buffer->height; - fbuf.fmt.width = buffer->width; - switch (buffer->depth) { - case 8: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332; - break; - case 15: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555; - break; - case 16: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565; - break; - case 24: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24; - break; - case 32: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32; - break; - } - fbuf.fmt.bytesperline = buffer->bytesperline; - err = drv(file, VIDIOC_S_FBUF, &fbuf); - if (err < 0) - dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_win_cap_dimensions( - struct video_window *win, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - memset(win, 0, sizeof(*win)); - - fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) - dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err); - if (err == 0) { - win->x = fmt->fmt.win.w.left; - win->y = fmt->fmt.win.w.top; - win->width = fmt->fmt.win.w.width; - win->height = fmt->fmt.win.w.height; - win->chromakey = fmt->fmt.win.chromakey; - win->clips = NULL; - win->clipcount = 0; - goto done; - } - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - win->x = 0; - win->y = 0; - win->width = fmt->fmt.pix.width; - win->height = fmt->fmt.pix.height; - win->chromakey = 0; - win->clips = NULL; - win->clipcount = 0; -done: - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_set_win_cap_dimensions( - struct video_window *win, - struct file *file, - v4l2_kioctl drv) -{ - long err, err1, err2; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - drv(file, VIDIOC_STREAMOFF, &fmt->type); - err1 = drv(file, VIDIOC_G_FMT, fmt); - if (err1 < 0) - dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1); - if (err1 == 0) { - fmt->fmt.pix.width = win->width; - fmt->fmt.pix.height = win->height; - fmt->fmt.pix.field = V4L2_FIELD_ANY; - fmt->fmt.pix.bytesperline = 0; - err = drv(file, VIDIOC_S_FMT, fmt); - if (err < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n", - err); - win->width = fmt->fmt.pix.width; - win->height = fmt->fmt.pix.height; - } - - memset(fmt, 0, sizeof(*fmt)); - fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - fmt->fmt.win.w.left = win->x; - fmt->fmt.win.w.top = win->y; - fmt->fmt.win.w.width = win->width; - fmt->fmt.win.w.height = win->height; - fmt->fmt.win.chromakey = win->chromakey; - fmt->fmt.win.clips = (void __user *)win->clips; - fmt->fmt.win.clipcount = win->clipcount; - err2 = drv(file, VIDIOC_S_FMT, fmt); - if (err2 < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2); - - if (err1 != 0 && err2 != 0) - err = err1; - else - err = 0; - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_turn_preview_on_off( - int *on, - struct file *file, - v4l2_kioctl drv) -{ - long err; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (0 == *on) { - /* dirty hack time. But v4l1 has no STREAMOFF - * equivalent in the API, and this one at - * least comes close ... */ - drv(file, VIDIOC_STREAMOFF, &captype); - } - err = drv(file, VIDIOC_OVERLAY, on); - if (err < 0) - dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_input_info( - struct video_channel *chan, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_input input2; - v4l2_std_id sid; - - memset(&input2, 0, sizeof(input2)); - input2.index = chan->channel; - err = drv(file, VIDIOC_ENUMINPUT, &input2); - if (err < 0) { - dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " - "channel=%d err=%ld\n", chan->channel, err); - goto done; - } - chan->channel = input2.index; - memcpy(chan->name, input2.name, - min(sizeof(chan->name), sizeof(input2.name))); - chan->name[sizeof(chan->name) - 1] = 0; - chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; - chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; - switch (input2.type) { - case V4L2_INPUT_TYPE_TUNER: - chan->type = VIDEO_TYPE_TV; - break; - default: - case V4L2_INPUT_TYPE_CAMERA: - chan->type = VIDEO_TYPE_CAMERA; - break; - } - chan->norm = 0; - /* Note: G_STD might not be present for radio receivers, - * so we should ignore any errors. */ - if (drv(file, VIDIOC_G_STD, &sid) == 0) { - if (sid & V4L2_STD_PAL) - chan->norm = VIDEO_MODE_PAL; - if (sid & V4L2_STD_NTSC) - chan->norm = VIDEO_MODE_NTSC; - if (sid & V4L2_STD_SECAM) - chan->norm = VIDEO_MODE_SECAM; - if (sid == V4L2_STD_ALL) - chan->norm = VIDEO_MODE_AUTO; - } -done: - return err; -} - -static noinline long v4l1_compat_set_input( - struct video_channel *chan, - struct file *file, - v4l2_kioctl drv) -{ - long err; - v4l2_std_id sid = 0; - - err = drv(file, VIDIOC_S_INPUT, &chan->channel); - if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err); - switch (chan->norm) { - case VIDEO_MODE_PAL: - sid = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - sid = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - sid = V4L2_STD_SECAM; - break; - case VIDEO_MODE_AUTO: - sid = V4L2_STD_ALL; - break; - } - if (0 != sid) { - err = drv(file, VIDIOC_S_STD, &sid); - if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err); - } - return err; -} - -static noinline long v4l1_compat_get_picture( - struct video_picture *pict, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - - pict->brightness = get_v4l_control(file, - V4L2_CID_BRIGHTNESS, drv); - pict->hue = get_v4l_control(file, - V4L2_CID_HUE, drv); - pict->contrast = get_v4l_control(file, - V4L2_CID_CONTRAST, drv); - pict->colour = get_v4l_control(file, - V4L2_CID_SATURATION, drv); - pict->whiteness = get_v4l_control(file, - V4L2_CID_WHITENESS, drv); - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - - if (fmt->fmt.pix.width) - { - pict->depth = ((fmt->fmt.pix.bytesperline << 3) - + (fmt->fmt.pix.width - 1)) - / fmt->fmt.pix.width; - } else { - err = -EINVAL; - goto done; - } - - pict->palette = pixelformat_to_palette( - fmt->fmt.pix.pixelformat); -done: - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_set_picture( - struct video_picture *pict, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - int mem_err = 0, ovl_err = 0; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - memset(&fbuf, 0, sizeof(fbuf)); - - set_v4l_control(file, - V4L2_CID_BRIGHTNESS, pict->brightness, drv); - set_v4l_control(file, - V4L2_CID_HUE, pict->hue, drv); - set_v4l_control(file, - V4L2_CID_CONTRAST, pict->contrast, drv); - set_v4l_control(file, - V4L2_CID_SATURATION, pict->colour, drv); - set_v4l_control(file, - V4L2_CID_WHITENESS, pict->whiteness, drv); - /* - * V4L1 uses this ioctl to set both memory capture and overlay - * pixel format, while V4L2 has two different ioctls for this. - * Some cards may not support one or the other, and may support - * different pixel formats for memory vs overlay. - */ - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - /* If VIDIOC_G_FMT failed, then the driver likely doesn't - support memory capture. Trying to set the memory capture - parameters would be pointless. */ - if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err); - mem_err = -1000; /* didn't even try */ - } else if (fmt->fmt.pix.pixelformat != - palette_to_pixelformat(pict->palette)) { - fmt->fmt.pix.pixelformat = palette_to_pixelformat( - pict->palette); - mem_err = drv(file, VIDIOC_S_FMT, fmt); - if (mem_err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", - mem_err); - } - - err = drv(file, VIDIOC_G_FBUF, &fbuf); - /* If VIDIOC_G_FBUF failed, then the driver likely doesn't - support overlay. Trying to set the overlay parameters - would be quite pointless. */ - if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err); - ovl_err = -1000; /* didn't even try */ - } else if (fbuf.fmt.pixelformat != - palette_to_pixelformat(pict->palette)) { - fbuf.fmt.pixelformat = palette_to_pixelformat( - pict->palette); - ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf); - if (ovl_err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", - ovl_err); - } - if (ovl_err < 0 && mem_err < 0) { - /* ioctl failed, couldn't set either parameter */ - if (mem_err != -1000) - err = mem_err; - else if (ovl_err == -EPERM) - err = 0; - else - err = ovl_err; - } else - err = 0; - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_get_tuner( - struct video_tuner *tun, - struct file *file, - v4l2_kioctl drv) -{ - long err; - int i; - struct v4l2_tuner tun2; - struct v4l2_standard std2; - v4l2_std_id sid; - - memset(&tun2, 0, sizeof(tun2)); - err = drv(file, VIDIOC_G_TUNER, &tun2); - if (err < 0) { - dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err); - goto done; - } - memcpy(tun->name, tun2.name, - min(sizeof(tun->name), sizeof(tun2.name))); - tun->name[sizeof(tun->name) - 1] = 0; - tun->rangelow = tun2.rangelow; - tun->rangehigh = tun2.rangehigh; - tun->flags = 0; - tun->mode = VIDEO_MODE_AUTO; - - for (i = 0; i < 64; i++) { - memset(&std2, 0, sizeof(std2)); - std2.index = i; - if (0 != drv(file, VIDIOC_ENUMSTD, &std2)) - break; - if (std2.id & V4L2_STD_PAL) - tun->flags |= VIDEO_TUNER_PAL; - if (std2.id & V4L2_STD_NTSC) - tun->flags |= VIDEO_TUNER_NTSC; - if (std2.id & V4L2_STD_SECAM) - tun->flags |= VIDEO_TUNER_SECAM; - } - - /* Note: G_STD might not be present for radio receivers, - * so we should ignore any errors. */ - if (drv(file, VIDIOC_G_STD, &sid) == 0) { - if (sid & V4L2_STD_PAL) - tun->mode = VIDEO_MODE_PAL; - if (sid & V4L2_STD_NTSC) - tun->mode = VIDEO_MODE_NTSC; - if (sid & V4L2_STD_SECAM) - tun->mode = VIDEO_MODE_SECAM; - } - - if (tun2.capability & V4L2_TUNER_CAP_LOW) - tun->flags |= VIDEO_TUNER_LOW; - if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) - tun->flags |= VIDEO_TUNER_STEREO_ON; - tun->signal = tun2.signal; -done: - return err; -} - -static noinline long v4l1_compat_select_tuner( - struct video_tuner *tun, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_tuner t;/*84 bytes on x86_64*/ - memset(&t, 0, sizeof(t)); - - t.index = tun->tuner; - - err = drv(file, VIDIOC_S_TUNER, &t); - if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_TUNER: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_frequency( - unsigned long *freq, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_frequency freq2; - memset(&freq2, 0, sizeof(freq2)); - - freq2.tuner = 0; - err = drv(file, VIDIOC_G_FREQUENCY, &freq2); - if (err < 0) - dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err); - if (0 == err) - *freq = freq2.frequency; - return err; -} - -static noinline long v4l1_compat_set_frequency( - unsigned long *freq, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_frequency freq2; - memset(&freq2, 0, sizeof(freq2)); - - drv(file, VIDIOC_G_FREQUENCY, &freq2); - freq2.frequency = *freq; - err = drv(file, VIDIOC_S_FREQUENCY, &freq2); - if (err < 0) - dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_audio( - struct video_audio *aud, - struct file *file, - v4l2_kioctl drv) -{ - long err; - int i; - struct v4l2_queryctrl qctrl2; - struct v4l2_audio aud2; - struct v4l2_tuner tun2; - memset(&aud2, 0, sizeof(aud2)); - - err = drv(file, VIDIOC_G_AUDIO, &aud2); - if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err); - goto done; - } - memcpy(aud->name, aud2.name, - min(sizeof(aud->name), sizeof(aud2.name))); - aud->name[sizeof(aud->name) - 1] = 0; - aud->audio = aud2.index; - aud->flags = 0; - i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv); - if (i >= 0) { - aud->volume = i; - aud->flags |= VIDEO_AUDIO_VOLUME; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv); - if (i >= 0) { - aud->bass = i; - aud->flags |= VIDEO_AUDIO_BASS; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv); - if (i >= 0) { - aud->treble = i; - aud->flags |= VIDEO_AUDIO_TREBLE; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv); - if (i >= 0) { - aud->balance = i; - aud->flags |= VIDEO_AUDIO_BALANCE; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv); - if (i >= 0) { - if (i) - aud->flags |= VIDEO_AUDIO_MUTE; - aud->flags |= VIDEO_AUDIO_MUTABLE; - } - aud->step = 1; - qctrl2.id = V4L2_CID_AUDIO_VOLUME; - if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && - !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) - aud->step = qctrl2.step; - aud->mode = 0; - - memset(&tun2, 0, sizeof(tun2)); - err = drv(file, VIDIOC_G_TUNER, &tun2); - if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err); - err = 0; - goto done; - } - - if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) - aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) - aud->mode = VIDEO_SOUND_STEREO; - else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) - aud->mode = VIDEO_SOUND_MONO; -done: - return err; -} - -static noinline long v4l1_compat_set_audio( - struct video_audio *aud, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_audio aud2; - struct v4l2_tuner tun2; - - memset(&aud2, 0, sizeof(aud2)); - memset(&tun2, 0, sizeof(tun2)); - - aud2.index = aud->audio; - err = drv(file, VIDIOC_S_AUDIO, &aud2); - if (err < 0) { - dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err); - goto done; - } - - set_v4l_control(file, V4L2_CID_AUDIO_VOLUME, - aud->volume, drv); - set_v4l_control(file, V4L2_CID_AUDIO_BASS, - aud->bass, drv); - set_v4l_control(file, V4L2_CID_AUDIO_TREBLE, - aud->treble, drv); - set_v4l_control(file, V4L2_CID_AUDIO_BALANCE, - aud->balance, drv); - set_v4l_control(file, V4L2_CID_AUDIO_MUTE, - !!(aud->flags & VIDEO_AUDIO_MUTE), drv); - - err = drv(file, VIDIOC_G_TUNER, &tun2); - if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err); - if (err == 0) { - switch (aud->mode) { - default: - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - tun2.audmode = V4L2_TUNER_MODE_MONO; - break; - case VIDEO_SOUND_STEREO: - tun2.audmode = V4L2_TUNER_MODE_STEREO; - break; - case VIDEO_SOUND_LANG2: - tun2.audmode = V4L2_TUNER_MODE_LANG2; - break; - } - err = drv(file, VIDIOC_S_TUNER, &tun2); - if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err); - } - err = 0; -done: - return err; -} - -static noinline long v4l1_compat_capture_frame( - struct video_mmap *mm, - struct file *file, - v4l2_kioctl drv) -{ - long err; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - struct v4l2_buffer buf; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - memset(&buf, 0, sizeof(buf)); - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - if (mm->width != fmt->fmt.pix.width || - mm->height != fmt->fmt.pix.height || - palette_to_pixelformat(mm->format) != - fmt->fmt.pix.pixelformat) { - /* New capture format... */ - fmt->fmt.pix.width = mm->width; - fmt->fmt.pix.height = mm->height; - fmt->fmt.pix.pixelformat = - palette_to_pixelformat(mm->format); - fmt->fmt.pix.field = V4L2_FIELD_ANY; - fmt->fmt.pix.bytesperline = 0; - err = drv(file, VIDIOC_S_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err); - goto done; - } - } - buf.index = mm->frame; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_QUERYBUF, &buf); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err); - goto done; - } - err = drv(file, VIDIOC_QBUF, &buf); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err); - goto done; - } - err = drv(file, VIDIOC_STREAMON, &captype); - if (err < 0) - dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err); -done: - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_sync( - int *i, - struct file *file, - v4l2_kioctl drv) -{ - long err; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - struct v4l2_buffer buf; - struct poll_wqueues *pwq; - - memset(&buf, 0, sizeof(buf)); - buf.index = *i; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_QUERYBUF, &buf); - if (err < 0) { - /* No such buffer */ - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err); - goto done; - } - if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) { - /* Buffer is not mapped */ - err = -EINVAL; - goto done; - } - - /* make sure capture actually runs so we don't block forever */ - err = drv(file, VIDIOC_STREAMON, &captype); - if (err < 0) { - dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err); - goto done; - } - - pwq = kmalloc(sizeof(*pwq), GFP_KERNEL); - /* Loop as long as the buffer is queued, but not done */ - while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) - == V4L2_BUF_FLAG_QUEUED) { - err = poll_one(file, pwq); - if (err < 0 || /* error or sleep was interrupted */ - err == 0) /* timeout? Shouldn't occur. */ - break; - err = drv(file, VIDIOC_QUERYBUF, &buf); - if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err); - } - kfree(pwq); - if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ - goto done; - do { - err = drv(file, VIDIOC_DQBUF, &buf); - if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err); - } while (err == 0 && buf.index != *i); -done: - return err; -} - -static noinline long v4l1_compat_get_vbi_format( - struct vbi_format *fmt, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt2; - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - return err; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - - err = drv(file, VIDIOC_G_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { - err = -EINVAL; - goto done; - } - memset(fmt, 0, sizeof(*fmt)); - fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; - fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; - fmt->sample_format = VIDEO_PALETTE_RAW; - fmt->start[0] = fmt2->fmt.vbi.start[0]; - fmt->count[0] = fmt2->fmt.vbi.count[0]; - fmt->start[1] = fmt2->fmt.vbi.start[1]; - fmt->count[1] = fmt2->fmt.vbi.count[1]; - fmt->flags = fmt2->fmt.vbi.flags & 0x03; -done: - kfree(fmt2); - return err; -} - -static noinline long v4l1_compat_set_vbi_format( - struct vbi_format *fmt, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt2 = NULL; - - if (VIDEO_PALETTE_RAW != fmt->sample_format) { - err = -EINVAL; - return err; - } - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - return err; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; - fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; - fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - fmt2->fmt.vbi.start[0] = fmt->start[0]; - fmt2->fmt.vbi.count[0] = fmt->count[0]; - fmt2->fmt.vbi.start[1] = fmt->start[1]; - fmt2->fmt.vbi.count[1] = fmt->count[1]; - fmt2->fmt.vbi.flags = fmt->flags; - err = drv(file, VIDIOC_TRY_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err); - goto done; - } - - if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || - fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || - fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || - fmt2->fmt.vbi.start[0] != fmt->start[0] || - fmt2->fmt.vbi.count[0] != fmt->count[0] || - fmt2->fmt.vbi.start[1] != fmt->start[1] || - fmt2->fmt.vbi.count[1] != fmt->count[1] || - fmt2->fmt.vbi.flags != fmt->flags) { - err = -EINVAL; - goto done; - } - err = drv(file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err); -done: - kfree(fmt2); - return err; -} - -/* - * This function is exported. - */ -long -v4l_compat_translate_ioctl(struct file *file, - int cmd, - void *arg, - v4l2_kioctl drv) -{ - long err; - - switch (cmd) { - case VIDIOCGCAP: /* capability */ - err = v4l1_compat_get_capabilities(arg, file, drv); - break; - case VIDIOCGFBUF: /* get frame buffer */ - err = v4l1_compat_get_frame_buffer(arg, file, drv); - break; - case VIDIOCSFBUF: /* set frame buffer */ - err = v4l1_compat_set_frame_buffer(arg, file, drv); - break; - case VIDIOCGWIN: /* get window or capture dimensions */ - err = v4l1_compat_get_win_cap_dimensions(arg, file, drv); - break; - case VIDIOCSWIN: /* set window and/or capture dimensions */ - err = v4l1_compat_set_win_cap_dimensions(arg, file, drv); - break; - case VIDIOCCAPTURE: /* turn on/off preview */ - err = v4l1_compat_turn_preview_on_off(arg, file, drv); - break; - case VIDIOCGCHAN: /* get input information */ - err = v4l1_compat_get_input_info(arg, file, drv); - break; - case VIDIOCSCHAN: /* set input */ - err = v4l1_compat_set_input(arg, file, drv); - break; - case VIDIOCGPICT: /* get tone controls & partial capture format */ - err = v4l1_compat_get_picture(arg, file, drv); - break; - case VIDIOCSPICT: /* set tone controls & partial capture format */ - err = v4l1_compat_set_picture(arg, file, drv); - break; - case VIDIOCGTUNER: /* get tuner information */ - err = v4l1_compat_get_tuner(arg, file, drv); - break; - case VIDIOCSTUNER: /* select a tuner input */ - err = v4l1_compat_select_tuner(arg, file, drv); - break; - case VIDIOCGFREQ: /* get frequency */ - err = v4l1_compat_get_frequency(arg, file, drv); - break; - case VIDIOCSFREQ: /* set frequency */ - err = v4l1_compat_set_frequency(arg, file, drv); - break; - case VIDIOCGAUDIO: /* get audio properties/controls */ - err = v4l1_compat_get_audio(arg, file, drv); - break; - case VIDIOCSAUDIO: /* set audio controls */ - err = v4l1_compat_set_audio(arg, file, drv); - break; - case VIDIOCMCAPTURE: /* capture a frame */ - err = v4l1_compat_capture_frame(arg, file, drv); - break; - case VIDIOCSYNC: /* wait for a frame */ - err = v4l1_compat_sync(arg, file, drv); - break; - case VIDIOCGVBIFMT: /* query VBI data capture format */ - err = v4l1_compat_get_vbi_format(arg, file, drv); - break; - case VIDIOCSVBIFMT: - err = v4l1_compat_set_vbi_format(arg, file, drv); - break; - default: - err = -ENOIOCTLCMD; - break; - } - - return err; -} -EXPORT_SYMBOL(v4l_compat_translate_ioctl); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 9294282b5ad..3f0871b550a 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -150,7 +150,7 @@ EXPORT_SYMBOL(v4l2_prio_check); struct v4l2_queryctrl and the available menu items. Note that menu_items may be NULL, in that case it is ignored. */ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, - const char **menu_items) + const char * const *menu_items) { if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) return -EINVAL; @@ -199,7 +199,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_fill); If menu_items is NULL, then the menu items are retrieved using v4l2_ctrl_get_menu. */ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, - const char **menu_items) + const char * const *menu_items) { int i; @@ -222,7 +222,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); Use this if there are 'holes' in the list of valid menu items. */ int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids) { - const char **menu_items = v4l2_ctrl_get_menu(qmenu->id); + const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id); qmenu->reserved = 0; if (menu_items == NULL || ids == NULL) @@ -368,18 +368,15 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); /* Load an i2c sub-device. */ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, const char *module_name, - struct i2c_board_info *info, const unsigned short *probe_addrs) + struct i2c_adapter *adapter, struct i2c_board_info *info, + const unsigned short *probe_addrs) { struct v4l2_subdev *sd = NULL; struct i2c_client *client; BUG_ON(!v4l2_dev); - if (module_name) - request_module(module_name); - else - request_module(I2C_MODULE_PREFIX "%s", info->type); + request_module(I2C_MODULE_PREFIX "%s", info->type); /* Create the i2c client */ if (info->addr == 0 && probe_addrs) @@ -432,8 +429,7 @@ error: EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, + struct i2c_adapter *adapter, const char *client_type, int irq, void *platform_data, u8 addr, const unsigned short *probe_addrs) { @@ -447,8 +443,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, info.irq = irq; info.platform_data = platform_data; - return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name, - &info, probe_addrs); + return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs); } EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg); diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index e30e8dfb620..dc82eb83c1d 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -15,219 +15,12 @@ #include <linux/compat.h> #define __OLD_VIDIOC_ /* To allow fixing old calls*/ -#include <linux/videodev.h> #include <linux/videodev2.h> #include <linux/module.h> #include <media/v4l2-ioctl.h> #ifdef CONFIG_COMPAT -#ifdef CONFIG_VIDEO_V4L1_COMPAT -struct video_tuner32 { - compat_int_t tuner; - char name[32]; - compat_ulong_t rangelow, rangehigh; - u32 flags; /* It is really u32 in videodev.h */ - u16 mode, signal; -}; - -static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) -{ - if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || - get_user(kp->tuner, &up->tuner) || - copy_from_user(kp->name, up->name, 32) || - get_user(kp->rangelow, &up->rangelow) || - get_user(kp->rangehigh, &up->rangehigh) || - get_user(kp->flags, &up->flags) || - get_user(kp->mode, &up->mode) || - get_user(kp->signal, &up->signal)) - return -EFAULT; - return 0; -} - -static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) -{ - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || - put_user(kp->tuner, &up->tuner) || - copy_to_user(up->name, kp->name, 32) || - put_user(kp->rangelow, &up->rangelow) || - put_user(kp->rangehigh, &up->rangehigh) || - put_user(kp->flags, &up->flags) || - put_user(kp->mode, &up->mode) || - put_user(kp->signal, &up->signal)) - return -EFAULT; - return 0; -} - -struct video_buffer32 { - compat_caddr_t base; - compat_int_t height, width, depth, bytesperline; -}; - -static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) -{ - u32 tmp; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) || - get_user(tmp, &up->base) || - get_user(kp->height, &up->height) || - get_user(kp->width, &up->width) || - get_user(kp->depth, &up->depth) || - get_user(kp->bytesperline, &up->bytesperline)) - return -EFAULT; - - /* This is actually a physical address stored - * as a void pointer. - */ - kp->base = (void *)(unsigned long) tmp; - - return 0; -} - -static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) -{ - u32 tmp = (u32)((unsigned long)kp->base); - - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) || - put_user(tmp, &up->base) || - put_user(kp->height, &up->height) || - put_user(kp->width, &up->width) || - put_user(kp->depth, &up->depth) || - put_user(kp->bytesperline, &up->bytesperline)) - return -EFAULT; - return 0; -} - -struct video_clip32 { - s32 x, y, width, height; /* It's really s32 in videodev.h */ - compat_caddr_t next; -}; - -struct video_window32 { - u32 x, y, width, height, chromakey, flags; - compat_caddr_t clips; - compat_int_t clipcount; -}; - -static int get_video_window32(struct video_window *kp, struct video_window32 __user *up) -{ - struct video_clip __user *uclips; - struct video_clip __user *kclips; - compat_caddr_t p; - int nclips; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) - return -EFAULT; - - if (get_user(nclips, &up->clipcount)) - return -EFAULT; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)) || - get_user(kp->x, &up->x) || - get_user(kp->y, &up->y) || - get_user(kp->width, &up->width) || - get_user(kp->height, &up->height) || - get_user(kp->chromakey, &up->chromakey) || - get_user(kp->flags, &up->flags) || - get_user(kp->clipcount, &up->clipcount)) - return -EFAULT; - - nclips = kp->clipcount; - kp->clips = NULL; - - if (nclips == 0) - return 0; - if (get_user(p, &up->clips)) - return -EFAULT; - uclips = compat_ptr(p); - - /* If nclips < 0, then it is a clipping bitmap of size - VIDEO_CLIPMAP_SIZE */ - if (nclips < 0) { - if (!access_ok(VERIFY_READ, uclips, VIDEO_CLIPMAP_SIZE)) - return -EFAULT; - kp->clips = compat_alloc_user_space(VIDEO_CLIPMAP_SIZE); - if (copy_in_user(kp->clips, uclips, VIDEO_CLIPMAP_SIZE)) - return -EFAULT; - return 0; - } - - /* Otherwise it is an array of video_clip structs. */ - if (!access_ok(VERIFY_READ, uclips, nclips * sizeof(struct video_clip))) - return -EFAULT; - - kp->clips = compat_alloc_user_space(nclips * sizeof(struct video_clip)); - kclips = kp->clips; - while (nclips--) { - int err; - - err = copy_in_user(&kclips->x, &uclips->x, sizeof(kclips->x)); - err |= copy_in_user(&kclips->y, &uclips->y, sizeof(kclips->y)); - err |= copy_in_user(&kclips->width, &uclips->width, sizeof(kclips->width)); - err |= copy_in_user(&kclips->height, &uclips->height, sizeof(kclips->height)); - kclips->next = NULL; - if (err) - return -EFAULT; - kclips++; - uclips++; - } - return 0; -} - -/* You get back everything except the clips... */ -static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) -{ - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || - put_user(kp->x, &up->x) || - put_user(kp->y, &up->y) || - put_user(kp->width, &up->width) || - put_user(kp->height, &up->height) || - put_user(kp->chromakey, &up->chromakey) || - put_user(kp->flags, &up->flags) || - put_user(kp->clipcount, &up->clipcount)) - return -EFAULT; - return 0; -} - -struct video_code32 { - char loadwhat[16]; /* name or tag of file being passed */ - compat_int_t datasize; - compat_uptr_t data; -}; - -static struct video_code __user *get_microcode32(struct video_code32 *kp) -{ - struct video_code __user *up; - - up = compat_alloc_user_space(sizeof(*up)); - - /* - * NOTE! We don't actually care if these fail. If the - * user address is invalid, the native ioctl will do - * the error handling for us - */ - (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat)); - (void) put_user(kp->datasize, &up->datasize); - (void) put_user(compat_ptr(kp->data), &up->data); - return up; -} - -#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) -#define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32) -#define VIDIOCGWIN32 _IOR('v', 9, struct video_window32) -#define VIDIOCSWIN32 _IOW('v', 10, struct video_window32) -#define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32) -#define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32) -#define VIDIOCGFREQ32 _IOR('v', 14, u32) -#define VIDIOCSFREQ32 _IOW('v', 15, u32) -#define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32) - -#define VIDIOCCAPTURE32 _IOW('v', 8, s32) -#define VIDIOCSYNC32 _IOW('v', 18, s32) -#define VIDIOCSWRITEMODE32 _IOW('v', 25, s32) - -#endif - static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -ENOIOCTLCMD; @@ -372,8 +165,6 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data))) return -EFAULT; return 0; - case 0: - return -EINVAL; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); @@ -403,8 +194,6 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user if (copy_to_user(up, kp, sizeof(up->fmt.raw_data))) return -EFAULT; return 0; - case 0: - return -EINVAL; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); @@ -741,13 +530,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { union { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - struct video_tuner vt; - struct video_buffer vb; - struct video_window vw; - struct video_code32 vc; - struct video_audio va; -#endif struct v4l2_format v2f; struct v4l2_buffer v2b; struct v4l2_framebuffer v2fb; @@ -763,17 +545,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar /* First, convert the command. */ switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; - case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; - case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break; -#endif case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; @@ -800,46 +571,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar } switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCSTUNER: - case VIDIOCGTUNER: - err = get_video_tuner32(&karg.vt, up); - compatible_arg = 0; - break; - - case VIDIOCSFBUF: - err = get_video_buffer32(&karg.vb, up); - compatible_arg = 0; - break; - - case VIDIOCSWIN: - err = get_video_window32(&karg.vw, up); - compatible_arg = 0; - break; - - case VIDIOCGWIN: - case VIDIOCGFBUF: - case VIDIOCGFREQ: - compatible_arg = 0; - break; - - case VIDIOCSMICROCODE: - /* Copy the 32-bit "video_code32" to kernel space */ - if (copy_from_user(&karg.vc, up, sizeof(karg.vc))) - return -EFAULT; - /* Convert the 32-bit version to a 64-bit version in user space */ - up = get_microcode32(&karg.vc); - break; - - case VIDIOCSFREQ: - err = get_user(karg.vx, (u32 __user *)up); - compatible_arg = 0; - break; - - case VIDIOCCAPTURE: - case VIDIOCSYNC: - case VIDIOCSWRITEMODE: -#endif case VIDIOC_OVERLAY: case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: @@ -922,23 +653,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar return err; switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; - - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; - - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; - - case VIDIOCGFREQ: - err = put_user(((u32)karg.vx), (u32 __user *)up); - break; -#endif case VIDIOC_S_INPUT: case VIDIOC_S_OUTPUT: case VIDIOC_G_INPUT: @@ -981,37 +695,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) return ret; switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGCAP: - case VIDIOCGCHAN: - case VIDIOCSCHAN: - case VIDIOCGTUNER32: - case VIDIOCSTUNER32: - case VIDIOCGPICT: - case VIDIOCSPICT: - case VIDIOCCAPTURE32: - case VIDIOCGWIN32: - case VIDIOCSWIN32: - case VIDIOCGFBUF32: - case VIDIOCSFBUF32: - case VIDIOCKEY: - case VIDIOCGFREQ32: - case VIDIOCSFREQ32: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - case VIDIOCSYNC32: - case VIDIOCMCAPTURE: - case VIDIOCGMBUF: - case VIDIOCGUNIT: - case VIDIOCGCAPTURE: - case VIDIOCSCAPTURE: - case VIDIOCSPLAYMODE: - case VIDIOCSWRITEMODE32: - case VIDIOCGPLAYINFO: - case VIDIOCSMICROCODE32: - case VIDIOCGVBIFMT: - case VIDIOCSVBIFMT: -#endif #ifdef __OLD_VIDIOC_ case VIDIOC_OVERLAY32_OLD: case VIDIOC_S_PARM_OLD: @@ -1096,19 +779,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) ret = do_video_ioctl(file, cmd, arg); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* BTTV specific... */ - case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): - case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): - case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int): - case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */ - case _IOR('v' , BASE_VIDIOCPRIVATE+4, int): - case _IOR('v' , BASE_VIDIOCPRIVATE+5, int): - case _IOR('v' , BASE_VIDIOCPRIVATE+6, int): - case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): - ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); - break; -#endif default: printk(KERN_WARNING "compat_ioctl32: " "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 9d2502cd03f..8f81efcfcf5 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -38,15 +38,15 @@ struct ctrl_helper { the given control ID. The pointer array ends with a NULL pointer. An empty string signifies a menu entry that is invalid. This allows drivers to disable certain options if it is not supported. */ -const char **v4l2_ctrl_get_menu(u32 id) +const char * const *v4l2_ctrl_get_menu(u32 id) { - static const char *mpeg_audio_sampling_freq[] = { + static const char * const mpeg_audio_sampling_freq[] = { "44.1 kHz", "48 kHz", "32 kHz", NULL }; - static const char *mpeg_audio_encoding[] = { + static const char * const mpeg_audio_encoding[] = { "MPEG-1/2 Layer I", "MPEG-1/2 Layer II", "MPEG-1/2 Layer III", @@ -54,7 +54,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "AC-3", NULL }; - static const char *mpeg_audio_l1_bitrate[] = { + static const char * const mpeg_audio_l1_bitrate[] = { "32 kbps", "64 kbps", "96 kbps", @@ -71,7 +71,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "448 kbps", NULL }; - static const char *mpeg_audio_l2_bitrate[] = { + static const char * const mpeg_audio_l2_bitrate[] = { "32 kbps", "48 kbps", "56 kbps", @@ -88,7 +88,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "384 kbps", NULL }; - static const char *mpeg_audio_l3_bitrate[] = { + static const char * const mpeg_audio_l3_bitrate[] = { "32 kbps", "40 kbps", "48 kbps", @@ -105,7 +105,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "320 kbps", NULL }; - static const char *mpeg_audio_ac3_bitrate[] = { + static const char * const mpeg_audio_ac3_bitrate[] = { "32 kbps", "40 kbps", "48 kbps", @@ -127,50 +127,50 @@ const char **v4l2_ctrl_get_menu(u32 id) "640 kbps", NULL }; - static const char *mpeg_audio_mode[] = { + static const char * const mpeg_audio_mode[] = { "Stereo", "Joint Stereo", "Dual", "Mono", NULL }; - static const char *mpeg_audio_mode_extension[] = { + static const char * const mpeg_audio_mode_extension[] = { "Bound 4", "Bound 8", "Bound 12", "Bound 16", NULL }; - static const char *mpeg_audio_emphasis[] = { + static const char * const mpeg_audio_emphasis[] = { "No Emphasis", "50/15 us", "CCITT J17", NULL }; - static const char *mpeg_audio_crc[] = { + static const char * const mpeg_audio_crc[] = { "No CRC", "16-bit CRC", NULL }; - static const char *mpeg_video_encoding[] = { + static const char * const mpeg_video_encoding[] = { "MPEG-1", "MPEG-2", "MPEG-4 AVC", NULL }; - static const char *mpeg_video_aspect[] = { + static const char * const mpeg_video_aspect[] = { "1x1", "4x3", "16x9", "2.21x1", NULL }; - static const char *mpeg_video_bitrate_mode[] = { + static const char * const mpeg_video_bitrate_mode[] = { "Variable Bitrate", "Constant Bitrate", NULL }; - static const char *mpeg_stream_type[] = { + static const char * const mpeg_stream_type[] = { "MPEG-2 Program Stream", "MPEG-2 Transport Stream", "MPEG-1 System Stream", @@ -179,25 +179,25 @@ const char **v4l2_ctrl_get_menu(u32 id) "MPEG-2 SVCD-compatible Stream", NULL }; - static const char *mpeg_stream_vbi_fmt[] = { + static const char * const mpeg_stream_vbi_fmt[] = { "No VBI", "Private packet, IVTV format", NULL }; - static const char *camera_power_line_frequency[] = { + static const char * const camera_power_line_frequency[] = { "Disabled", "50 Hz", "60 Hz", NULL }; - static const char *camera_exposure_auto[] = { + static const char * const camera_exposure_auto[] = { "Auto Mode", "Manual Mode", "Shutter Priority Mode", "Aperture Priority Mode", NULL }; - static const char *colorfx[] = { + static const char * const colorfx[] = { "None", "Black & White", "Sepia", @@ -210,7 +210,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "Vivid", NULL }; - static const char *tune_preemphasis[] = { + static const char * const tune_preemphasis[] = { "No preemphasis", "50 useconds", "75 useconds", @@ -952,7 +952,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, const char *name, enum v4l2_ctrl_type type, s32 min, s32 max, u32 step, s32 def, - u32 flags, const char **qmenu, void *priv) + u32 flags, const char * const *qmenu, void *priv) { struct v4l2_ctrl *ctrl; unsigned sz_extra = 0; @@ -962,13 +962,20 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, /* Sanity checks */ if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || - def < min || def > max || max < min || + max < min || (type == V4L2_CTRL_TYPE_INTEGER && step == 0) || (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || (type == V4L2_CTRL_TYPE_STRING && max == 0)) { handler_set_err(hdl, -ERANGE); return NULL; } + if ((type == V4L2_CTRL_TYPE_INTEGER || + type == V4L2_CTRL_TYPE_MENU || + type == V4L2_CTRL_TYPE_BOOLEAN) && + (def < min || def > max)) { + handler_set_err(hdl, -ERANGE); + return NULL; + } if (type == V4L2_CTRL_TYPE_BUTTON) flags |= V4L2_CTRL_FLAG_WRITE_ONLY; @@ -1019,7 +1026,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, bool is_menu; struct v4l2_ctrl *ctrl; const char *name = cfg->name; - const char **qmenu = cfg->qmenu; + const char * const *qmenu = cfg->qmenu; enum v4l2_ctrl_type type = cfg->type; u32 flags = cfg->flags; s32 min = cfg->min; @@ -1075,7 +1082,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, s32 max, s32 mask, s32 def) { - const char **qmenu = v4l2_ctrl_get_menu(id); + const char * const *qmenu = v4l2_ctrl_get_menu(id); const char *name; enum v4l2_ctrl_type type; s32 min; diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 03f7f4670e9..359e23290a7 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, size_t sz, loff_t *off) { struct video_device *vdev = video_devdata(filp); - int ret = -EIO; + int ret = -ENODEV; if (!vdev->fops->read) return -EINVAL; - if (vdev->lock) - mutex_lock(vdev->lock); + if (vdev->lock && mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->read(filp, buf, sz, off); if (vdev->lock) @@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, size_t sz, loff_t *off) { struct video_device *vdev = video_devdata(filp); - int ret = -EIO; + int ret = -ENODEV; if (!vdev->fops->write) return -EINVAL; - if (vdev->lock) - mutex_lock(vdev->lock); + if (vdev->lock && mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->write(filp, buf, sz, off); if (vdev->lock) @@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) { struct video_device *vdev = video_devdata(filp); - int ret = DEFAULT_POLLMASK; + int ret = POLLERR | POLLHUP; if (!vdev->fops->poll) - return ret; + return DEFAULT_POLLMASK; if (vdev->lock) mutex_lock(vdev->lock); if (video_is_registered(vdev)) @@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int ret = -ENODEV; if (vdev->fops->unlocked_ioctl) { - if (vdev->lock) - mutex_lock(vdev->lock); + if (vdev->lock && mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); if (vdev->lock) mutex_unlock(vdev->lock); } else if (vdev->fops->ioctl) { - /* TODO: convert all drivers to unlocked_ioctl */ + /* This code path is a replacement for the BKL. It is a major + * hack but it will have to do for those drivers that are not + * yet converted to use unlocked_ioctl. + * + * There are two options: if the driver implements struct + * v4l2_device, then the lock defined there is used to + * serialize the ioctls. Otherwise the v4l2 core lock defined + * below is used. This lock is really bad since it serializes + * completely independent devices. + * + * Both variants suffer from the same problem: if the driver + * sleeps, then it blocks all ioctls since the lock is still + * held. This is very common for VIDIOC_DQBUF since that + * normally waits for a frame to arrive. As a result any other + * ioctl calls will proceed very, very slowly since each call + * will have to wait for the VIDIOC_QBUF to finish. Things that + * should take 0.01s may now take 10-20 seconds. + * + * The workaround is to *not* take the lock for VIDIOC_DQBUF. + * This actually works OK for videobuf-based drivers, since + * videobuf will take its own internal lock. + */ static DEFINE_MUTEX(v4l2_ioctl_mutex); + struct mutex *m = vdev->v4l2_dev ? + &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex; - mutex_lock(&v4l2_ioctl_mutex); + if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) + return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->ioctl(filp, cmd, arg); - mutex_unlock(&v4l2_ioctl_mutex); + if (cmd != VIDIOC_DQBUF) + mutex_unlock(m); } else ret = -ENOTTY; @@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) if (!vdev->fops->mmap) return ret; - if (vdev->lock) - mutex_lock(vdev->lock); + if (vdev->lock && mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->mmap(filp, vm); if (vdev->lock) @@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) mutex_lock(&videodev_lock); vdev = video_devdata(filp); /* return ENODEV if the video device has already been removed. */ - if (vdev == NULL) { + if (vdev == NULL || !video_is_registered(vdev)) { mutex_unlock(&videodev_lock); return -ENODEV; } @@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp) video_get(vdev); mutex_unlock(&videodev_lock); if (vdev->fops->open) { - if (vdev->lock) - mutex_lock(vdev->lock); + if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { + ret = -ERESTARTSYS; + goto err; + } if (video_is_registered(vdev)) ret = vdev->fops->open(filp); else @@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) mutex_unlock(vdev->lock); } +err: /* decrease the refcount in case of an error */ if (ret) video_put(vdev); @@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev) if (!vdev || !video_is_registered(vdev)) return; + mutex_lock(&videodev_lock); + /* This must be in a critical section to prevent a race with v4l2_open. + * Once this bit has been cleared video_get may never be called again. + */ clear_bit(V4L2_FL_REGISTERED, &vdev->flags); + mutex_unlock(&videodev_lock); device_unregister(&vdev->dev); } EXPORT_SYMBOL(video_unregister_device); diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 0b08f96b74a..7fe6f92af48 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) INIT_LIST_HEAD(&v4l2_dev->subdevs); spin_lock_init(&v4l2_dev->lock); + mutex_init(&v4l2_dev->ioctl_lock); v4l2_dev->dev = dev; if (dev == NULL) { /* If dev == NULL, then name must be filled in by the caller */ diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index dd9283fcb56..7e47f15f350 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -18,12 +18,8 @@ #include <linux/kernel.h> #define __OLD_VIDIOC_ /* To allow fixing old calls */ -#include <linux/videodev.h> #include <linux/videodev2.h> -#ifdef CONFIG_VIDEO_V4L1 -#include <linux/videodev.h> -#endif #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> @@ -183,42 +179,6 @@ static const char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static const char *v4l1_ioctls[] = { - [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", - [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", - [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN", - [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER", - [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER", - [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT", - [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT", - [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE", - [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN", - [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN", - [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF", - [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF", - [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY", - [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ", - [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ", - [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO", - [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO", - [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC", - [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE", - [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF", - [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT", - [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE", - [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE", - [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE", - [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE", - [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO", - [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE", - [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT", - [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT" -}; -#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) -#endif - static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", @@ -310,15 +270,6 @@ void v4l_printk_ioctl(unsigned int cmd) case 'd': type = "v4l2_int"; break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case 'v': - if (_IOC_NR(cmd) >= V4L1_IOCTLS) { - type = "v4l1"; - break; - } - printk("%s", v4l1_ioctls[_IOC_NR(cmd)]); - return; -#endif case 'V': if (_IOC_NR(cmd) >= V4L2_IOCTLS) { type = "v4l2"; @@ -622,20 +573,6 @@ static long __video_do_ioctl(struct file *file, return -EINVAL; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /******************************************************** - All other V4L1 calls are handled by v4l1_compat module. - Those calls will be translated into V4L2 calls, and - __video_do_ioctl will be called again, with one or more - V4L2 ioctls. - ********************************************************/ - if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF && - _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) { - return v4l_compat_translate_ioctl(file, cmd, arg, - __video_do_ioctl); - } -#endif - if ((vfd->debug & V4L2_DEBUG_IOCTL) && !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, cmd); @@ -644,29 +581,6 @@ static long __video_do_ioctl(struct file *file, switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /*********************************************************** - Handles calls to the obsoleted V4L1 API - Due to the nature of VIDIOCGMBUF, each driver that supports - V4L1 should implement its own handler for this ioctl. - ***********************************************************/ - - /* --- streaming capture ------------------------------------- */ - case VIDIOCGMBUF: - { - struct video_mbuf *p = arg; - - if (!ops->vidiocgmbuf) - break; - ret = ops->vidiocgmbuf(file, fh, p); - if (!ret) - dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", - p->size, p->frames, - (unsigned long)p->offsets); - break; - } -#endif - /* --- capabilities ------------------------------------------ */ case VIDIOC_QUERYCAP: { diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index 02a21bccae1..e25aca5759f 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c @@ -1161,16 +1161,6 @@ out: return ret; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int viacam_vidiocgmbuf(struct file *filp, void *priv, - struct video_mbuf *mbuf) -{ - struct via_camera *cam = priv; - - return videobuf_cgmbuf(&cam->vb_queue, mbuf, 6); -} -#endif - /* G/S_PARM */ static int viacam_g_parm(struct file *filp, void *priv, @@ -1251,9 +1241,6 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_s_parm = viacam_s_parm, .vidioc_enum_framesizes = viacam_enum_framesizes, .vidioc_enum_frameintervals = viacam_enum_frameintervals, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = viacam_vidiocgmbuf, -#endif }; /*----------------------------------------------------------------------------*/ @@ -1360,7 +1347,7 @@ static __devinit int viacam_probe(struct platform_device *pdev) */ sensor_adapter = viafb_find_i2c_adapter(VIA_PORT_31); cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, sensor_adapter, - "ov7670", "ov7670", 0x42 >> 1, NULL); + "ov7670", 0x42 >> 1, NULL); if (cam->sensor == NULL) { dev_err(&pdev->dev, "Unable to find the sensor!\n"); ret = -ENODEV; diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 8979f91fa8e..de4fa4eb884 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -1202,33 +1202,3 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) return rc; } EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -int videobuf_cgmbuf(struct videobuf_queue *q, - struct video_mbuf *mbuf, int count) -{ - struct v4l2_requestbuffers req; - int rc, i; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - memset(&req, 0, sizeof(req)); - req.type = q->type; - req.count = count; - req.memory = V4L2_MEMORY_MMAP; - rc = videobuf_reqbufs(q, &req); - if (rc < 0) - return rc; - - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += PAGE_ALIGN(q->bufs[i]->bsize); - } - - return 0; -} -EXPORT_SYMBOL_GPL(videobuf_cgmbuf); -#endif - diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 20f227ee2b3..ddb8f4b46c0 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -69,10 +69,9 @@ static struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, struct page *pg; int i; - sglist = vmalloc(nr_pages * sizeof(*sglist)); + sglist = vzalloc(nr_pages * sizeof(*sglist)); if (NULL == sglist) return NULL; - memset(sglist, 0, nr_pages * sizeof(*sglist)); sg_init_table(sglist, nr_pages); for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { pg = vmalloc_to_page(virt); @@ -544,14 +543,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, retval = -EINVAL; - /* This function maintains backwards compatibility with V4L1 and will - * map more than one buffer if the vma length is equal to the combined - * size of multiple buffers than it will map them together. See - * VIDIOCGMBUF in the v4l spec - * - * TODO: Allow drivers to specify if they support this mode - */ - BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); @@ -571,29 +562,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, } last = first; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - if (size != (vma->vm_end - vma->vm_start)) { - /* look for last buffer to map */ - for (last = first + 1; last < VIDEO_MAX_FRAME; last++) { - if (NULL == q->bufs[last]) - continue; - if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) - continue; - if (q->bufs[last]->map) { - retval = -EBUSY; - goto done; - } - size += PAGE_ALIGN(q->bufs[last]->bsize); - if (size == (vma->vm_end - vma->vm_start)) - break; - } - if (VIDEO_MAX_FRAME == last) { - dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n", - (vma->vm_end - vma->vm_start)); - goto done; - } - } -#endif /* create mapping + update buffer list */ retval = -ENOMEM; diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index e5e005dc155..d63e9d97849 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -2954,9 +2954,6 @@ static int vino_enum_input(struct file *file, void *__fh, if (input == VINO_INPUT_NONE) return -EINVAL; - memset(i, 0, sizeof(struct v4l2_input)); - - i->index = index; i->type = V4L2_INPUT_TYPE_CAMERA; i->std = vino_inputs[input].std; strcpy(i->name, vino_inputs[input].name); @@ -4334,10 +4331,10 @@ static int __init vino_module_init(void) vino_drvdata->decoder = v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, - NULL, "saa7191", 0, I2C_ADDRS(0x45)); + "saa7191", 0, I2C_ADDRS(0x45)); vino_drvdata->camera = v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, - NULL, "indycam", 0, I2C_ADDRS(0x2b)); + "indycam", 0, I2C_ADDRS(0x2b)); dprintk("init complete!\n"); diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9797e5a6926..c49c39386bd 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -870,15 +870,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct vivi_dev *dev = video_drvdata(file); - - return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8); -} -#endif - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct vivi_dev *dev = video_drvdata(file); @@ -1105,9 +1096,6 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static struct video_device vivi_template = { diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 635420d8d84..019ee206cbe 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -815,7 +815,7 @@ out: static const struct v4l2_file_operations w9966_fops = { .owner = THIS_MODULE, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .read = w9966_v4l_read, }; diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 13552564908..fe8ef6419f8 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -35,7 +35,6 @@ #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> -#include <media/wm8775.h> MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); @@ -51,16 +50,10 @@ enum { TOT_REGS }; -#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */ -#define ALC_EN 0x100 /* R17: ALC enable */ - struct wm8775_state { struct v4l2_subdev sd; struct v4l2_ctrl_handler hdl; struct v4l2_ctrl *mute; - struct v4l2_ctrl *vol; - struct v4l2_ctrl *bal; - struct v4l2_ctrl *loud; u8 input; /* Last selected input (0-0xf) */ }; @@ -92,30 +85,6 @@ static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val) return -1; } -static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly) -{ - struct wm8775_state *state = to_state(sd); - u8 vol_l, vol_r; - int muted = 0 != state->mute->val; - u16 volume = (u16)state->vol->val; - u16 balance = (u16)state->bal->val; - - /* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */ - vol_l = (min(65536 - balance, 32768) * volume) >> 23; - vol_r = (min(balance, (u16)32768) * volume) >> 23; - - /* Mute */ - if (muted || quietly) - wm8775_write(sd, R21, 0x0c0 | state->input); - - wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */ - wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */ - - /* Un-mute */ - if (!muted) - wm8775_write(sd, R21, state->input); -} - static int wm8775_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { @@ -133,26 +102,25 @@ static int wm8775_s_routing(struct v4l2_subdev *sd, state->input = input; if (!v4l2_ctrl_g_ctrl(state->mute)) return 0; - if (!v4l2_ctrl_g_ctrl(state->vol)) - return 0; - if (!v4l2_ctrl_g_ctrl(state->bal)) - return 0; - wm8775_set_audio(sd, 1); + wm8775_write(sd, R21, 0x0c0); + wm8775_write(sd, R14, 0x1d4); + wm8775_write(sd, R15, 0x1d4); + wm8775_write(sd, R21, 0x100 + state->input); return 0; } static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_sd(ctrl); + struct wm8775_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BALANCE: - wm8775_set_audio(sd, 0); - return 0; - case V4L2_CID_AUDIO_LOUDNESS: - wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD); + wm8775_write(sd, R21, 0x0c0); + wm8775_write(sd, R14, 0x1d4); + wm8775_write(sd, R15, 0x1d4); + if (!ctrl->val) + wm8775_write(sd, R21, 0x100 + state->input); return 0; } return -EINVAL; @@ -176,7 +144,16 @@ static int wm8775_log_status(struct v4l2_subdev *sd) static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) { - wm8775_set_audio(sd, 0); + struct wm8775_state *state = to_state(sd); + + /* If I remove this, then it can happen that I have no + sound the first time I tune from static to a valid channel. + It's difficult to reproduce and is almost certainly related + to the zero cross detect circuit. */ + wm8775_write(sd, R21, 0x0c0); + wm8775_write(sd, R14, 0x1d4); + wm8775_write(sd, R15, 0x1d4); + wm8775_write(sd, R21, 0x100 + state->input); return 0; } @@ -226,7 +203,6 @@ static int wm8775_probe(struct i2c_client *client, { struct wm8775_state *state; struct v4l2_subdev *sd; - int err; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -240,21 +216,15 @@ static int wm8775_probe(struct i2c_client *client, return -ENOMEM; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &wm8775_ops); - sd->grp_id = WM8775_GID; /* subdev group id */ state->input = 2; - v4l2_ctrl_handler_init(&state->hdl, 4); + v4l2_ctrl_handler_init(&state->hdl, 1); state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); - state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, - V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/ - state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, - V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768); - state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, - V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1); sd->ctrl_handler = &state->hdl; - err = state->hdl.error; - if (err) { + if (state->hdl.error) { + int err = state->hdl.error; + v4l2_ctrl_handler_free(&state->hdl); kfree(state); return err; @@ -266,25 +236,29 @@ static int wm8775_probe(struct i2c_client *client, wm8775_write(sd, R23, 0x000); /* Disable zero cross detect timeout */ wm8775_write(sd, R7, 0x000); - /* HPF enable, I2S mode, 24-bit */ - wm8775_write(sd, R11, 0x022); + /* Left justified, 24-bit mode */ + wm8775_write(sd, R11, 0x021); /* Master mode, clock ratio 256fs */ wm8775_write(sd, R12, 0x102); /* Powered up */ wm8775_write(sd, R13, 0x000); - /* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */ - wm8775_write(sd, R16, 0x1bb); - /* Set ALC mode and hold time */ - wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD); + /* ADC gain +2.5dB, enable zero cross */ + wm8775_write(sd, R14, 0x1d4); + /* ADC gain +2.5dB, enable zero cross */ + wm8775_write(sd, R15, 0x1d4); + /* ALC Stereo, ALC target level -1dB FS max gain +8dB */ + wm8775_write(sd, R16, 0x1bf); + /* Enable gain control, use zero cross detection, + ALC hold time 42.6 ms */ + wm8775_write(sd, R17, 0x185); /* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */ wm8775_write(sd, R18, 0x0a2); /* Enable noise gate, threshold -72dBfs */ wm8775_write(sd, R19, 0x005); - /* Transient window 4ms, ALC min gain -5dB */ - wm8775_write(sd, R20, 0x0fb); - - wm8775_set_audio(sd, 1); /* set volume/mute/mux */ - + /* Transient window 4ms, lower PGA gain limit -1dB */ + wm8775_write(sd, R20, 0x07a); + /* LRBOTH = 1, use input 2. */ + wm8775_write(sd, R21, 0x102); return 0; } diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 27f05551183..4bb368e6fd4 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -33,15 +33,6 @@ #include <media/v4l2-device.h> -#define ZORAN_VIDMODE_PAL 0 -#define ZORAN_VIDMODE_NTSC 1 -#define ZORAN_VIDMODE_SECAM 2 - -struct zoran_requestbuffers { - unsigned long count; /* Number of buffers for MJPEG grabbing */ - unsigned long size; /* Size PER BUFFER in bytes */ -}; - struct zoran_sync { unsigned long frame; /* number of buffer that has been free'd */ unsigned long length; /* number of code bytes in buffer (capture only) */ @@ -49,102 +40,6 @@ struct zoran_sync { struct timeval timestamp; /* timestamp */ }; -struct zoran_status { - int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ - int signal; /* Returned: 1 if valid video signal detected */ - int norm; /* Returned: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ - int color; /* Returned: 1 if color signal detected */ -}; - -struct zoran_params { - - /* The following parameters can only be queried */ - - int major_version; /* Major version number of driver */ - int minor_version; /* Minor version number of driver */ - - /* Main control parameters */ - - int input; /* Input channel: 0 = Composite, 1 = S-VHS */ - int norm; /* Norm: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ - int decimation; /* decimation of captured video, - * enlargement of video played back. - * Valid values are 1, 2, 4 or 0. - * 0 is a special value where the user - * has full control over video scaling */ - - /* The following parameters only have to be set if decimation==0, - * for other values of decimation they provide the data how the image is captured */ - - int HorDcm; /* Horizontal decimation: 1, 2 or 4 */ - int VerDcm; /* Vertical decimation: 1 or 2 */ - int TmpDcm; /* Temporal decimation: 1 or 2, - * if TmpDcm==2 in capture every second frame is dropped, - * in playback every frame is played twice */ - int field_per_buff; /* Number of fields per buffer: 1 or 2 */ - int img_x; /* start of image in x direction */ - int img_y; /* start of image in y direction */ - int img_width; /* image width BEFORE decimation, - * must be a multiple of HorDcm*16 */ - int img_height; /* image height BEFORE decimation, - * must be a multiple of VerDcm*8 */ - - /* --- End of parameters for decimation==0 only --- */ - - /* JPEG control parameters */ - - int quality; /* Measure for quality of compressed images. - * Scales linearly with the size of the compressed images. - * Must be beetween 0 and 100, 100 is a compression - * ratio of 1:4 */ - - int odd_even; /* Which field should come first ??? */ - - int APPn; /* Number of APP segment to be written, must be 0..15 */ - int APP_len; /* Length of data in JPEG APPn segment */ - char APP_data[60]; /* Data in the JPEG APPn segment. */ - - int COM_len; /* Length of data in JPEG COM segment */ - char COM_data[60]; /* Data in JPEG COM segment */ - - unsigned long jpeg_markers; /* Which markers should go into the JPEG output. - * Unless you exactly know what you do, leave them untouched. - * Inluding less markers will make the resulting code - * smaller, but there will be fewer applications - * which can read it. - * The presence of the APP and COM marker is - * influenced by APP0_len and COM_len ONLY! */ -#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ -#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ -#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ -#define JPEG_MARKER_COM (1<<6) /* Comment segment */ -#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ - - int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. - * If this flag is turned on and JPEG decompressing - * is going to the screen, the decompress process - * is stopped every time the Video Fifo is full. - * This enables a smooth decompress to the screen - * but the video output signal will get scrambled */ - - /* Misc */ - - char reserved[312]; /* Makes 512 bytes for this structure */ -}; - -/* -Private IOCTL to set up for displaying MJPEG -*/ -#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOC_PRIVATE+0, struct zoran_params) -#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOC_PRIVATE+1, struct zoran_params) -#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOC_PRIVATE+2, struct zoran_requestbuffers) -#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOC_PRIVATE+3, int) -#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOC_PRIVATE+4, int) -#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOC_PRIVATE+5, struct zoran_sync) -#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOC_PRIVATE+6, struct zoran_status) - - -#ifdef __KERNEL__ #define MAJOR_VERSION 0 /* driver major version */ #define MINOR_VERSION 10 /* driver minor version */ @@ -507,6 +402,4 @@ static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev) #define btor(dat,adr) btwrite((dat) | btread(adr), adr) #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) -#endif /* __kernel__ */ - #endif diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 7e6d62467ea..9cdc3bb15b1 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -943,7 +943,7 @@ zoran_open_init_params (struct zoran *zr) memset(zr->jpg_settings.jpg_comp.COM_data, 0, sizeof(zr->jpg_settings.jpg_comp.COM_data)); zr->jpg_settings.jpg_comp.jpeg_markers = - JPEG_MARKER_DHT | JPEG_MARKER_DQT; + V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT; i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); if (i) dprintk(1, KERN_ERR "%s: %s internal error\n", @@ -1343,13 +1343,12 @@ static int __devinit zoran_probe(struct pci_dev *pdev, } zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, - &zr->i2c_adapter, NULL, zr->card.i2c_decoder, + &zr->i2c_adapter, zr->card.i2c_decoder, 0, zr->card.addrs_decoder); if (zr->card.i2c_encoder) zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, - &zr->i2c_adapter, - NULL, zr->card.i2c_encoder, + &zr->i2c_adapter, zr->card.i2c_encoder, 0, zr->card.addrs_encoder); dprintk(2, diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index b02007e4215..e8a27844bf3 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -1523,7 +1523,7 @@ zoran_irq (int irq, zr->JPEG_missed > 25 || zr->JPEG_error == 1 || ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) && - (zr->frame_num & (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { + (zr->frame_num && (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { error_handler(zr, astat, stat); } diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 67a52e844ae..7c3921de958 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1528,323 +1528,6 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - struct zoran_jpg_settings settings; - - switch (cmd) { - case BUZIOC_G_PARAMS: - { - struct zoran_params *bparams = arg; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_G_PARAMS\n", ZR_DEVNAME(zr)); - - memset(bparams, 0, sizeof(struct zoran_params)); - bparams->major_version = MAJOR_VERSION; - bparams->minor_version = MINOR_VERSION; - - mutex_lock(&zr->resource_lock); - - if (zr->norm & V4L2_STD_NTSC) - bparams->norm = ZORAN_VIDMODE_NTSC; - else if (zr->norm & V4L2_STD_SECAM) - bparams->norm = ZORAN_VIDMODE_SECAM; - else - bparams->norm = ZORAN_VIDMODE_PAL; - - bparams->input = zr->input; - - bparams->decimation = fh->jpg_settings.decimation; - bparams->HorDcm = fh->jpg_settings.HorDcm; - bparams->VerDcm = fh->jpg_settings.VerDcm; - bparams->TmpDcm = fh->jpg_settings.TmpDcm; - bparams->field_per_buff = fh->jpg_settings.field_per_buff; - bparams->img_x = fh->jpg_settings.img_x; - bparams->img_y = fh->jpg_settings.img_y; - bparams->img_width = fh->jpg_settings.img_width; - bparams->img_height = fh->jpg_settings.img_height; - bparams->odd_even = fh->jpg_settings.odd_even; - - bparams->quality = fh->jpg_settings.jpg_comp.quality; - bparams->APPn = fh->jpg_settings.jpg_comp.APPn; - bparams->APP_len = fh->jpg_settings.jpg_comp.APP_len; - memcpy(bparams->APP_data, - fh->jpg_settings.jpg_comp.APP_data, - sizeof(bparams->APP_data)); - bparams->COM_len = zr->jpg_settings.jpg_comp.COM_len; - memcpy(bparams->COM_data, - fh->jpg_settings.jpg_comp.COM_data, - sizeof(bparams->COM_data)); - bparams->jpeg_markers = - fh->jpg_settings.jpg_comp.jpeg_markers; - - mutex_unlock(&zr->resource_lock); - - bparams->VFIFO_FB = 0; - - return 0; - } - - case BUZIOC_S_PARAMS: - { - struct zoran_params *bparams = arg; - int res = 0; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_S_PARAMS\n", ZR_DEVNAME(zr)); - - settings.decimation = bparams->decimation; - settings.HorDcm = bparams->HorDcm; - settings.VerDcm = bparams->VerDcm; - settings.TmpDcm = bparams->TmpDcm; - settings.field_per_buff = bparams->field_per_buff; - settings.img_x = bparams->img_x; - settings.img_y = bparams->img_y; - settings.img_width = bparams->img_width; - settings.img_height = bparams->img_height; - settings.odd_even = bparams->odd_even; - - settings.jpg_comp.quality = bparams->quality; - settings.jpg_comp.APPn = bparams->APPn; - settings.jpg_comp.APP_len = bparams->APP_len; - memcpy(settings.jpg_comp.APP_data, bparams->APP_data, - sizeof(bparams->APP_data)); - settings.jpg_comp.COM_len = bparams->COM_len; - memcpy(settings.jpg_comp.COM_data, bparams->COM_data, - sizeof(bparams->COM_data)); - settings.jpg_comp.jpeg_markers = bparams->jpeg_markers; - - mutex_lock(&zr->resource_lock); - - if (zr->codec_mode != BUZ_MODE_IDLE) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_S_PARAMS called, but Buz in capture/playback mode\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto sparams_unlock_and_return; - } - - /* Check the params first before overwriting our - * nternal values */ - if (zoran_check_jpg_settings(zr, &settings, 0)) { - res = -EINVAL; - goto sparams_unlock_and_return; - } - - fh->jpg_settings = settings; -sparams_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_REQBUFS: - { - struct zoran_requestbuffers *breq = arg; - int res = 0; - - dprintk(3, - KERN_DEBUG - "%s: BUZIOC_REQBUFS - count=%lu, size=%lu\n", - ZR_DEVNAME(zr), breq->count, breq->size); - - /* Enforce reasonable lower and upper limits */ - if (breq->count < 4) - breq->count = 4; /* Could be choosen smaller */ - if (breq->count > jpg_nbufs) - breq->count = jpg_nbufs; - breq->size = PAGE_ALIGN(breq->size); - if (breq->size < 8192) - breq->size = 8192; /* Arbitrary */ - /* breq->size is limited by 1 page for the stat_com - * tables to a Maximum of 2 MB */ - if (breq->size > jpg_bufsize) - breq->size = jpg_bufsize; - - mutex_lock(&zr->resource_lock); - - if (fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_REQBUFS - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto jpgreqbuf_unlock_and_return; - } - - /* The next mmap will map the MJPEG buffers - could - * also be *_PLAY, but it doesn't matter here */ - map_mode_jpg(fh, 0); - fh->buffers.num_buffers = breq->count; - fh->buffers.buffer_size = breq->size; - - if (jpg_fbuffer_alloc(fh)) { - res = -ENOMEM; - goto jpgreqbuf_unlock_and_return; - } - -jpgreqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_QBUF_CAPT: - { - int *frame = arg, res; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n", - ZR_DEVNAME(zr), *frame); - - mutex_lock(&zr->resource_lock); - res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_COMPRESS); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_QBUF_PLAY: - { - int *frame = arg, res; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n", - ZR_DEVNAME(zr), *frame); - - mutex_lock(&zr->resource_lock); - res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_DECOMPRESS); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_SYNC: - { - struct zoran_sync *bsync = arg; - int res; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - dprintk(2, KERN_WARNING - "%s: %s - not in jpg capture mode\n", - ZR_DEVNAME(zr), __func__); - res = -EINVAL; - } else { - res = jpg_sync(fh, bsync); - } - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_G_STATUS: - { - struct zoran_status *bstat = arg; - int status = 0, res = 0; - v4l2_std_id norm; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr)); - - if (zr->codec_mode != BUZ_MODE_IDLE) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_G_STATUS called but Buz in capture/playback mode\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - mutex_lock(&zr->resource_lock); - - if (zr->codec_mode != BUZ_MODE_IDLE) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_G_STATUS called, but Buz in capture/playback mode\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto gstat_unlock_and_return; - } - - decoder_call(zr, video, s_routing, - zr->card.input[bstat->input].muxsel, 0, 0); - - /* sleep 1 second */ - ssleep(1); - - /* Get status of video decoder */ - decoder_call(zr, video, querystd, &norm); - decoder_call(zr, video, g_input_status, &status); - - /* restore previous input and norm */ - decoder_call(zr, video, s_routing, - zr->card.input[zr->input].muxsel, 0, 0); -gstat_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - if (!res) { - bstat->signal = - (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; - if (norm & V4L2_STD_NTSC) - bstat->norm = ZORAN_VIDMODE_NTSC; - else if (norm & V4L2_STD_SECAM) - bstat->norm = ZORAN_VIDMODE_SECAM; - else - bstat->norm = ZORAN_VIDMODE_PAL; - - bstat->color = - (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; - } - - return res; - } - - default: - return -EINVAL; - } -} - -static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *vmbuf) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int i, res = 0; - - - mutex_lock(&zr->resource_lock); - - if (fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOCGMBUF - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto v4l1reqbuf_unlock_and_return; - } - - /* The next mmap will map the V4L buffers */ - map_mode_raw(fh); - - if (v4l_fbuffer_alloc(fh)) { - res = -ENOMEM; - goto v4l1reqbuf_unlock_and_return; - } - - vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size; - vmbuf->frames = fh->buffers.num_buffers; - for (i = 0; i < vmbuf->frames; i++) - vmbuf->offsets[i] = i * fh->buffers.buffer_size; - -v4l1reqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; -} -#endif - static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) { struct zoran_fh *fh = __fh; @@ -2533,6 +2216,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = -EAGAIN; goto dqbuf_unlock_and_return; } + bs.frame = 0; /* suppress compiler warning */ res = jpg_sync(fh, &bs); if (res) goto dqbuf_unlock_and_return; @@ -2766,11 +2450,6 @@ static int zoran_enum_input(struct file *file, void *__fh, if (inp->index >= zr->card.inputs) return -EINVAL; - else { - int id = inp->index; - memset(inp, 0, sizeof(*inp)); - inp->index = id; - } strncpy(inp->name, zr->card.input[inp->index].name, sizeof(inp->name) - 1); @@ -2820,7 +2499,6 @@ static int zoran_enum_output(struct file *file, void *__fh, if (outp->index != 0) return -EINVAL; - memset(outp, 0, sizeof(*outp)); outp->index = 0; outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); @@ -3364,10 +3042,6 @@ static const struct v4l2_ioctl_ops zoran_ioctl_ops = { .vidioc_queryctrl = zoran_queryctrl, .vidioc_s_ctrl = zoran_s_ctrl, .vidioc_g_ctrl = zoran_g_ctrl, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidioc_default = zoran_default, - .vidiocgmbuf = zoran_vidiocgmbuf, -#endif }; /* please use zr->resource_lock consistently and kill this wrapper */ |