diff options
Diffstat (limited to 'linux/drivers/media/video')
126 files changed, 4770 insertions, 2570 deletions
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index ac65aaf20..070f4b1c0 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -2,14 +2,19 @@ # Multimedia Video device configuration # -menu "Video Capture Adapters" +menuconfig VIDEO_CAPTURE_DRIVERS + bool "Video capture adapters" depends on VIDEO_DEV + default y + ---help--- + Say Y here to enable selecting the video adapters for + webcams, analog TV, and hybrid analog/digital TV. + Some of those devices also supports FM radio. -comment "Video Capture Adapters" +if VIDEO_CAPTURE_DRIVERS config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" - depends on VIDEO_DEV default n ---help--- Say Y here to enable advanced debugging functionality on some @@ -34,7 +39,7 @@ config VIDEO_HELPER_CHIPS_AUTO # menu "Encoders/decoders and other helper chips" - depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO + depends on !VIDEO_HELPER_CHIPS_AUTO comment "Audio decoders" @@ -61,7 +66,7 @@ config VIDEO_TDA7432 config VIDEO_TDA9840 tristate "Philips TDA9840 audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tda9840 audio decoder chip found on some Zoran boards. @@ -79,7 +84,7 @@ config VIDEO_TDA9875 config VIDEO_TEA6415C tristate "Philips TEA6415C audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tea6415c audio decoder chip found on some bt8xx boards. @@ -88,7 +93,7 @@ config VIDEO_TEA6415C config VIDEO_TEA6420 tristate "Philips TEA6420 audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tea6420 audio decoder chip found on some bt8xx boards. @@ -469,7 +474,7 @@ config VIDEO_SAA5246A config VIDEO_SAA5249 tristate "SAA5249 Teletext processor" - depends on VIDEO_DEV && I2C && VIDEO_V4L2 + depends on I2C && VIDEO_V4L2 help Support for I2C bus based teletext using the SAA5249 chip. At the moment this is only useful on some European WinTV cards. @@ -479,14 +484,14 @@ config VIDEO_SAA5249 config TUNER_3036 tristate "SAB3036 tuner" - depends on VIDEO_DEV && I2C && VIDEO_V4L1 + depends on I2C && VIDEO_V4L1 help Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. config TUNER_TEA5761 tristate "TEA 5761 radio tuner (EXPERIMENTAL)" - depends on VIDEO_DEV && I2C + depends on I2C select VIDEO_TUNER help Say Y here to include support for Philips TEA5761 radio tuner. @@ -585,14 +590,14 @@ config VIDEO_ZORAN_AVS6EYES config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" - depends on PCI && SONYPI && VIDEO_V4L1 + depends on PCI && SONY_LAPTOP && VIDEO_V4L1 ---help--- This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in <file:Documentation/video4linux/meye.txt> for more information. - If you say Y or M here, you need to say Y or M to "Sony Programmable - I/O Control Device" in the character device section. + If you say Y or M here, you need to say Y or M to "Sony Laptop + Extras" in the misc device section. To compile this driver as a module, choose M here: the module will be called meye. @@ -689,8 +694,12 @@ config VIDEO_CAFE_CCIC # USB Multimedia device configuration # -menu "V4L USB devices" - depends on USB && VIDEO_DEV +menuconfig V4L_USB_DRIVERS + bool "V4L USB devices" + depends on USB + default y + +if V4L_USB_DRIVERS source "drivers/media/video/pvrusb2/Kconfig" @@ -715,7 +724,7 @@ config VIDEO_OVCAMCHIP config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_V4L1 && I2C + depends on VIDEO_V4L1 && I2C select VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or @@ -733,7 +742,7 @@ config USB_W9968CF config USB_OV511 tristate "USB OV511 Camera support" - depends on USB && VIDEO_V4L1 + 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/ov511.txt> @@ -744,7 +753,7 @@ config USB_OV511 config USB_SE401 tristate "USB SE401 Camera support" - depends on USB && VIDEO_V4L1 + 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> @@ -757,7 +766,7 @@ source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 tristate "USB STV680 (Pencam) Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. @@ -773,7 +782,7 @@ source "drivers/media/video/pwc/Kconfig" config USB_ZR364XX tristate "USB ZR364XX Camera support" - depends on USB && VIDEO_V4L2 + depends on VIDEO_V4L2 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. @@ -783,6 +792,6 @@ config USB_ZR364XX To compile this driver as a module, choose M here: the module will be called zr364xx. -endmenu # V4L USB devices +endif # V4L_USB_DRIVERS -endmenu +endif # VIDEO_CAPTURE_DRIVERS diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 2fca38f92..90a48b507 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -37,7 +37,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index f4047bec6..e8487b745 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -33,7 +33,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index 64149b5c1..7e705c3d8 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -37,7 +37,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index ae2c1bc56..5b487acd1 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -37,7 +37,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 06c1a918f..be7342135 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -37,7 +37,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index b0e6c3e9c..c704efb05 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -314,6 +314,9 @@ static struct CARD { { 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" }, + { 0x53534149, BTTV_BOARD_SSAI_SECURITY, "SSAI Security Video Interface" }, + { 0x5353414a, BTTV_BOARD_SSAI_ULTRASOUND, "SSAI Ultrasound Video Interface" }, + /* likely broken, vendor id doesn't match the other magic views ... * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */ @@ -2952,6 +2955,28 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .has_remote = 1, }, + [BTTV_BOARD_SSAI_SECURITY] = { + .name = "SSAI Security Video Interface", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 0, 1, 2, 3 }, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_SSAI_ULTRASOUND] = { + .name = "SSAI Ultrasound Video Interface", + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 0, 1, 3 }, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3015,20 +3040,20 @@ void __devinit bttv_idcard(struct bttv *btv) if (UNSET != audiomux[0]) { gpiobits = 0; - for (i = 0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) { bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i]; gpiobits |= audiomux[i]; } } else { gpiobits = audioall; - for (i = 0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) { bttv_tvcards[btv->c.type].gpiomux[i] = audioall; } } bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", btv->c.nr,bttv_tvcards[btv->c.type].gpiomask); - for (i = 0; i < 5; i++) { + for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) { printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]); } printk("\n"); @@ -3692,7 +3717,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) for (n = 0; n < microlen; n++) { bits = micro[n]; - for ( i = 0 ; i < 8 ; i++ ) { + for (i = 0 ; i < 8 ; i++) { gpio_bits(BTTV_ALT_DCLK,0); if (bits & 0x01) gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA); @@ -3749,7 +3774,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) /* this might be an antique... check for MMAC label in eeprom */ if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { unsigned char checksum = 0; - for (i =0; i<21; i++) + for (i = 0; i < 21; i++) checksum += ee[i]; if (checksum != ee[21]) return; @@ -3761,12 +3786,13 @@ static void __devinit osprey_eeprom(struct bttv *btv) unsigned short type; int offset = 4*16; - for(; offset < 8*16; offset += 16) { + for (; offset < 8*16; offset += 16) { unsigned short checksum = 0; /* verify the checksum */ - for(i = 0; i<14; i++) checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && + for (i = 0; i < 14; i++) + checksum += ee[i+offset]; + checksum = ~checksum; /* no idea why */ + if ((((checksum>>8)&0x0FF) == ee[offset+14]) && ((checksum & 0x0FF) == ee[offset+15])) { break; } @@ -3779,7 +3805,6 @@ static void __devinit osprey_eeprom(struct bttv *btv) type = (ee[offset+4]<<8) | (ee[offset+5]); switch(type) { - /* 848 based */ case 0x0004: btv->c.type = BTTV_BOARD_OSPREY1x0_848; @@ -4245,8 +4270,7 @@ static int tea5757_read(struct bttv *btv) } dprintk("bttv%d: tea5757:",btv->c.nr); - for(i = 0; i < 24; i++) - { + for (i = 0; i < 24; i++) { udelay(5); bus_high(btv,btv->mbox_clk); udelay(5); @@ -4278,8 +4302,7 @@ static int tea5757_write(struct bttv *btv, int value) dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value); bus_low(btv,btv->mbox_clk); bus_high(btv,btv->mbox_we); - for(i = 0; i < 25; i++) - { + for (i = 0; i < 25; i++) { if (reg & 0x1000000) bus_high(btv,btv->mbox_data); else @@ -4871,7 +4894,7 @@ static void kodicom4400r_init(struct bttv *btv) gpio_write(1 << 9); /* reset MUX */ gpio_write(0); /* Preset camera 0 to the 4 controllers */ - for (ix=0; ix<4; ix++) { + for (ix = 0; ix < 4; ix++) { sw_status[ix] = ix; kodicom4400r_write(btv, ix, ix, 1); } diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 25a61e379..2aad57b5a 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -177,6 +177,36 @@ static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL); #endif /* ----------------------------------------------------------------------- */ +/* dvb auto-load setup */ +#if defined(CONFIG_MODULES) && defined(MODULE) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void request_module_async(void *ptr) +#else +static void request_module_async(struct work_struct *work) +#endif +{ + request_module("dvb-bt8xx"); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define request_modules(dev) +#else +static void request_modules(struct bttv *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&dev->request_module_wk, request_module_async, (void*)dev); +#else + INIT_WORK(&dev->request_module_wk, request_module_async); +#endif + schedule_work(&dev->request_module_wk); +} +#endif +#else +#define request_modules(dev) +#endif /* CONFIG_MODULES */ + + +/* ----------------------------------------------------------------------- */ /* static data */ /* special timing tables from conexant... */ @@ -4811,9 +4841,11 @@ static int __devinit bttv_probe(struct pci_dev *dev, } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* add subdevices */ - if (bttv_tvcards[btv->c.type].has_dvb) + /* add subdevices and autoload dvb-bt8xx if needed */ + if (bttv_tvcards[btv->c.type].has_dvb) { bttv_sub_add_device(&btv->c, "dvb"); + request_modules(btv); + } #endif bttv_input_init(btv); diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index 68522754a..3f545c610 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -426,7 +426,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) unsigned char buf; int i,rc; - for (i = 0; i < 128; i++) { + for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { c->addr = i; rc = i2c_master_recv(c,&buf,0); if (rc < 0) diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index ed565fb8b..f9681147d 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -169,6 +169,8 @@ #define BTTV_BOARD_SABRENT_TVFM 0x8e #define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f #define BTTV_BOARD_MACHTV_MAGICTV 0x90 +#define BTTV_BOARD_SSAI_SECURITY 0x91 +#define BTTV_BOARD_SSAI_ULTRASOUND 0x92 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index a273c424b..eee6f5ae3 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -452,6 +452,9 @@ struct bttv { unsigned int users; struct bttv_fh init; + /* used to make dvb-bt8xx autoloadable */ + struct work_struct request_module_wk; + /* Default (0) and current (1) video capturing and overlay cropping parameters in bttv_tvnorm.cropcap units. Protected by bttv.lock. */ diff --git a/linux/drivers/media/video/cafe_ccic-regs.h b/linux/drivers/media/video/cafe_ccic-regs.h index b2c22a0d6..8e2a87cdc 100644 --- a/linux/drivers/media/video/cafe_ccic-regs.h +++ b/linux/drivers/media/video/cafe_ccic-regs.h @@ -150,6 +150,12 @@ #define REG_GL_IMASK 0x300c /* Interrupt mask register */ #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ +#define REG_GL_FCR 0x3038 /* GPIO functional control register */ +#define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */ +#define REG_GL_GPIOR 0x315c /* GPIO register */ +#define GGPIO_OUT 0x80000 /* GPIO output */ +#define GGPIO_VAL 0x00008 /* Output pin value */ + #define REG_LEN REG_GL_IMASK + 4 diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index b96d45654..4480df11e 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -4,6 +4,7 @@ * sensor. * * Copyright 2006 One Laptop Per Child Association, Inc. + * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> * * Written by Jonathan Corbet, corbet@lwn.net. * @@ -38,7 +39,7 @@ #include "cafe_ccic-regs.h" -#define CAFE_VERSION 0x000001 +#define CAFE_VERSION 0x000002 /* @@ -712,7 +713,13 @@ static void cafe_ctlr_init(struct cafe_camera *cam) cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); + /* + * Here we must wait a bit for the controller to come around. + */ + spin_unlock_irqrestore(&cam->dev_lock, flags); mdelay(5); /* FIXME revisit this */ + spin_lock_irqsave(&cam->dev_lock, flags); + cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); /* @@ -775,15 +782,22 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam) spin_lock_irqsave(&cam->dev_lock, flags); cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); /* + * Part one of the sensor dance: turn the global + * GPIO signal on. + */ + cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); + cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL); + /* * Put the sensor into operational mode (assumes OLPC-style * wiring). Control 0 is reset - set to 1 to operate. * Control 1 is power down, set to 0 to operate. */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ - mdelay(1); /* Marvell says 1ms will do it */ +// mdelay(1); /* Marvell says 1ms will do it */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); - mdelay(1); /* Enough? */ +// mdelay(1); /* Enough? */ spin_unlock_irqrestore(&cam->dev_lock, flags); + msleep(5); /* Just to be sure */ } static void cafe_ctlr_power_down(struct cafe_camera *cam) @@ -792,6 +806,8 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam) spin_lock_irqsave(&cam->dev_lock, flags); cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); + cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); + cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT); cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); spin_unlock_irqrestore(&cam->dev_lock, flags); } @@ -851,6 +867,7 @@ static int cafe_cam_init(struct cafe_camera *cam) ret = 0; cam->state = S_IDLE; out: + cafe_ctlr_power_down(cam); mutex_unlock(&cam->s_mutex); return ret; } @@ -1803,18 +1820,19 @@ static void cafe_frame_tasklet(unsigned long data) if (list_empty(&cam->sb_avail)) break; /* Leave it valid, hope for better later */ clear_bit(bufno, &cam->flags); - /* - * We could perhaps drop the spinlock during this - * big copy. Something to consider. - */ sbuf = list_entry(cam->sb_avail.next, struct cafe_sio_buffer, list); + /* + * Drop the lock during the big copy. This *should* be safe... + */ + spin_unlock_irqrestore(&cam->dev_lock, flags); memcpy(sbuf->buffer, cam->dma_bufs[bufno], cam->pix_format.sizeimage); sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage; sbuf->v4lbuf.sequence = cam->buf_seq[bufno]; sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; + spin_lock_irqsave(&cam->dev_lock, flags); list_move_tail(&sbuf->list, &cam->sb_full); } if (! list_empty(&cam->sb_full)) @@ -2102,10 +2120,16 @@ static int cafe_pci_probe(struct pci_dev *pdev, ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); if (ret) goto out_iounmap; + /* + * Initialize the controller and leave it powered up. It will + * stay that way until the sensor driver shows up. + */ cafe_ctlr_init(cam); cafe_ctlr_power_up(cam); /* - * Set up I2C/SMBUS communications + * Set up I2C/SMBUS communications. We have to drop the mutex here + * because the sensor could attach in this call chain, leading to + * unsightly deadlocks. */ mutex_unlock(&cam->s_mutex); /* attach can deadlock */ ret = cafe_smbus_setup(cam); @@ -2118,6 +2142,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, cam->v4ldev = cafe_v4l_template; cam->v4ldev.debug = 0; // cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; + cam->v4ldev.dev = &pdev->dev; ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); if (ret) goto out_smbus; @@ -2187,10 +2212,52 @@ static void cafe_pci_remove(struct pci_dev *pdev) } +#ifdef CONFIG_PM +/* + * Basic power management. + */ +static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct cafe_camera *cam = cafe_find_by_pdev(pdev); + int ret; + + ret = pci_save_state(pdev); + if (ret) + return ret; + cafe_ctlr_stop_dma(cam); + cafe_ctlr_power_down(cam); + pci_disable_device(pdev); + return 0; +} + + +static int cafe_pci_resume(struct pci_dev *pdev) +{ + struct cafe_camera *cam = cafe_find_by_pdev(pdev); + int ret = 0; + + ret = pci_restore_state(pdev); + if (ret) + return ret; + ret = pci_enable_device(pdev); + if (ret) { + cam_warn(cam, "Unable to re-enable device on resume!\n"); + return ret; + } + cafe_ctlr_init(cam); + cafe_ctlr_power_up(cam); + set_bit(CF_CONFIG_NEEDED, &cam->flags); + if (cam->state == S_SPECREAD) + cam->state = S_IDLE; /* Don't bother restarting */ + else if (cam->state == S_SINGLEREAD || cam->state == S_STREAMING) + ret = cafe_read_setup(cam, cam->state); + return ret; +} + +#endif /* CONFIG_PM */ static struct pci_device_id cafe_ids[] = { - { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */ { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */ { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */ { 0, } @@ -2203,6 +2270,10 @@ static struct pci_driver cafe_pci_driver = { .id_table = cafe_ids, .probe = cafe_pci_probe, .remove = cafe_pci_remove, +#ifdef CONFIG_PM + .suspend = cafe_pci_suspend, + .resume = cafe_pci_resume, +#endif }; diff --git a/linux/drivers/media/video/cpia.h b/linux/drivers/media/video/cpia.h index d4f61b037..ed6201abe 100644 --- a/linux/drivers/media/video/cpia.h +++ b/linux/drivers/media/video/cpia.h @@ -48,7 +48,6 @@ #include <linux/videodev.h> #include <media/v4l2-common.h> #include <linux/list.h> -#include <linux/smp_lock.h> #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) #include <linux/mutex.h> #endif diff --git a/linux/drivers/media/video/cpia_pp.c b/linux/drivers/media/video/cpia_pp.c index 337675e96..9f4f5f590 100644 --- a/linux/drivers/media/video/cpia_pp.c +++ b/linux/drivers/media/video/cpia_pp.c @@ -34,7 +34,6 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/workqueue.h> -#include <linux/smp_lock.h> #include <linux/sched.h> #include <linux/kmod.h> @@ -62,7 +61,6 @@ static int cpia_pp_close(void *privdata); #define PPCPIA_PARPORT_OFF -2 #define PPCPIA_PARPORT_NONE -1 -#ifdef MODULE static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; static char *parport[PARPORT_MAX] = {NULL,}; @@ -72,11 +70,6 @@ MODULE_LICENSE("GPL"); module_param_array(parport, charp, NULL, 0); MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp."); -#else -static int parport_nr[PARPORT_MAX] __initdata = - {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; -static int parport_ptr = 0; -#endif struct pp_cam_entry { struct pardevice *pdev; @@ -827,7 +820,7 @@ static struct parport_driver cpia_pp_driver = { .detach = cpia_pp_detach, }; -static int cpia_pp_init(void) +static int __init cpia_pp_init(void) { printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); @@ -846,8 +839,7 @@ static int cpia_pp_init(void) return 0; } -#ifdef MODULE -int init_module(void) +static int __init cpia_init(void) { if (parport[0]) { /* The user gave some parameters. Let's see what they were. */ @@ -874,38 +866,11 @@ int init_module(void) return cpia_pp_init(); } -void cleanup_module(void) +static void __exit cpia_cleanup(void) { - parport_unregister_driver (&cpia_pp_driver); + parport_unregister_driver(&cpia_pp_driver); return; } -#else /* !MODULE */ - -static int __init cpia_pp_setup(char *str) -{ - int err; - - if (!strncmp(str, "parport", 7)) { - int n = simple_strtoul(str + 7, NULL, 10); - if (parport_ptr < PARPORT_MAX) { - parport_nr[parport_ptr++] = n; - } else { - LOG("too many ports, %s ignored.\n", str); - } - } else if (!strcmp(str, "auto")) { - parport_nr[0] = PPCPIA_PARPORT_AUTO; - } else if (!strcmp(str, "none")) { - parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; - } - - err=cpia_pp_init(); - if (err) - return err; - - return 1; -} - -__setup("cpia_pp=", cpia_pp_setup); - -#endif /* !MODULE */ +module_init(cpia_init); +module_exit(cpia_cleanup); diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c index 422d2c6a4..d34180c9d 100644 --- a/linux/drivers/media/video/cx2341x.c +++ b/linux/drivers/media/video/cx2341x.c @@ -26,7 +26,6 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/videodev2.h> -#include <linux/i2c.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include <linux/slab.h> #endif diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index c401c1ee7..9d40a2b95 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -566,7 +566,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; - int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); + int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -578,7 +578,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; - Vlines = pix->height + (is_pal ? 4 : 7); + Vlines = pix->height + (is_50Hz ? 4 : 7); if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index bf67ec27d..a2d0abae6 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -27,6 +27,8 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> +#include <linux/dma-mapping.h> + #include <asm/delay.h> #include <sound/driver.h> #include <sound/core.h> @@ -257,7 +259,8 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip) cx_write(MO_AUD_INTSTAT, status); if (debug > 1 || (status & mask & ~0xff)) cx88_print_irqbits(core->name, "irq aud", - cx88_aud_irqs, status, mask); + cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs), + status, mask); /* risc op code error */ if (status & (1 << 16)) { printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); @@ -467,11 +470,9 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, dprintk(1,"Setting buffer\n"); - buf = kmalloc(sizeof(*buf),GFP_KERNEL); + buf = kzalloc(sizeof(*buf),GFP_KERNEL); if (NULL == buf) return -ENOMEM; - memset(buf,0,sizeof(*buf)); - buf->vb.memory = V4L2_MEMORY_MMAP; buf->vb.width = chip->period_size; @@ -789,7 +790,7 @@ static int __devinit snd_cx88_create(struct snd_card *card, return err; } - if (!pci_dma_supported(pci,0xffffffff)) { + if (!pci_dma_supported(pci,DMA_32BIT_MASK)) { dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); err = -EIO; cx88_core_put(core,pci); diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 774bcfed9..ebde756b2 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -886,6 +886,12 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, .mpeg = CX88_MPEG_DVB, }, @@ -1362,6 +1368,26 @@ struct cx88_board cx88_boards[] = { /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, }, + [CX88_BOARD_ADSTECH_PTV_390] = { + .name = "ADS Tech Instant Video PCI", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DEBUG, + .vmux = 3, + .gpio0 = 0x04ff, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x07fa, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x07fa, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1668,6 +1694,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1421, .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */ .card = CX88_BOARD_KWORLD_DVBS_100, + },{ + .subvendor = 0x1421, + .subdevice = 0x0390, + .card = CX88_BOARD_ADSTECH_PTV_390, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1823,7 +1853,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) { 0x03, 0x0C }, }; - for (i = 0; i < 13; i++) { + for (i = 0; i < ARRAY_SIZE(init_bufs); i++) { msg.buf = init_bufs[i]; msg.len = (i != 12 ? 5 : 2); err = i2c_transfer(&core->i2c_adap, &msg, 1); @@ -1950,12 +1980,21 @@ void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) { /* enable tuner */ int i; - static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; + static const u8 buffer [][2] = { + {0x10,0x12}, + {0x13,0x04}, + {0x16,0x00}, + {0x14,0x04}, + {0x17,0x00} + }; core->i2c_client.addr = 0x0a; - for (i = 0; i < 5; i++) - if (2 != i2c_master_send(&core->i2c_client,&buffer[i*2],2)) - printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n", + for (i = 0; i < ARRAY_SIZE(buffer); i++) + if (2 != i2c_master_send(&core->i2c_client, + buffer[i],2)) + printk(KERN_WARNING + "%s: Unable to enable " + "tuner(%i).\n", core->name, i); } break; diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index 367dc3c7b..ba132d065 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -524,12 +524,12 @@ static char *cx88_pci_irqs[32] = { }; void cx88_print_irqbits(char *name, char *tag, char **strings, - u32 bits, u32 mask) + int len, u32 bits, u32 mask) { unsigned int i; printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); - for (i = 0; i < 32; i++) { + for (i = 0; i < len; i++) { if (!(bits & (1 << i))) continue; if (strings[i]) @@ -555,8 +555,8 @@ int cx88_core_irq(struct cx88_core *core, u32 status) } if (!handled) cx88_print_irqbits(core->name, "irq pci", - cx88_pci_irqs, status, - core->pci_irqmask); + cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs), + status, core->pci_irqmask); return handled; } diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 2b24c27a6..f01fee80b 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -36,9 +36,7 @@ #include "mt352.h" #include "mt352_priv.h" -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) -# include "cx88-vp3054-i2c.h" -#endif +#include "cx88-vp3054-i2c.h" #include "zl10353.h" #include "cx22702.h" #include "or51132.h" @@ -200,7 +198,7 @@ static struct mt352_config dvico_fusionhdtv_dual = { .demod_init = dvico_dual_demod_init, }; -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) +#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { 0x89, 0x38, 0x38 }; @@ -224,64 +222,6 @@ static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) return 0; } -static int philips_fmd1216_pll_init(struct dvb_frontend *fe) -{ - struct cx8802_dev *dev= fe->dvb->priv; - - /* this message is to set up ATC and ALC */ - static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; - struct i2c_msg msg = - { .addr = dev->core->pll_addr, .flags = 0, - .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; - int err; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} - -static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) -{ - struct cx8802_dev *dev= fe->dvb->priv; - u8 buf[4]; - struct i2c_msg msg = - { .addr = dev->core->pll_addr, .flags = 0, - .buf = buf, .len = 4 }; - int err; - - /* Switch PLL to DVB mode */ - err = philips_fmd1216_pll_init(fe); - if (err) - return err; - - /* Tune PLL */ - dvb_pll_configure(dev->core->pll_desc, buf, - params->frequency, - params->u.ofdm.bandwidth); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { - - printk(KERN_WARNING "cx88-dvb: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, dev->core->pll_addr, buf[0], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} - static struct mt352_config dntv_live_dvbt_pro_config = { .demod_address = 0x0f, .no_tuner = 1, @@ -371,18 +311,8 @@ static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) return 0; } -static int nxt200x_set_pll_input(u8* buf, int input) -{ - if (input) - buf[3] |= 0x08; - else - buf[3] &= ~0x08; - return 0; -} - static struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, - .set_pll_input = nxt200x_set_pll_input, .set_ts_params = nxt200x_set_ts_param, }; @@ -476,6 +406,8 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: + case CX88_BOARD_HAUPPAUGE_HVR1300: + case CX88_BOARD_HAUPPAUGE_HVR3000: dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &dev->core->i2c_adap); @@ -543,13 +475,12 @@ static int dvb_register(struct cx8802_dev *dev) } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_fmd1216me; +#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &((struct vp3054_i2c_state *)dev->card_priv)->adap); if (dev->dvb.frontend != NULL) { - dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, &dvb_pll_fmd1216me); } #else printk("%s: built without vp3054 support\n", dev->core->name); @@ -694,24 +625,6 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; - case CX88_BOARD_HAUPPAUGE_HVR1300: - dev->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &dev->core->i2c_adap); - if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, &dvb_pll_fmd1216me); - } - break; - case CX88_BOARD_HAUPPAUGE_HVR3000: - dev->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &dev->core->i2c_adap); - if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, &dvb_pll_fmd1216me); - } - break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); @@ -722,10 +635,6 @@ static int dvb_register(struct cx8802_dev *dev) return -1; } - if (dev->core->pll_desc) { - dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; - dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; - } /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; @@ -798,11 +707,10 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) goto fail_core; -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) + /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) goto fail_core; -#endif /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); @@ -827,9 +735,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) /* dvb */ videobuf_dvb_unregister(&dev->dvb); -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) vp3054_i2c_remove(dev); -#endif return 0; } diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index 2f60c957b..30fd0776a 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -1,3 +1,4 @@ + /* cx88-i2c.c -- all the i2c code is here @@ -206,7 +207,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) unsigned char buf; int i,rc; - for (i = 0; i < 128; i++) { + for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { c->addr = i; rc = i2c_master_recv(c,&buf,0); if (rc < 0) diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 6c712ecdd..a2e34e901 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -157,24 +157,20 @@ static void cx88_ir_work(struct work_struct *work) #else struct cx88_IR *ir = container_of(work, struct cx88_IR, work); #endif - unsigned long timeout; cx88_ir_handle_key(ir); - timeout = jiffies + (ir->polling * HZ / 1000); - mod_timer(&ir->timer, timeout); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { + setup_timer(&ir->timer, ir_timer, (unsigned long)ir); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&ir->work, cx88_ir_work, ir); #else INIT_WORK(&ir->work, cx88_ir_work); #endif - init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; schedule_work(&ir->work); } if (ir->sampling) { diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index cb642ca03..bd5ed6760 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -29,7 +29,9 @@ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) #include <linux/device.h> #endif +#include <linux/dma-mapping.h> #include <linux/interrupt.h> +#include <linux/dma-mapping.h> #include <asm/delay.h> #include "cx88.h" @@ -405,7 +407,8 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) if (debug || (status & mask & ~0xff)) cx88_print_irqbits(core->name, "irq mpeg ", - cx88_mpeg_irqs, status, mask); + cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs), + status, mask); /* risc op code error */ if (status & (1 << 16)) { @@ -491,7 +494,7 @@ int cx8802_init_common(struct cx8802_dev *dev) if (pci_enable_device(dev->pci)) return -EIO; pci_set_master(dev->pci); - if (!pci_dma_supported(dev->pci,0xffffffff)) { + if (!pci_dma_supported(dev->pci,DMA_32BIT_MASK)) { printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name); return -EIO; } @@ -669,7 +672,7 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board } /* Driver asked for hardware access. */ -int cx8802_request_acquire(struct cx8802_driver *drv) +static int cx8802_request_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; @@ -689,7 +692,7 @@ int cx8802_request_acquire(struct cx8802_driver *drv) } /* Driver asked to release hardware. */ -int cx8802_request_release(struct cx8802_driver *drv) +static int cx8802_request_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; diff --git a/linux/drivers/media/video/cx88/cx88-tvaudio.c b/linux/drivers/media/video/cx88/cx88-tvaudio.c index e65cf72af..f69b4752d 100644 --- a/linux/drivers/media/video/cx88/cx88-tvaudio.c +++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c @@ -48,14 +48,12 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/poll.h> -#include <linux/pci.h> #include <linux/signal.h> #include <linux/ioport.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/vmalloc.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/delay.h> #include "compat.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 2e6259ceb..612c8393f 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1,4 +1,3 @@ - /* * * device driver for Conexant 2388x based TV cards @@ -34,11 +33,13 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/interrupt.h> +#include <linux/dma-mapping.h> #include <linux/delay.h> #include "compat.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #include <linux/kthread.h> #endif +#include <linux/dma-mapping.h> #include <asm/div64.h> #include "cx88.h" @@ -1836,7 +1837,8 @@ static void cx8800_vid_irq(struct cx8800_dev *dev) cx_write(MO_VID_INTSTAT, status); if (irq_debug || (status & mask & ~0xff)) cx88_print_irqbits(core->name, "irq vid", - cx88_vid_irqs, status, mask); + cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs), + status, mask); /* risc op code error */ if (status & (1 << 16)) { @@ -2067,7 +2069,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev,0xffffffff)) { + if (!pci_dma_supported(pci_dev,DMA_32BIT_MASK)) { printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name); err = -EIO; goto fail_core; diff --git a/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c b/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c index 59802d9ee..dc97f4686 100644 --- a/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -117,10 +117,6 @@ static struct i2c_adapter vp3054_i2c_adap_template = { .id = I2C_HW_B_CX2388x, }; -static struct i2c_client vp3054_i2c_client_template = { - .name = "VP-3054", -}; - int vp3054_i2c_probe(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -139,8 +135,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) sizeof(vp3054_i2c->adap)); memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, sizeof(vp3054_i2c->algo)); - memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template, - sizeof(vp3054_i2c->client)); #ifdef I2C_CLASS_TV_DIGITAL vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL; @@ -154,7 +148,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) vp3054_i2c->algo.data = dev; i2c_set_adapdata(&vp3054_i2c->adap, dev); vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; - vp3054_i2c->client.adapter = &vp3054_i2c->adap; vp3054_bit_setscl(dev,1); vp3054_bit_setsda(dev,1); diff --git a/linux/drivers/media/video/cx88/cx88-vp3054-i2c.h b/linux/drivers/media/video/cx88/cx88-vp3054-i2c.h index b7a0a04d2..be99c931d 100644 --- a/linux/drivers/media/video/cx88/cx88-vp3054-i2c.h +++ b/linux/drivers/media/video/cx88/cx88-vp3054-i2c.h @@ -26,10 +26,16 @@ struct vp3054_i2c_state { struct i2c_adapter adap; struct i2c_algo_bit_data algo; - struct i2c_client client; u32 state; }; /* ----------------------------------------------------------------------- */ +#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) int vp3054_i2c_probe(struct cx8802_dev *dev); void vp3054_i2c_remove(struct cx8802_dev *dev); +#else +static inline int vp3054_i2c_probe(struct cx8802_dev *dev) +{ return 0; } +static inline void vp3054_i2c_remove(struct cx8802_dev *dev) +{ } +#endif diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 4719046e1..144c40410 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -212,6 +212,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_NORWOOD_MICRO 54 #define CX88_BOARD_TE_DTV_250_OEM_SWANN 55 #define CX88_BOARD_HAUPPAUGE_HVR1300 56 +#define CX88_BOARD_ADSTECH_PTV_390 57 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -322,8 +323,6 @@ struct cx88_core { /* config info -- dvb */ #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) - struct dvb_pll_desc *pll_desc; - unsigned int pll_addr; int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); #endif @@ -545,7 +544,7 @@ struct cx8802_dev { /* cx88-core.c */ extern void cx88_print_irqbits(char *name, char *tag, char **strings, - u32 bits, u32 mask); + int len, u32 bits, u32 mask); extern int cx88_core_irq(struct cx88_core *core, u32 status); extern void cx88_wakeup(struct cx88_core *core, diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c index 692dbd93c..8d034ca2b 100644 --- a/linux/drivers/media/video/dabusb.c +++ b/linux/drivers/media/video/dabusb.c @@ -37,7 +37,6 @@ #include <asm/atomic.h> #include <linux/delay.h> #include <linux/usb.h> -#include <linux/smp_lock.h> #include "compat.h" #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) #include <linux/mutex.h> diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig index 9285a58e4..5b6a40371 100644 --- a/linux/drivers/media/video/em28xx/Kconfig +++ b/linux/drivers/media/video/em28xx/Kconfig @@ -1,7 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_V4L1 && USB && I2C - select VIDEO_BUF + depends on VIDEO_V4L1 && I2C select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 48240b3ec..9809463b6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/module.h> -#include <linux/pci.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/usb.h> diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 4ee4cea10..f9a8002d3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -70,7 +70,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); if (ret != 2 + len) { - em28xx_warn("writting to i2c device failed (error=%i)\n", ret); + em28xx_warn("writing to i2c device failed (error=%i)\n", ret); return -EIO; } for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; @@ -544,7 +544,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) unsigned char buf; int i, rc; - for (i = 0; i < 128; i++) { + for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { c->addr = i; rc = i2c_master_recv(c, &buf, 0); if (rc < 0) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 3f2ad0677..566ef6994 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1833,7 +1833,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, endpoint = &interface->cur_altsetting->endpoint[1].desc; - /* check if the the device has the iso in endpoint at the correct place */ + /* check if the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); diff --git a/linux/drivers/media/video/et61x251/Kconfig b/linux/drivers/media/video/et61x251/Kconfig index c6bff7056..664676f44 100644 --- a/linux/drivers/media/video/et61x251/Kconfig +++ b/linux/drivers/media/video/et61x251/Kconfig @@ -1,6 +1,6 @@ config USB_ET61X251 tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on Etoms ET61X151 or ET61X251 PC Camera Controllers. diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index d20bad700..3333d0832 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -174,7 +174,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, return -EIO; } - for (start = 0; start<4; start++) { + for (start = 0; start < ARRAY_SIZE(b); start++) { if (b[start] == marker) { code=b[(start+parity_offset+1)%4]; parity=b[(start+parity_offset)%4]; @@ -279,8 +279,9 @@ static void ir_work(struct work_struct *work) #else struct IR_i2c *ir = container_of(work, struct IR_i2c, work); #endif + ir_key_poll(ir); - mod_timer(&ir->timer, jiffies+HZ/10); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); } /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/ivtv/Kconfig b/linux/drivers/media/video/ivtv/Kconfig index e854f3f1b..1aaeaa02f 100644 --- a/linux/drivers/media/video/ivtv/Kconfig +++ b/linux/drivers/media/video/ivtv/Kconfig @@ -1,6 +1,6 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" - depends on VIDEO_V4L1 && VIDEO_V4L2 && USB && I2C && EXPERIMENTAL + depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 4031df6db..b0c11d90e 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -74,7 +74,7 @@ int ivtv_first_minor = 0; struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; /* Protects ivtv_cards_active */ -spinlock_t ivtv_cards_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(ivtv_cards_lock); /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { @@ -339,6 +339,7 @@ static void ivtv_process_eeprom(struct ivtv *itv) /* In a few cases the PCI subsystem IDs do not correctly identify the card. A better method is to check the model number from the eeprom instead. */ + case 30012 ... 30039: /* Low profile PVR250 */ case 32000 ... 32999: case 48000 ... 48099: /* 48??? range are PVR250s with a cx23415 */ case 48400 ... 48599: @@ -656,6 +657,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->dma_timer.data = (unsigned long)itv; itv->cur_dma_stream = -1; + itv->cur_pio_stream = -1; itv->audio_stereo_mode = AUDIO_STEREO; itv->audio_bilingual_mode = AUDIO_MONO_LEFT; diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.h b/linux/drivers/media/video/ivtv/ivtv-driver.h index 39e1d7e46..7b162e415 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.h +++ b/linux/drivers/media/video/ivtv/ivtv-driver.h @@ -70,14 +70,6 @@ #include <media/ivtv.h> -#ifdef CONFIG_LIRC_I2C -# error "This driver is not compatible with the LIRC I2C kernel configuration option." -#endif /* CONFIG_LIRC_I2C */ - -#ifndef CONFIG_PCI -# error "This driver requires kernel PCI support." -#endif /* CONFIG_PCI */ - #define IVTV_ENCODER_OFFSET 0x00000000 #define IVTV_ENCODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */ @@ -248,6 +240,7 @@ extern const u32 yuv_offset[4]; #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) +#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25) #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) @@ -258,7 +251,8 @@ extern const u32 yuv_offset[4]; #define IVTV_IRQ_DEC_VSYNC (0x1 << 10) /* IRQ Masks */ -#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ) +#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\ + IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE) #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) @@ -385,6 +379,9 @@ struct ivtv_mailbox_data { #define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ +#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */ +#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */ + /* per-ivtv, i_flags */ #define IVTV_F_I_DMA 0 /* DMA in progress */ #define IVTV_F_I_UDMA 1 /* UDMA in progress */ @@ -401,8 +398,11 @@ struct ivtv_mailbox_data { #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ -#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */ -#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */ +#define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */ +#define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */ +#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ +#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ +#define IVTV_F_I_PIO 19 /* PIO in progress */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ @@ -499,6 +499,7 @@ struct ivtv_stream { /* Base Dev SG Array for cx23415/6 */ struct ivtv_SG_element *SGarray; + struct ivtv_SG_element *PIOarray; dma_addr_t SG_handle; int SG_length; @@ -721,6 +722,7 @@ struct ivtv { atomic_t decoding; /* count number of active decoding streams */ u32 irq_rr_idx; /* Round-robin stream index */ int cur_dma_stream; /* index of stream doing DMA */ + int cur_pio_stream; /* index of stream doing PIO */ u32 dma_data_req_offset; u32 dma_data_req_size; int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */ diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index 1637097dd..555d5e636 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -32,6 +32,8 @@ #include "ivtv-yuv.h" #include "ivtv-controls.h" #include "ivtv-ioctl.h" +#include "ivtv-cards.h" +#include <media/saa7115.h> /* This function tries to claim the stream for a specific file descriptor. If no one else is using this stream then the stream is claimed and @@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); /* Select correct audio input (i.e. TV tuner or Line in) */ ivtv_audio_set_io(itv); + if (itv->hw_flags & IVTV_HW_SAA711X) + { + struct v4l2_crystal_freq crystal_freq; + crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; + crystal_freq.flags = 0; + ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + } /* Done! Unmute and continue. */ ivtv_unmute(itv); ivtv_release_stream(s); @@ -804,7 +813,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) struct ivtv_open_id *item; struct ivtv *itv = NULL; struct ivtv_stream *s = NULL; - int minor = MINOR(inode->i_rdev); + int minor = iminor(inode); /* Find which card this open was on */ spin_lock(&ivtv_cards_lock); @@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); /* Select the correct audio input (i.e. radio tuner) */ ivtv_audio_set_io(itv); + if (itv->hw_flags & IVTV_HW_SAA711X) + { + struct v4l2_crystal_freq crystal_freq; + crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; + crystal_freq.flags = SAA7115_FREQ_FL_APLL; + ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + } /* Done! Unmute and continue. */ ivtv_unmute(itv); } diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index d6f0b0235..5b799f016 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -289,7 +289,7 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, } case VIDEO_CMD_STOP: - vc->flags &= ~(VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK); + vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) vc->stop.pts = 0; if (try) break; @@ -302,7 +302,7 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); case VIDEO_CMD_FREEZE: - vc->flags &= ~VIDEO_CMD_FREEZE_TO_BLACK; + vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; if (try) break; if (itv->output_mode != OUT_MPG) return -EBUSY; @@ -362,8 +362,12 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; +#if 0 + /* Temporarily removed until a better solution is in place that does not + break the ABI */ fmt->fmt.pix.left = itv->main_rect.left; fmt->fmt.pix.top = itv->main_rect.top; +#endif fmt->fmt.pix.width = itv->main_rect.width; fmt->fmt.pix.height = itv->main_rect.height; fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; @@ -402,8 +406,12 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm break; case V4L2_BUF_TYPE_VIDEO_CAPTURE: +#if 0 + /* Temporarily removed until a better solution is in place that does not + break the ABI */ fmt->fmt.pix.left = 0; fmt->fmt.pix.top = 0; +#endif fmt->fmt.pix.width = itv->params.width; fmt->fmt.pix.height = itv->params.height; fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; @@ -498,15 +506,26 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; field = fmt->fmt.pix.field; +#if 0 + /* Temporarily removed until a better solution is in place that does not + break the ABI */ r.top = fmt->fmt.pix.top; r.left = fmt->fmt.pix.left; +#else + r.top = 0; + r.left = 0; +#endif r.width = fmt->fmt.pix.width; r.height = fmt->fmt.pix.height; ivtv_get_fmt(itv, streamtype, fmt); if (itv->output_mode != OUT_UDMA_YUV) { /* TODO: would setting the rect also be valid for this mode? */ +#if 0 + /* Temporarily removed until a better solution is in place that does not + break the ABI */ fmt->fmt.pix.top = r.top; fmt->fmt.pix.left = r.left; +#endif fmt->fmt.pix.width = r.width; fmt->fmt.pix.height = r.height; } @@ -1107,7 +1126,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void return ivtv_start_capture(id); case V4L2_ENC_CMD_STOP: - enc->flags &= ~V4L2_ENC_CMD_STOP_AT_GOP_END; + enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; if (try) return 0; ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); @@ -1153,8 +1172,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void fb->fmt.pixelformat = itv->osd_pixelformat; fb->fmt.width = itv->osd_rect.width; fb->fmt.height = itv->osd_rect.height; +#if 0 + /* Temporarily removed until a better solution is in place that does not + break the ABI */ fb->fmt.left = itv->osd_rect.left; fb->fmt.top = itv->osd_rect.top; +#endif fb->base = (void *)itv->osd_video_pbase; if (itv->osd_global_alpha_state) fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c index e87a4dc37..4825d1749 100644 --- a/linux/drivers/media/video/ivtv/ivtv-irq.c +++ b/linux/drivers/media/video/ivtv/ivtv-irq.c @@ -31,8 +31,6 @@ #define DMA_MAGIC_COOKIE 0x000001fe -#define SLICED_VBI_PIO 1 - static void ivtv_dma_dec_start(struct ivtv_stream *s); static const int ivtv_stream_map[] = { @@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = { IVTV_ENC_STREAM_TYPE_VBI, }; -static inline int ivtv_use_pio(struct ivtv_stream *s) + +static void ivtv_pio_work_handler(struct ivtv *itv) { - struct ivtv *itv = s->itv; + struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream]; + struct ivtv_buffer *buf; + struct list_head *p; + int i = 0; + + IVTV_DEBUG_DMA("ivtv_pio_work_handler\n"); + if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || + s->v4l2dev == NULL || !ivtv_use_pio(s)) { + itv->cur_pio_stream = -1; + /* trigger PIO complete user interrupt */ + write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); + return; + } + IVTV_DEBUG_DMA("Process PIO %s\n", s->name); + buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list); + list_for_each(p, &s->q_dma.list) { + struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); + u32 size = s->PIOarray[i].size & 0x3ffff; - return s->dma == PCI_DMA_NONE || - (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); + /* Copy the data from the card to the buffer */ + if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { + memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size); + } + else { + memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size); + } + if (s->PIOarray[i].size & 0x80000000) + break; + i++; + } + write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) @@ -62,8 +88,11 @@ void ivtv_irq_work_handler(void *arg) DEFINE_WAIT(wait); + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags)) + ivtv_pio_work_handler(itv); + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags)) - vbi_work_handler(itv); + ivtv_vbi_work_handler(itv); if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) ivtv_yuv_work_handler(itv); @@ -179,8 +208,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA } s->buffers_stolen = rc; - /* got the buffers, now fill in SGarray (DMA) or copy the data from the card - to the buffers (PIO). */ + /* got the buffers, now fill in SGarray (DMA) */ buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); memset(buf->buf, 0, 128); list_for_each(p, &s->q_predma.list) { @@ -188,21 +216,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA if (skip_bufs-- > 0) continue; - if (!ivtv_use_pio(s)) { - s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); - s->SGarray[idx].src = cpu_to_le32(offset); - s->SGarray[idx].size = cpu_to_le32(s->buf_size); - } + s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); + s->SGarray[idx].src = cpu_to_le32(offset); + s->SGarray[idx].size = cpu_to_le32(s->buf_size); buf->bytesused = (size < s->buf_size) ? size : s->buf_size; - /* If PIO, then copy the data from the card to the buffer */ - if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { - memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused); - } - else if (ivtv_use_pio(s)) { - memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused); - } - s->q_predma.bytesused += buf->bytesused; size -= buf->bytesused; offset += s->buf_size; @@ -230,11 +248,6 @@ static void dma_post(struct ivtv_stream *s) u32 *u32buf; int x = 0; - if (ivtv_use_pio(s)) { - if (s->q_predma.bytesused) - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - s->SG_length = 0; - } IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", s->name, s->dma_offset); list_for_each(p, &s->q_dma.list) { @@ -284,10 +297,14 @@ static void dma_post(struct ivtv_stream *s) if (buf) buf->bytesused += s->dma_last_offset; if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { - /* Parse and Groom VBI Data */ - s->q_dma.bytesused -= buf->bytesused; - ivtv_process_vbi_data(itv, buf, 0, s->type); - s->q_dma.bytesused += buf->bytesused; + list_for_each(p, &s->q_dma.list) { + buf = list_entry(p, struct ivtv_buffer, list); + + /* Parse and Groom VBI Data */ + s->q_dma.bytesused -= buf->bytesused; + ivtv_process_vbi_data(itv, buf, 0, s->type); + s->q_dma.bytesused += buf->bytesused; + } if (s->id == -1) { ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); return; @@ -357,10 +374,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; int i; + IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name); + if (s->q_predma.bytesused) ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - IVTV_DEBUG_DMA("start DMA for %s\n", s->name); - s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); + + if (ivtv_use_dma(s)) + s->SGarray[s->SG_length - 1].size = + cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); /* If this is an MPEG stream, and VBI data is also pending, then append the VBI DMA to the MPEG DMA and transfer both sets of data at once. @@ -374,7 +395,8 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length && s->SG_length + s_vbi->SG_length <= s->buffers) { ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); - s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); + if (ivtv_use_dma(s_vbi)) + s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); for (i = 0; i < s_vbi->SG_length; i++) { s->SGarray[s->SG_length++] = s_vbi->SGarray[i]; } @@ -387,14 +409,26 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) /* Mark last buffer size for Interrupt flag */ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); - /* Sync Hardware SG List of buffers */ - ivtv_stream_sync_for_device(s); - write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); - write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); - set_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + HZ / 10; - add_timer(&itv->dma_timer); + if (ivtv_use_pio(s)) { + for (i = 0; i < s->SG_length; i++) { + s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src); + s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size); + } + set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags); + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); + set_bit(IVTV_F_I_PIO, &itv->i_flags); + itv->cur_pio_stream = s->type; + } + else { + /* Sync Hardware SG List of buffers */ + ivtv_stream_sync_for_device(s); + write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); + write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); + set_bit(IVTV_F_I_DMA, &itv->i_flags); + itv->cur_dma_stream = s->type; + itv->dma_timer.expires = jiffies + HZ / 10; + add_timer(&itv->dma_timer); + } } static void ivtv_dma_dec_start(struct ivtv_stream *s) @@ -495,6 +529,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) wake_up(&itv->dma_waitq); } +static void ivtv_irq_enc_pio_complete(struct ivtv *itv) +{ + struct ivtv_stream *s; + + if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) { + itv->cur_pio_stream = -1; + return; + } + s = &itv->streams[itv->cur_pio_stream]; + IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name); + s->SG_length = 0; + clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + clear_bit(IVTV_F_I_PIO, &itv->i_flags); + itv->cur_pio_stream = -1; + dma_post(s); + if (s->type == IVTV_ENC_STREAM_TYPE_MPG) + ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0); + else if (s->type == IVTV_ENC_STREAM_TYPE_YUV) + ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1); + else if (s->type == IVTV_ENC_STREAM_TYPE_PCM) + ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2); + clear_bit(IVTV_F_I_PIO, &itv->i_flags); + if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { + u32 tmp; + + s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; + tmp = s->dma_offset; + s->dma_offset = itv->vbi.dma_offset; + dma_post(s); + s->dma_offset = tmp; + } + wake_up(&itv->dma_waitq); +} + static void ivtv_irq_dma_err(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; @@ -538,13 +606,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); s = &itv->streams[ivtv_stream_map[data[0]]]; if (!stream_enc_dma_append(s, data)) { - if (ivtv_use_pio(s)) { - dma_post(s); - ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]); - } - else { - set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); - } + set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } @@ -557,15 +619,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) IVTV_DEBUG_IRQ("ENC START VBI CAP\n"); s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - if (ivtv_use_pio(s)) { - if (stream_enc_dma_append(s, data)) - return; - if (s->q_predma.bytesused) - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - s->SG_length = 0; - dma_post(s); - return; - } /* If more than two VBI buffers are pending, then clear the old ones and start with this new one. This can happen during transition stages when MPEG capturing is @@ -588,11 +641,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) if (!stream_enc_dma_append(s, data) && !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); - set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); + set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } -static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) +static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; @@ -600,7 +653,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) IVTV_DEBUG_IRQ("DEC VBI REINSERT\n"); if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && !stream_enc_dma_append(s, data)) { - dma_post(s); + set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags); } } @@ -663,7 +716,6 @@ static void ivtv_irq_vsync(struct ivtv *itv) } if (frame != (itv->lastVsyncFrame & 1)) { struct ivtv_stream *s = ivtv_get_output_stream(itv); - int work = 0; itv->lastVsyncFrame += 1; if (frame == 0) { @@ -684,7 +736,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) /* Send VBI to saa7127 */ if (frame) { set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); - work = 1; + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); } /* Check if we need to update the yuv registers */ @@ -697,11 +749,9 @@ static void ivtv_irq_vsync(struct ivtv *itv) itv->yuv_info.new_frame_info[last_dma_frame].update = 0; itv->yuv_info.yuv_forced_update = 0; set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); - work = 1; + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); } } - if (work) - queue_work(itv->irq_work_queues, &itv->irq_work_queue); } } @@ -765,6 +815,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) ivtv_irq_enc_dma_complete(itv); } + if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) { + ivtv_irq_enc_pio_complete(itv); + } + if (combo & IVTV_IRQ_DMA_ERR) { ivtv_irq_dma_err(itv); } @@ -778,7 +832,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) } if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { - ivtv_irq_dev_vbi_reinsert(itv); + ivtv_irq_dec_vbi_reinsert(itv); } if (combo & IVTV_IRQ_ENC_EOS) { @@ -823,6 +877,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) } } + if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { + for (i = 0; i < IVTV_MAX_STREAMS; i++) { + int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS; + struct ivtv_stream *s = &itv->streams[idx]; + + if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags)) + continue; + if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG) + ivtv_dma_enc_start(s); + break; + } + } + + if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) + queue_work(itv->irq_work_queues, &itv->irq_work_queue); + spin_unlock(&itv->dma_reg_lock); /* If we've just handled a 'forced' vsync, it's safest to say it diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.c b/linux/drivers/media/video/ivtv/ivtv-queue.c index ccfcef1ad..a04f9387f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-queue.c +++ b/linux/drivers/media/video/ivtv/ivtv-queue.c @@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s) s->dma != PCI_DMA_NONE ? "DMA " : "", s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); - /* Allocate DMA SG Arrays */ - if (s->dma != PCI_DMA_NONE) { - s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); - if (s->SGarray == NULL) { - IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); + if (ivtv_might_use_pio(s)) { + s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); + if (s->PIOarray == NULL) { + IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name); return -ENOMEM; } - s->SG_length = 0; + } + + /* Allocate DMA SG Arrays */ + s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); + if (s->SGarray == NULL) { + IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); + if (ivtv_might_use_pio(s)) { + kfree(s->PIOarray); + s->PIOarray = NULL; + } + return -ENOMEM; + } + s->SG_length = 0; + if (ivtv_might_use_dma(s)) { s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma); ivtv_stream_sync_for_cpu(s); } @@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) break; } INIT_LIST_HEAD(&buf->list); - if (s->dma != PCI_DMA_NONE) { + if (ivtv_might_use_dma(s)) { buf->dma_handle = pci_map_single(s->itv->dev, buf->buf, s->buf_size + 256, s->dma); ivtv_buf_sync_for_cpu(s, buf); @@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s) /* empty q_free */ while ((buf = ivtv_dequeue(s, &s->q_free))) { - if (s->dma != PCI_DMA_NONE) + if (ivtv_might_use_dma(s)) pci_unmap_single(s->itv->dev, buf->dma_handle, s->buf_size + 256, s->dma); kfree(buf->buf); @@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s) sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); s->SG_handle = IVTV_DMA_UNMAPPED; } + kfree(s->SGarray); + kfree(s->PIOarray); + s->PIOarray = NULL; s->SGarray = NULL; s->SG_length = 0; } diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.h b/linux/drivers/media/video/ivtv/ivtv-queue.h index 903edd4b4..2ed8d5482 100644 --- a/linux/drivers/media/video/ivtv/ivtv-queue.h +++ b/linux/drivers/media/video/ivtv/ivtv-queue.h @@ -20,18 +20,43 @@ */ #define IVTV_DMA_UNMAPPED ((u32) -1) +#define SLICED_VBI_PIO 1 /* ivtv_buffer utility functions */ + +static inline int ivtv_might_use_pio(struct ivtv_stream *s) +{ + return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI); +} + +static inline int ivtv_use_pio(struct ivtv_stream *s) +{ + struct ivtv *itv = s->itv; + + return s->dma == PCI_DMA_NONE || + (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); +} + +static inline int ivtv_might_use_dma(struct ivtv_stream *s) +{ + return s->dma != PCI_DMA_NONE; +} + +static inline int ivtv_use_dma(struct ivtv_stream *s) +{ + return !ivtv_use_pio(s); +} + static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) { - if (s->dma != PCI_DMA_NONE) + if (ivtv_use_dma(s)) pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, s->buf_size + 256, s->dma); } static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) { - if (s->dma != PCI_DMA_NONE) + if (ivtv_use_dma(s)) pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, s->buf_size + 256, s->dma); } @@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s); static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) { - pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, - sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); + if (ivtv_use_dma(s)) + pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, + sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); } static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) { - pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, - sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); + if (ivtv_use_dma(s)) + pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, + sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); } diff --git a/linux/drivers/media/video/ivtv/ivtv-vbi.c b/linux/drivers/media/video/ivtv/ivtv-vbi.c index 5efa5a867..3ba46e07e 100644 --- a/linux/drivers/media/video/ivtv/ivtv-vbi.c +++ b/linux/drivers/media/video/ivtv/ivtv-vbi.c @@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv) } -void vbi_work_handler(struct ivtv *itv) +void ivtv_vbi_work_handler(struct ivtv *itv) { struct v4l2_sliced_vbi_data data; diff --git a/linux/drivers/media/video/ivtv/ivtv-vbi.h b/linux/drivers/media/video/ivtv/ivtv-vbi.h index cdaea697b..ec211b497 100644 --- a/linux/drivers/media/video/ivtv/ivtv-vbi.h +++ b/linux/drivers/media/video/ivtv/ivtv-vbi.h @@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, int ivtv_used_line(struct ivtv *itv, int line, int field); void ivtv_disable_vbi(struct ivtv *itv); void ivtv_set_vbi(unsigned long arg); -void vbi_work_handler(struct ivtv *itv); +void ivtv_vbi_work_handler(struct ivtv *itv); diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 6499c7831..9ba068a7d 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -930,13 +930,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV) return -EINVAL; mutex_lock(&meye.lock); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, p->brightness >> 10); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, p->hue >> 10); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, p->colour >> 10); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, p->contrast >> 10); meye.picture = *p; mutex_unlock(&meye.lock); @@ -1048,11 +1048,11 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.quality != jp->quality) mchip_hic_stop(); /* need restart */ meye.params = *jp; - sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, meye.params.sharpness); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, meye.params.agc); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, meye.params.picture); mutex_unlock(&meye.lock); break; @@ -1292,38 +1292,38 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, mutex_lock(&meye.lock); switch (c->id) { case V4L2_CID_BRIGHTNESS: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERABRIGHTNESS, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); meye.picture.brightness = c->value << 10; break; case V4L2_CID_HUE: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERAHUE, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERAHUE, c->value); meye.picture.hue = c->value << 10; break; case V4L2_CID_CONTRAST: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERACONTRAST, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); meye.picture.contrast = c->value << 10; break; case V4L2_CID_SATURATION: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERACOLOR, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); meye.picture.colour = c->value << 10; break; case V4L2_CID_AGC: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERAAGC, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERAAGC, c->value); meye.params.agc = c->value; break; case V4L2_CID_SHARPNESS: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERASHARPNESS, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value); meye.params.sharpness = c->value; break; case V4L2_CID_PICTURE: - sonypi_camera_command( - SONYPI_COMMAND_SETCAMERAPICTURE, c->value); + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value); meye.params.picture = c->value; break; case V4L2_CID_JPEGQUAL: @@ -1853,7 +1853,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); meye.video_dev->dev = &meye.mchip_dev->dev; - if ((ret = sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1))) { + if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) { printk(KERN_ERR "meye: unable to power on the camera\n"); printk(KERN_ERR "meye: did you enable the camera in " "sonypi using the module options ?\n"); @@ -1933,13 +1933,13 @@ static int __devinit meye_probe(struct pci_dev *pcidev, meye.params.picture = 0; meye.params.framerate = 0; - sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 32); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 32); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 32); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, 32); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS, 32); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, 0); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", MEYE_DRIVER_VERSION); @@ -1958,7 +1958,7 @@ outremap: outregions: pci_disable_device(meye.mchip_dev); outenabledev: - sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); outsonypienable: kfifo_free(meye.doneq); outkfifoalloc2: @@ -1991,7 +1991,7 @@ static void __devexit meye_remove(struct pci_dev *pcidev) pci_disable_device(meye.mchip_dev); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); kfifo_free(meye.doneq); kfifo_free(meye.grabq); diff --git a/linux/drivers/media/video/meye.h b/linux/drivers/media/video/meye.h index d6306af94..fdba6226e 100644 --- a/linux/drivers/media/video/meye.h +++ b/linux/drivers/media/video/meye.h @@ -255,7 +255,11 @@ /****************************************************************************/ /* Sony Programmable I/O Controller for accessing the camera commands */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) +#include <linux/sony-laptop.h> +#else #include <linux/sonypi.h> +#endif /* private API definitions */ #include <linux/meye.h> diff --git a/linux/drivers/media/video/ov511.h b/linux/drivers/media/video/ov511.h index 1749665fc..2fb0d992c 100644 --- a/linux/drivers/media/video/ov511.h +++ b/linux/drivers/media/video/ov511.h @@ -5,7 +5,6 @@ #include "compat.h" #include <linux/videodev.h> #include <media/v4l2-common.h> -#include <linux/smp_lock.h> #include <linux/usb.h> #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) #include <linux/mutex.h> diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index b033bf334..dcba098aa 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -5,6 +5,8 @@ * by Jonathan Corbet with substantial inspiration from Mark * McClelland's ovcamchip code. * + * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> + * * This file may be distributed under the terms of the GNU General * Public License, version 2. */ @@ -164,6 +166,10 @@ MODULE_LICENSE("GPL"); #define REG_GFIX 0x69 /* Fix gain control */ +#define REG_REG76 0x76 /* OV's name */ +#define R76_BLKPCOR 0x80 /* Black pixel correction enable */ +#define R76_WHTPCOR 0x40 /* White pixel correction enable */ + #define REG_RGB444 0x8c /* RGB 444 control */ #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ #define R444_RGBX 0x01 /* Empty nibble at end */ @@ -257,7 +263,7 @@ static struct regval_list ov7670_default_regs[] = { /* Almost all of these are magic "reserved" values. */ { REG_COM5, 0x61 }, { REG_COM6, 0x4b }, - { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR }, + { 0x16, 0x02 }, { REG_MVFP, 0x07 }, { 0x21, 0x02 }, { 0x22, 0x91 }, { 0x29, 0x07 }, { 0x33, 0x0b }, { 0x35, 0x0b }, { 0x37, 0x1d }, @@ -382,6 +388,13 @@ static struct regval_list ov7670_fmt_rgb444[] = { { 0xff, 0xff }, }; +static struct regval_list ov7670_fmt_raw[] = { + { REG_COM7, COM7_BAYER }, + { REG_COM13, 0x08 }, /* No gamma, magic rsvd bit */ + { REG_COM16, 0x3d }, /* Edge enhancement, denoise */ + { REG_REG76, 0xe1 }, /* Pix correction, magic rsvd */ + { 0xff, 0xff }, +}; @@ -506,32 +519,39 @@ static struct ov7670_format_struct { __u32 pixelformat; struct regval_list *regs; int cmatrix[CMATRIX_LEN]; + int bpp; /* Bytes per pixel */ } ov7670_formats[] = { { .desc = "YUYV 4:2:2", .pixelformat = V4L2_PIX_FMT_YUYV, .regs = ov7670_fmt_yuv422, .cmatrix = { 128, -128, 0, -34, -94, 128 }, + .bpp = 2, }, { .desc = "RGB 444", .pixelformat = V4L2_PIX_FMT_RGB444, .regs = ov7670_fmt_rgb444, .cmatrix = { 179, -179, 0, -61, -176, 228 }, + .bpp = 2, }, { .desc = "RGB 565", .pixelformat = V4L2_PIX_FMT_RGB565, .regs = ov7670_fmt_rgb565, .cmatrix = { 179, -179, 0, -61, -176, 228 }, + .bpp = 2, + }, + { + .desc = "Raw RGB Bayer", + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .regs = ov7670_fmt_raw, + .cmatrix = { 0, 0, 0, 0, 0, 0 }, + .bpp = 1 }, }; -#define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0])) +#define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats) -/* - * All formats we support are 2 bytes/pixel. - */ -#define BYTES_PER_PIXEL 2 /* * Then there is the issue of window sizes. Try to capture the info here. @@ -708,7 +728,7 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, */ pix->width = wsize->width; pix->height = wsize->height; - pix->bytesperline = pix->width*BYTES_PER_PIXEL; + pix->bytesperline = pix->width*ov7670_formats[index].bpp; pix->sizeimage = pix->height*pix->bytesperline; return 0; } @@ -722,12 +742,22 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; struct ov7670_info *info = i2c_get_clientdata(c); - unsigned char com7; + unsigned char com7, clkrc; ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); if (ret) return ret; /* + * HACK: if we're running rgb565 we need to grab then rewrite + * CLKRC. If we're *not*, however, then rewriting clkrc hoses + * the colors. + */ + if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { + ret = ov7670_read(c, REG_CLKRC, &clkrc); + if (ret) + return ret; + } + /* * COM7 is a pain in the ass, it doesn't like to be read then * quickly written afterward. But we have everything we need * to set it absolutely here, as long as the format-specific @@ -746,7 +776,10 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) if (wsize->regs) ret = ov7670_write_array(c, wsize->regs); info->fmt = ovfmt; - return 0; + + if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) + ret = ov7670_write(c, REG_CLKRC, clkrc); + return ret; } /* @@ -1291,7 +1324,9 @@ static int ov7670_attach(struct i2c_adapter *adapter) ret = ov7670_detect(client); if (ret) goto out_free_info; - i2c_attach_client(client); + ret = i2c_attach_client(client); + if (ret) + goto out_free_info; return 0; out_free_info: diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h b/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h index 1231335a9..50c7763d4 100644 --- a/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -15,6 +15,7 @@ #ifndef __LINUX_OVCAMCHIP_PRIV_H #define __LINUX_OVCAMCHIP_PRIV_H +#include <linux/i2c.h> #include <media/ovcamchip.h> #ifdef DEBUG diff --git a/linux/drivers/media/video/planb.c b/linux/drivers/media/video/planb.c index c393b26e1..b399806af 100644 --- a/linux/drivers/media/video/planb.c +++ b/linux/drivers/media/video/planb.c @@ -2169,7 +2169,7 @@ static int find_planb(void) if (!machine_is(powermac)) return 0; - planb_devices = find_devices("planb"); + planb_devices = of_find_node_by_name(NULL, "planb"); if (planb_devices == 0) { planb_num=0; printk(KERN_WARNING "PlanB: no device found!\n"); @@ -2184,12 +2184,14 @@ static int find_planb(void) if (planb_devices->n_addrs != 1) { printk (KERN_WARNING "PlanB: expecting 1 address for planb " "(got %d)", planb_devices->n_addrs); + of_node_put(planb_devices); return 0; } if (planb_devices->n_intrs == 0) { printk(KERN_WARNING "PlanB: no intrs for device %s\n", planb_devices->full_name); + of_node_put(planb_devices); return 0; } else { irq = planb_devices->intrs[0].line; @@ -2211,12 +2213,13 @@ static int find_planb(void) confreg = planb_devices->addrs[0].space & 0xff; old_base = planb_devices->addrs[0].address; new_base = 0xf1000000; + of_node_put(planb_devices); DEBUG("PlanB: Found on bus %d, dev %d, func %d, " "membase 0x%x (base reg. 0x%x)\n", bus, PCI_SLOT(dev_fn), PCI_FUNC(dev_fn), old_base, confreg); - pdev = pci_find_slot (bus, dev_fn); + pdev = pci_get_bus_and_slot(bus, dev_fn); if (!pdev) { printk(KERN_ERR "planb: cannot find slot\n"); goto err_out; @@ -2246,6 +2249,7 @@ static int find_planb(void) pb->planb_base = planb_regs; pb->planb_base_phys = (struct planb_registers *)new_base; pb->irq = irq; + pb->dev = pdev; return planb_num; @@ -2253,6 +2257,7 @@ err_out_disable: pci_disable_device(pdev); err_out: /* FIXME handle error */ /* comment moved from pci_find_slot, above */ + pci_dev_put(pdev); return 0; } @@ -2280,6 +2285,8 @@ static void release_planb(void) printk(KERN_INFO "PlanB: unregistering with v4l\n"); video_unregister_device(&pb->video_dev); + pci_dev_put(pb->dev); + /* note that iounmap() does nothing on the PPC right now */ iounmap ((void *)pb->planb_base); } diff --git a/linux/drivers/media/video/planb.h b/linux/drivers/media/video/planb.h index 92823211d..e21b5735c 100644 --- a/linux/drivers/media/video/planb.h +++ b/linux/drivers/media/video/planb.h @@ -177,6 +177,7 @@ struct planb { struct mutex lock; unsigned int irq; /* interrupt number */ volatile unsigned int intr_mask; + struct pci_dev *dev; /* Our PCI device */ int overlay; /* overlay running? */ struct planb_window win; diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 5645c9318..d0c2cd785 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" - depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c index a7424f847..4abee970c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -424,22 +424,29 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) int pvr2_encoder_configure(struct pvr2_hdw *hdw) { int ret; + int val; pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure" " (cx2341x module)"); hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING; hdw->enc_ctl_state.width = hdw->res_hor_val; hdw->enc_ctl_state.height = hdw->res_ver_val; - hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & - (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ? + hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ? 0 : 1); ret = 0; ret |= pvr2_encoder_prep_config(hdw); + /* saa7115: 0xf0 */ + val = 0xf0; + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + /* ivtv cx25840: 0x140 */ + val = 0x140; + } + if (!ret) ret = pvr2_encoder_vcmd( hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - 0xf0, 0xf0); + val, val); /* setup firmware to notify us about some events (don't know why...) */ if (!ret) ret = pvr2_encoder_vcmd( diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index db0b02f0f..e8ee1bf73 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -299,6 +299,8 @@ struct pvr2_hdw { int unit_number; /* ID for driver instance */ unsigned long serial_number; /* ID for hardware itself */ + char bus_info[32]; /* Bus location info */ + /* Minor numbers used by v4l logic (yes, this is a hack, as there should be no v4l junk here). Probably a better way to do this. */ int v4l_minor_number_video; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index d1de5cd59..52078f4d0 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -84,7 +84,7 @@ static struct pvr2_string_table pvr2_client_lists[] = { }; static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; -static DECLARE_MUTEX(pvr2_unit_sem); +static DEFINE_MUTEX(pvr2_unit_mtx); static int ctlchg = 0; static int initusbreset = 1; @@ -1009,6 +1009,13 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw) return hdw->serial_number; } + +const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *hdw) +{ + return hdw->bus_info; +} + + unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) { return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio; @@ -1258,10 +1265,10 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_FWPOST1; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); hdw->cmd_buffer[0] = FX2CMD_MEMSEL; hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); if (ret) { @@ -1330,7 +1337,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_MEMSEL; hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); if (ret) { @@ -2096,14 +2103,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; - down(&pvr2_unit_sem); do { + mutex_lock(&pvr2_unit_mtx); do { for (idx = 0; idx < PVR_NUM; idx++) { if (unit_pointers[idx]) continue; hdw->unit_number = idx; unit_pointers[idx] = hdw; break; } - } while (0); up(&pvr2_unit_sem); + } while (0); mutex_unlock(&pvr2_unit_mtx); cnt1 = 0; cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2"); @@ -2132,6 +2139,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->usb_intf = intf; hdw->usb_dev = interface_to_usbdev(intf); + scnprintf(hdw->bus_info,sizeof(hdw->bus_info), + "usb %s address %d", + hdw->usb_dev->dev.bus_id, + hdw->usb_dev->devnum); + ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; usb_set_interface(hdw->usb_dev,ifnum,0); @@ -2201,13 +2213,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) } pvr2_i2c_core_done(hdw); pvr2_hdw_remove_usb_stuff(hdw); - down(&pvr2_unit_sem); do { + mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && (hdw->unit_number < PVR_NUM) && (unit_pointers[hdw->unit_number] == hdw)) { unit_pointers[hdw->unit_number] = NULL; } - } while (0); up(&pvr2_unit_sem); + } while (0); mutex_unlock(&pvr2_unit_mtx); kfree(hdw->controls); kfree(hdw->mpeg_ctrl_info); kfree(hdw->std_defs); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 319dab523..6e4cd7976 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -133,6 +133,9 @@ struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *); /* Retrieve serial number of device */ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *); +/* Retrieve bus location info of device */ +const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *); + /* Called when hardware has been unplugged */ void pvr2_hdw_disconnect(struct pvr2_hdw *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 22a02dd76..1a9563aa5 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -23,6 +23,7 @@ #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" +#include "pvrusb2.h" #include "compat.h" #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) @@ -39,6 +40,10 @@ static unsigned int i2c_scan = 0; module_param(i2c_scan, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); +static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; +module_param_array(ir_mode, int, NULL, 0444); +MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); + static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, unsigned int detail, char *buf,unsigned int maxlen); @@ -348,6 +353,15 @@ static int i2c_hack_wm8775(struct pvr2_hdw *hdw, return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen); } +/* This is an entry point designed to always fail any attempt to perform a + transfer. We use this to cause certain I2C addresses to not be + probed. */ +static int i2c_black_hole(struct pvr2_hdw *hdw, + u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) +{ + return -EIO; +} + /* This is a special entry point that is entered if an I2C operation is attempted to a cx25840 chip on model 24xxx hardware. This chip can sometimes wedge itself. Worse still, when this happens msp3400 can @@ -1080,10 +1094,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) } /* However, deal with various special cases for 24xxx hardware. */ + if (ir_mode[hdw->unit_number] == 0) { + printk(KERN_INFO "%s: IR disabled\n",hdw->name); + hdw->i2c_func[0x18] = i2c_black_hole; + } else if (ir_mode[hdw->unit_number] == 1) { + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + hdw->i2c_func[0x18] = i2c_24xxx_ir; + } + } if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { hdw->i2c_func[0x1b] = i2c_hack_wm8775; hdw->i2c_func[0x44] = i2c_hack_cx25840; - hdw->i2c_func[0x18] = i2c_24xxx_ir; } // Configure the adapter and set up everything else related to it. diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c index ccf5a1ac0..ab41fe782 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -25,7 +25,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/smp_lock.h> #include <linux/usb.h> #include <linux/videodev2.h> diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 4e3dd17dc..e28cc23ea 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -43,9 +43,11 @@ struct pvr2_sysfs { struct class_device_attribute attr_v4l_minor_number; struct class_device_attribute attr_v4l_radio_minor_number; struct class_device_attribute attr_unit_number; + struct class_device_attribute attr_bus_info; int v4l_minor_number_created_ok; int v4l_radio_minor_number_created_ok; int unit_number_created_ok; + int bus_info_created_ok; }; #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC @@ -517,40 +519,32 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) } sfp->item_last = cip; - cip->attr_name.attr.owner = THIS_MODULE; cip->attr_name.attr.name = "name"; cip->attr_name.attr.mode = S_IRUGO; cip->attr_name.show = fp->show_name; - cip->attr_type.attr.owner = THIS_MODULE; cip->attr_type.attr.name = "type"; cip->attr_type.attr.mode = S_IRUGO; cip->attr_type.show = fp->show_type; - cip->attr_min.attr.owner = THIS_MODULE; cip->attr_min.attr.name = "min_val"; cip->attr_min.attr.mode = S_IRUGO; cip->attr_min.show = fp->show_min; - cip->attr_max.attr.owner = THIS_MODULE; cip->attr_max.attr.name = "max_val"; cip->attr_max.attr.mode = S_IRUGO; cip->attr_max.show = fp->show_max; - cip->attr_val.attr.owner = THIS_MODULE; cip->attr_val.attr.name = "cur_val"; cip->attr_val.attr.mode = S_IRUGO; - cip->attr_custom.attr.owner = THIS_MODULE; cip->attr_custom.attr.name = "custom_val"; cip->attr_custom.attr.mode = S_IRUGO; - cip->attr_enum.attr.owner = THIS_MODULE; cip->attr_enum.attr.name = "enum_val"; cip->attr_enum.attr.mode = S_IRUGO; cip->attr_enum.show = fp->show_enum; - cip->attr_bits.attr.owner = THIS_MODULE; cip->attr_bits.attr.name = "bit_val"; cip->attr_bits.attr.mode = S_IRUGO; cip->attr_bits.show = fp->show_bits; @@ -615,12 +609,10 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) dip = kzalloc(sizeof(*dip),GFP_KERNEL); if (!dip) return; - dip->attr_debugcmd.attr.owner = THIS_MODULE; dip->attr_debugcmd.attr.name = "debugcmd"; dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; dip->attr_debugcmd.show = debugcmd_show; dip->attr_debugcmd.store = debugcmd_store; - dip->attr_debuginfo.attr.owner = THIS_MODULE; dip->attr_debuginfo.attr.name = "debuginfo"; dip->attr_debuginfo.attr.mode = S_IRUGO; dip->attr_debuginfo.show = debuginfo_show; @@ -706,6 +698,10 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) pvr2_sysfs_tear_down_debugifc(sfp); #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ pvr2_sysfs_tear_down_controls(sfp); + if (sfp->bus_info_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->attr_bus_info); + } if (sfp->v4l_minor_number_created_ok) { class_device_remove_file(sfp->class_dev, &sfp->attr_v4l_minor_number); @@ -736,6 +732,16 @@ static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf) } +static ssize_t bus_info_show(struct class_device *class_dev,char *buf) +{ + struct pvr2_sysfs *sfp; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + return scnprintf(buf,PAGE_SIZE,"%s\n", + pvr2_hdw_get_bus_info(sfp->channel.hdw)); +} + + static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev, char *buf) { @@ -796,7 +802,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, return; } - sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.show = v4l_minor_number_show; @@ -810,7 +815,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->v4l_minor_number_created_ok = !0; } - sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number"; sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; @@ -824,7 +828,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->v4l_radio_minor_number_created_ok = !0; } - sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.name = "unit_number"; sfp->attr_unit_number.attr.mode = S_IRUGO; sfp->attr_unit_number.show = unit_number_show; @@ -837,6 +840,19 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->unit_number_created_ok = !0; } + sfp->attr_bus_info.attr.name = "bus_info_str"; + sfp->attr_bus_info.attr.mode = S_IRUGO; + sfp->attr_bus_info.show = bus_info_show; + sfp->attr_bus_info.store = NULL; + ret = class_device_create_file(sfp->class_dev, + &sfp->attr_bus_info); + if (ret < 0) { + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + } else { + sfp->bus_info_created_ok = !0; + } + pvr2_sysfs_add_controls(sfp); #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC pvr2_sysfs_add_debugifc(sfp); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 9f2f11754..a8a8a36ee 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -204,6 +204,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); + strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw), + sizeof(cap->bus_info)); ret = 0; break; @@ -809,11 +811,11 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) { if (vp->dev_video) { pvr2_v4l2_dev_destroy(vp->dev_video); - vp->dev_video = 0; + vp->dev_video = NULL; } if (vp->dev_radio) { pvr2_v4l2_dev_destroy(vp->dev_radio); - vp->dev_radio = 0; + vp->dev_radio = NULL; } pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); @@ -1142,7 +1144,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, #endif int mindevnum; int unit_number; - int *nr_ptr = 0; + int *nr_ptr = NULL; dip->v4lp = vp; #if 0 diff --git a/linux/drivers/media/video/pwc/Kconfig b/linux/drivers/media/video/pwc/Kconfig index 8fdf7101d..7298cf2e1 100644 --- a/linux/drivers/media/video/pwc/Kconfig +++ b/linux/drivers/media/video/pwc/Kconfig @@ -1,6 +1,6 @@ config USB_PWC tristate "USB Philips Cameras" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y or M here if you want to use one of these Philips & OEM webcams: diff --git a/linux/drivers/media/video/pwc/philips.txt b/linux/drivers/media/video/pwc/philips.txt index f5e848410..f9f358428 100644 --- a/linux/drivers/media/video/pwc/philips.txt +++ b/linux/drivers/media/video/pwc/philips.txt @@ -54,9 +54,9 @@ fps Specifies the desired framerate. Is an integer in the range of 4-30. fbufs - This paramter specifies the number of internal buffers to use for storing + This parameter specifies the number of internal buffers to use for storing frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarely busy. However, on slow machines it + the cam is a bit slow or momentarily busy. However, on slow machines it only introduces lag, so choose carefully. The default is 3, which is reasonable. You can set it between 2 and 5. @@ -209,7 +209,7 @@ trace 128 0x80 PWCX debugging Off - For example, to trace the open() & read() fuctions, sum 8 + 4 = 12, + For example, to trace the open() & read() functions, sum 8 + 4 = 12, so you would supply trace=12 during insmod or modprobe. If you want to turn the initialization and probing tracing off, set trace=0. The default value for trace is 35 (0x23). diff --git a/linux/drivers/media/video/pwc/pwc-ctrl.c b/linux/drivers/media/video/pwc/pwc-ctrl.c index acd8d4af1..9cc416a59 100644 --- a/linux/drivers/media/video/pwc/pwc-ctrl.c +++ b/linux/drivers/media/video/pwc/pwc-ctrl.c @@ -140,6 +140,8 @@ static const char *size2name[PSZ_MAX] = An alternate value of 0 means this mode is not available at all. */ +#define PWC_FPS_MAX_NALA 8 + struct Nala_table_entry { char alternate; /* USB alternate setting */ int compressed; /* Compressed yes/no */ @@ -147,7 +149,9 @@ struct Nala_table_entry { unsigned char mode[3]; /* precomputed mode table */ }; -static struct Nala_table_entry Nala_table[PSZ_MAX][8] = +static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 }; + +static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = { #include "pwc-nala.h" }; @@ -423,6 +427,59 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame return 0; } +static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size) +{ + unsigned int i; + + for (i = 0; i < PWC_FPS_MAX_NALA; i++) { + if (Nala_table[size][i].alternate) { + if (index--==0) return Nala_fps_vector[i]; + } + } + return 0; +} + +static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size) +{ + unsigned int i; + + for (i = 0; i < PWC_FPS_MAX_KIARA; i++) { + if (Kiara_table[size][i][3].alternate) { + if (index--==0) return Kiara_fps_vector[i]; + } + } + return 0; +} + +static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size) +{ + unsigned int i; + + for (i=0; i < PWC_FPS_MAX_TIMON; i++) { + if (Timon_table[size][i][3].alternate) { + if (index--==0) return Timon_fps_vector[i]; + } + } + return 0; +} + +unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size) +{ + unsigned int ret; + + if (DEVICE_USE_CODEC1(pdev->type)) { + ret = pwc_get_fps_Nala(pdev, index, size); + + } else if (DEVICE_USE_CODEC3(pdev->type)) { + ret = pwc_get_fps_Kiara(pdev, index, size); + + } else { + ret = pwc_get_fps_Timon(pdev, index, size); + } + + return ret; +} + #define BLACK_Y 0 #define BLACK_U 128 #define BLACK_V 128 @@ -1362,7 +1419,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red); if (ret < 0) break; - ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); + ret = pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); if (ret < 0) break; } diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index 782699cf9..282ec2153 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -95,8 +95,8 @@ static const struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */ { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */ { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */ - { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ - { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */ + { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */ { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */ { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */ @@ -1541,7 +1541,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id case 0x0329: PWC_INFO("Philips SPC 900NC USB webcam detected.\n"); name = "Philips SPC 900NC webcam"; - type_id = 720; + type_id = 740; break; default: return -ENODEV; @@ -1595,8 +1595,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id features |= FEATURE_MOTOR_PANTILT; break; case 0x08b6: + PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n"); + name = "Cisco VT Camera"; + type_id = 740; /* CCD sensor */ + break; case 0x08b7: - case 0x08b8: + PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n"); + name = "Logitech ViewPort AV 100"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b8: /* Where this released? */ PWC_INFO("Logitech QuickCam detected (reserved ID).\n"); name = "Logitech QuickCam (res.)"; type_id = 730; /* Assuming CMOS */ diff --git a/linux/drivers/media/video/pwc/pwc-ioctl.h b/linux/drivers/media/video/pwc/pwc-ioctl.h index 784bc7252..58904acda 100644 --- a/linux/drivers/media/video/pwc/pwc-ioctl.h +++ b/linux/drivers/media/video/pwc/pwc-ioctl.h @@ -2,7 +2,7 @@ #define PWC_IOCTL_H /* (C) 2001-2004 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This is pwc-ioctl.h belonging to PWC 8.12.1 +/* This is pwc-ioctl.h belonging to PWC 10.0.10 It contains structures and defines to communicate from user space directly to the driver. */ @@ -51,6 +51,13 @@ ... the function */ +#include <linux/types.h> +#include <linux/version.h> + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 10) +/* Compatibility for older kernel */ +typedef __u16 __le16; +#endif /* Enumeration of image sizes */ #define PSZ_SQCIF 0x00 @@ -65,6 +72,8 @@ /* The frame rate is encoded in the video_window.flags parameter using the upper 16 bits, since some flags are defined nowadays. The following defines provide a mask and shift to filter out this value. + This value can also be passing using the private flag when using v4l2 and + VIDIOC_S_FMT ioctl. In 'Snapshot' mode the camera freezes its automatic exposure and colour balance controls. @@ -73,6 +82,8 @@ #define PWC_FPS_MASK 0x00FF0000 #define PWC_FPS_FRMASK 0x003F0000 #define PWC_FPS_SNAPSHOT 0x00400000 +#define PWC_QLT_MASK 0x03000000 +#define PWC_QLT_SHIFT 24 /* structure for transferring x & y coordinates */ @@ -289,4 +300,29 @@ struct pwc_table_init_buffer { }; #define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer) +/* + * This is private command used when communicating with v4l2. + * In the future all private ioctl will be remove/replace to + * use interface offer by v4l2. + */ + +#define V4L2_CID_PRIVATE_SAVE_USER (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PRIVATE_RESTORE_USER (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PRIVATE_COLOUR_MODE (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PRIVATE_AUTOCONTOUR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_PRIVATE_CONTOUR (V4L2_CID_PRIVATE_BASE + 5) +#define V4L2_CID_PRIVATE_BACKLIGHT (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_PRIVATE_FLICKERLESS (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8) + +struct pwc_raw_frame { + __le16 type; /* type of the webcam */ + __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */ + __u8 cmd[4]; /* the four byte of the command (in case of nala, + only the first 3 bytes is filled) */ + __u8 rawframe[0]; /* frame_size = H/4*vbandlength */ +} __attribute__ ((packed)); + + #endif diff --git a/linux/drivers/media/video/pwc/pwc-kiara.c b/linux/drivers/media/video/pwc/pwc-kiara.c index fec39cc5a..f4ae83c0c 100644 --- a/linux/drivers/media/video/pwc/pwc-kiara.c +++ b/linux/drivers/media/video/pwc/pwc-kiara.c @@ -42,6 +42,8 @@ #include "pwc-kiara.h" #include "pwc-uncompress.h" +const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 }; + const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = { /* SQCIF */ diff --git a/linux/drivers/media/video/pwc/pwc-kiara.h b/linux/drivers/media/video/pwc/pwc-kiara.h index 0bdb22547..047dad8c1 100644 --- a/linux/drivers/media/video/pwc/pwc-kiara.h +++ b/linux/drivers/media/video/pwc/pwc-kiara.h @@ -29,6 +29,8 @@ #include <media/pwc-ioctl.h> +#define PWC_FPS_MAX_KIARA 6 + struct Kiara_table_entry { char alternate; /* USB alternate interface */ @@ -37,8 +39,9 @@ struct Kiara_table_entry unsigned char mode[12]; /* precomputed mode settings for cam */ }; -extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; +extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4]; extern const unsigned int KiaraRomTable[8][2][16][8]; +extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA]; #endif diff --git a/linux/drivers/media/video/pwc/pwc-timon.c b/linux/drivers/media/video/pwc/pwc-timon.c index be65bdcd1..c56c174b1 100644 --- a/linux/drivers/media/video/pwc/pwc-timon.c +++ b/linux/drivers/media/video/pwc/pwc-timon.c @@ -40,7 +40,9 @@ #include "pwc-timon.h" -const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = +const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON] = { 5, 10, 15, 20, 25, 30 }; + +const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4] = { /* SQCIF */ { diff --git a/linux/drivers/media/video/pwc/pwc-timon.h b/linux/drivers/media/video/pwc/pwc-timon.h index eef9e2cd4..a6e22224c 100644 --- a/linux/drivers/media/video/pwc/pwc-timon.h +++ b/linux/drivers/media/video/pwc/pwc-timon.h @@ -44,6 +44,8 @@ #include <media/pwc-ioctl.h> +#define PWC_FPS_MAX_TIMON 6 + struct Timon_table_entry { char alternate; /* USB alternate interface */ @@ -52,9 +54,9 @@ struct Timon_table_entry unsigned char mode[13]; /* precomputed mode settings for cam */ }; -extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; +extern const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4]; extern const unsigned int TimonRomTable [16][2][16][8]; - +extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON]; #endif diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c index 2d5bb48f3..32fbe1ae6 100644 --- a/linux/drivers/media/video/pwc/pwc-v4l.c +++ b/linux/drivers/media/video/pwc/pwc-v4l.c @@ -127,7 +127,6 @@ static struct v4l2_queryctrl pwc_controls[] = { .step = 1, .default_value = 0, }, -#ifndef BROKEN_XAWTV { .id = V4L2_CID_PRIVATE_SAVE_USER, .type = V4L2_CTRL_TYPE_BUTTON, @@ -209,7 +208,6 @@ static struct v4l2_queryctrl pwc_controls[] = { .step = 1, .default_value = 0, }, -#endif }; @@ -1170,7 +1168,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, buf->sequence = 0; buf->memory = V4L2_MEMORY_MMAP; buf->m.offset = pdev->fill_image * pdev->len_per_image; - buf->length = buf->bytesused; + buf->length = pdev->len_per_image; pwc_next_image(pdev); PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index); @@ -1195,6 +1193,64 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, return 0; } + case VIDIOC_ENUM_FRAMESIZES: + { + struct v4l2_frmsizeenum *fsize = arg; + unsigned int i = 0, index = fsize->index; + + if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) { + for (i = 0; i < PSZ_MAX; i++) { + if (pdev->image_mask & (1UL << i)) { + if (!index--) { + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = pwc_image_sizes[i].x; + fsize->discrete.height = pwc_image_sizes[i].y; + return 0; + } + } + } + } else if (fsize->index == 0 && + ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) || + (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) { + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = pdev->abs_max.x; + fsize->discrete.height = pdev->abs_max.y; + return 0; + } + return -EINVAL; + } + + case VIDIOC_ENUM_FRAMEINTERVALS: + { + struct v4l2_frmivalenum *fival = arg; + int size = -1; + unsigned int i; + + for (i = 0; i < PSZ_MAX; i++) { + if (pwc_image_sizes[i].x == fival->width && + pwc_image_sizes[i].y == fival->height) { + size = i; + break; + } + } + + /* TODO: Support raw format */ + if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420) { + return -EINVAL; + } + + i = pwc_get_fps(pdev, fival->index, size); + if (!i) + return -EINVAL; + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete.numerator = 1; + fival->discrete.denominator = i; + + return 0; + } + default: return pwc_ioctl(pdev, cmd, arg); } /* ..switch */ diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h index e778a2b8c..acbb93129 100644 --- a/linux/drivers/media/video/pwc/pwc.h +++ b/linux/drivers/media/video/pwc/pwc.h @@ -44,7 +44,7 @@ #define PWC_MINOR 0 #define PWC_EXTRAMINOR 12 #define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR) -#define PWC_VERSION "10.0.12" +#define PWC_VERSION "10.0.13" #define PWC_NAME "pwc" #define PFX PWC_NAME ": " @@ -85,7 +85,7 @@ #define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) #define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) -#else /* if ! CONFIG_PWC_DEBUG */ +#else /* if ! CONFIG_USB_PWC_DEBUG */ #define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args) #define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args) @@ -287,6 +287,7 @@ void pwc_construct(struct pwc_device *pdev); /** Functions in pwc-ctrl.c */ /* Request a certain video mode. Returns < 0 if not possible */ extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); +extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size); /* Calculate the number of bytes per image (not frame) */ extern int pwc_mpt_reset(struct pwc_device *pdev, int flags); extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt); diff --git a/linux/drivers/media/video/saa7111.c b/linux/drivers/media/video/saa7111.c index f6f408e2a..7f34c0cdf 100644 --- a/linux/drivers/media/video/saa7111.c +++ b/linux/drivers/media/video/saa7111.c @@ -36,7 +36,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/saa7114.c b/linux/drivers/media/video/saa7114.c index 3fc451ea8..4ac79add1 100644 --- a/linux/drivers/media/video/saa7114.c +++ b/linux/drivers/media/video/saa7114.c @@ -39,7 +39,6 @@ #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/saa711x.c b/linux/drivers/media/video/saa711x.c index 0d23c3693..715e297fd 100644 --- a/linux/drivers/media/video/saa711x.c +++ b/linux/drivers/media/video/saa711x.c @@ -30,7 +30,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 5e8a2f498..aa0082d99 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1171,6 +1171,42 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_ECS_TVP3XP_4CB6] = { + /* Barry Scott <barry.scott@onelan.co.uk> */ + .name = "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_PHILIPS_PAL_I, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = "CVid over SVid", + .vmux = 0, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, [SAA7134_BOARD_AVACSSMARTTV] = { /* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */ .name = "AVACS SmartTV", @@ -1544,12 +1580,12 @@ struct saa7134_board saa7134_boards[] = { },{ .name = name_comp1, .vmux = 0, - .amux = LINE2, + .amux = LINE1, .gpio = 0x02, },{ .name = name_svideo, .vmux = 6, - .amux = LINE2, + .amux = LINE1, .gpio = 0x02, }}, .radio = { @@ -2755,6 +2791,35 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_KWORLD_DVBT_210] = { + .name = "KWorld DVB-T 210", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 1 << 21, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, [SAA7134_BOARD_KWORLD_ATSC110] = { .name = "Kworld ATSC110", .audio_clock = 0x00187de7, @@ -3447,6 +3512,68 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_SABRENT_TV_PCB05] = { + .name = "Sabrent PCMCIA TV-PCB05", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_comp2, + .vmux = 0, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, + [SAA7134_BOARD_10MOONSTVMASTER3] = { + /* Tony Wan <aloha_cn@hotmail.com> */ + .name = "10MOONS TM300 TV Card", + .audio_clock = 0x00200000, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x7000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .gpio = 0x0000, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x2000, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x2000, + }}, + .mute = { + .name = name_mute, + .amux = LINE2, + .gpio = 0x3000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3555,7 +3682,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5168, /* Animation Technologies (LifeView) */ - .subdevice = 0x0214, /* Standard PCI, LR214WF */ + .subdevice = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */ + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, /* Animation Technologies (LifeView) */ + .subdevice = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, },{ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3729,6 +3862,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1019, + .subdevice = 0x4cb6, + .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB6, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x12ab, .subdevice = 0x0800, @@ -3955,6 +4094,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x17de, + .subdevice = 0x7250, + .driver_data = SAA7134_BOARD_KWORLD_DVBT_210, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ .subvendor = 0x17de, .subdevice = 0x7350, @@ -4140,6 +4285,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x4857, .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */ + .subdevice = 0x2003, /* OEM cardbus */ + .driver_data = SAA7134_BOARD_SABRENT_TV_PCB05, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = PCI_VENDOR_ID_PHILIPS, + .subdevice = 0x2304, + .driver_data = SAA7134_BOARD_10MOONSTVMASTER3, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -4255,6 +4412,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_CINERGY600_MK3: case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: + case SAA7134_BOARD_ECS_TVP3XP_4CB6: case SAA7134_BOARD_MD2819: case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: case SAA7134_BOARD_KWORLD_XPERT: @@ -4287,6 +4445,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_A16AR: case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: + case SAA7134_BOARD_10MOONSTVMASTER3: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: @@ -4503,6 +4662,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PINNACLE_PCTV_310i: + case SAA7134_BOARD_KWORLD_DVBT_210: case SAA7134_BOARD_TEVION_DVBT_220RF: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 752e90e97..4a5bc90d2 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -176,18 +176,6 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, return mt352_pinnacle_init(fe); } -static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) -{ - if (buf_len < 5) - return -EINVAL; - - pllbuf[0] = 0x61; - dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1, - params->frequency, - params->u.ofdm.bandwidth); - return 5; -} - static struct mt352_config pinnacle_300i = { .demod_address = 0x3c >> 1, .adc_clock = 20333, @@ -445,135 +433,6 @@ static struct tda1004x_config philips_europa_config = { /* ------------------------------------------------------------------ */ -static int philips_fmd1216_tuner_init(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - /* this message is to set up ATC and ALC */ - static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) - return -EIO; - msleep(1); - - return 0; -} - -static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - /* this message actually turns the tuner back to analog mode */ - u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 }; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - msleep(1); - fmd1216_init[2] = 0x86; - fmd1216_init[3] = 0x54; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - msleep(1); - return 0; -} - -static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - u8 tuner_buf[4]; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len = - sizeof(tuner_buf) }; - int tuner_frequency = 0; - int divider = 0; - u8 band, mode, cp; - - /* determine charge pump */ - tuner_frequency = params->frequency + 36130000; - if (tuner_frequency < 87000000) - return -EINVAL; - /* low band */ - else if (tuner_frequency < 180000000) { - band = 1; - mode = 7; - cp = 0; - } else if (tuner_frequency < 195000000) { - band = 1; - mode = 6; - cp = 1; - /* mid band */ - } else if (tuner_frequency < 366000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 10; - } else { - band = 2; - } - mode = 7; - cp = 0; - } else if (tuner_frequency < 478000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 10; - } else { - band = 2; - } - mode = 6; - cp = 1; - /* high band */ - } else if (tuner_frequency < 662000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 12; - } else { - band = 4; - } - mode = 7; - cp = 0; - } else if (tuner_frequency < 840000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 12; - } else { - band = 4; - } - mode = 6; - cp = 1; - } else { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 12; - } else { - band = 4; - } - mode = 7; - cp = 1; - - } - /* calculate divisor */ - /* ((36166000 + Finput) / 166666) rounded! */ - divider = (tuner_frequency + 83333) / 166667; - - /* setup tuner buffer */ - tuner_buf[0] = (divider >> 8) & 0x7f; - tuner_buf[1] = divider & 0xff; - tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4; - tuner_buf[3] = 0x40 | band; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) { - wprintk("could not write to tuner at addr: 0x%02x\n", - addr << 1); - return -EIO; - } - return 0; -} - static struct tda1004x_config medion_cardbus = { .demod_address = 0x08, .invert = 1, @@ -888,6 +747,20 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = { .antenna_switch= 2, .request_firmware = philips_tda1004x_request_firmware }; +static struct tda1004x_config kworld_dvb_t_210_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, + .if_freq = TDA10046_FREQ_045, + .i2c_gate = 0x4b, + .tuner_address = 0x61, + .tuner_config = 2, + .antenna_switch= 1, + .request_firmware = philips_tda1004x_request_firmware +}; /* ------------------------------------------------------------------ * special case: this card uses saa713x GPIO22 for the mode switch */ @@ -945,18 +818,8 @@ static struct nxt200x_config avertvhda180 = { .demod_address = 0x0a, }; -static int nxt200x_set_pll_input(u8 *buf, int input) -{ - if (input) - buf[3] |= 0x08; - else - buf[3] &= ~0x08; - return 0; -} - static struct nxt200x_config kworldatsc110 = { .demod_address = 0x0a, - .set_pll_input = nxt200x_set_pll_input, }; /* ================================================================== @@ -992,7 +855,8 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs; + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + NULL, &dvb_pll_philips_td1316); } break; case SAA7134_BOARD_MD7134: @@ -1000,9 +864,8 @@ static int dvb_init(struct saa7134_dev *dev) &medion_cardbus, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; + dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address, + &dev->i2c_adap, &dvb_pll_fmd1216me); } break; case SAA7134_BOARD_PHILIPS_TOUGH: @@ -1040,6 +903,9 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; + case SAA7134_BOARD_KWORLD_DVBT_210: + configure_tda827x_fe(dev, &kworld_dvb_t_210_config); + break; case SAA7134_BOARD_PHILIPS_TIGER: configure_tda827x_fe(dev, &philips_tiger_config); break; @@ -1128,9 +994,9 @@ static int dvb_init(struct saa7134_dev *dev) if (dev->dvb.frontend) { dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; + + dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address, + &dev->i2c_adap, &dvb_pll_fmd1216me); } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200A: @@ -1178,6 +1044,8 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.init(dev->dvb.frontend); if (dev->dvb.frontend->ops.sleep) dev->dvb.frontend->ops.sleep(dev->dvb.frontend); + if (dev->dvb.frontend->ops.tuner_ops.sleep) + dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); } return ret; } diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index 1d41abee5..f470c85e7 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -465,7 +465,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) unsigned char buf; int i,rc; - for (i = 0; i < 128; i++) { + for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { c->addr = i; rc = i2c_master_recv(c,&buf,0); if (rc < 0) diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 24d3f5088..c505076ae 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -154,21 +154,18 @@ 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 saa7134_dev *dev = (struct saa7134_dev *)data; struct card_ir *ir = dev->remote; - unsigned long timeout; build_key(dev); - timeout = jiffies + (ir->polling * HZ / 1000); - mod_timer(&ir->timer, timeout); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) { if (ir->polling) { - init_timer(&ir->timer); - ir->timer.function = saa7134_input_timer; - ir->timer.data = (unsigned long)dev; + setup_timer(&ir->timer, saa7134_input_timer, + (unsigned long)dev); ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); } else if (ir->rc5_gpio) { @@ -322,6 +319,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x0040000; break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: + case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: ir_codes = ir_codes_asus_pc39; mask_keydown = 0x0040000; rc5_gpio = 1; @@ -333,6 +331,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x040000; polling = 50; // ms break; + case SAA7134_BOARD_10MOONSTVMASTER3: + ir_codes = ir_codes_encore_enltv; + mask_keycode = 0x5f80000; + mask_keyup = 0x8000000; + polling = 50; //ms + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c index 019e3eada..3a7c2b019 100644 --- a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/smp_lock.h> #include <asm/div64.h> #include "compat.h" diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index aa9d73c6b..d6f4bd0b4 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -242,6 +242,10 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_M102 110 #define SAA7134_BOARD_ASUS_P7131_4871 111 #define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112 +#define SAA7134_BOARD_ECS_TVP3XP_4CB6 113 +#define SAA7134_BOARD_KWORLD_DVBT_210 114 +#define SAA7134_BOARD_SABRENT_TV_PCB05 115 +#define SAA7134_BOARD_10MOONSTVMASTER3 116 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index f29e27b5b..04dad000d 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -33,7 +33,6 @@ #include <linux/major.h> #include <linux/slab.h> #include <linux/mm.h> -#include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> #include <asm/pgtable.h> diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c index eecb4002e..bf8a6d560 100644 --- a/linux/drivers/media/video/se401.c +++ b/linux/drivers/media/video/se401.c @@ -458,6 +458,13 @@ static int se401_start_stream(struct usb_se401 *se401) } 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; @@ -466,13 +473,26 @@ static int se401_start_stream(struct usb_se401 *se401) 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) - return -ENOMEM; + 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), @@ -490,6 +510,18 @@ static int se401_start_stream(struct usb_se401 *se401) 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) diff --git a/linux/drivers/media/video/se401.h b/linux/drivers/media/video/se401.h index 9fd8485f3..bdbb20f75 100644 --- a/linux/drivers/media/video/se401.h +++ b/linux/drivers/media/video/se401.h @@ -6,7 +6,6 @@ #include "compat.h" #include <linux/videodev.h> #include <media/v4l2-common.h> -#include <linux/smp_lock.h> #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) #include <linux/mutex.h> #endif diff --git a/linux/drivers/media/video/sn9c102/Kconfig b/linux/drivers/media/video/sn9c102/Kconfig index 1a7ccb666..f71f27277 100644 --- a/linux/drivers/media/video/sn9c102/Kconfig +++ b/linux/drivers/media/video/sn9c102/Kconfig @@ -1,6 +1,6 @@ config USB_SN9C102 tristate "USB SN9C1xx PC Camera Controller support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L2 ---help--- Say Y here if you want support for cameras based on SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. diff --git a/linux/drivers/media/video/sn9c102/Makefile b/linux/drivers/media/video/sn9c102/Makefile index 30e3dfe53..a56d16f69 100644 --- a/linux/drivers/media/video/sn9c102/Makefile +++ b/linux/drivers/media/video/sn9c102/Makefile @@ -1,7 +1,14 @@ -sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ - sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \ - sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ - sn9c102_tas5130d1b.o +sn9c102-objs := sn9c102_core.o \ + sn9c102_hv7131d.o \ + sn9c102_hv7131r.o \ + sn9c102_mi0343.o \ + sn9c102_mi0360.o \ + sn9c102_ov7630.o \ + sn9c102_ov7660.o \ + sn9c102_pas106b.o \ + sn9c102_pas202bcb.o \ + sn9c102_tas5110c1b.o \ + sn9c102_tas5110d.o \ + sn9c102_tas5130d1b.o obj-$(CONFIG_USB_SN9C102) += sn9c102.o - diff --git a/linux/drivers/media/video/sn9c102/sn9c102.h b/linux/drivers/media/video/sn9c102/sn9c102.h index d6af8fa87..4561c294f 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102.h +++ b/linux/drivers/media/video/sn9c102/sn9c102.h @@ -23,7 +23,6 @@ #include <linux/version.h> #include <linux/usb.h> -#include "compat.h" #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <linux/device.h> @@ -39,6 +38,7 @@ #endif #include <linux/string.h> #include <linux/stddef.h> +#include "compat.h" #include "sn9c102_config.h" #include "sn9c102_sensor.h" @@ -81,8 +81,13 @@ enum sn9c102_stream_state { typedef char sn9c102_sof_header_t[62]; +struct sn9c102_sof_t { + sn9c102_sof_header_t header; + u16 bytesread; +}; + struct sn9c102_sysfs_attr { - u8 reg, i2c_reg; + u16 reg, i2c_reg; sn9c102_sof_header_t frame_header; }; @@ -115,7 +120,7 @@ struct sn9c102_device { struct v4l2_jpegcompression compression; struct sn9c102_sysfs_attr sysfs; - sn9c102_sof_header_t sof_header; + struct sn9c102_sof_t sof; u16 reg[384]; struct sn9c102_module_param module_param; @@ -143,7 +148,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); } @@ -189,8 +194,8 @@ do { \ if ((level) == 1 || (level) == 2) \ pr_info("sn9c102: " fmt "\n", ## args); \ else if ((level) == 3) \ - pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + pr_debug("sn9c102: [%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) #else @@ -201,8 +206,8 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ + __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/linux/drivers/media/video/sn9c102/sn9c102_core.c b/linux/drivers/media/video/sn9c102/sn9c102_core.c index a02d43ece..d22638c01 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_core.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_core.c @@ -44,11 +44,12 @@ /*****************************************************************************/ #define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" -#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" +#define SN9C102_MODULE_ALIAS "sn9c1xx" +#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.34" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34) +#define SN9C102_MODULE_VERSION "1:1.44" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44) /*****************************************************************************/ @@ -56,6 +57,7 @@ MODULE_DEVICE_TABLE(usb, sn9c102_id_table); MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); MODULE_DESCRIPTION(SN9C102_MODULE_NAME); +MODULE_ALIAS(SN9C102_MODULE_ALIAS); MODULE_VERSION(SN9C102_MODULE_VERSION); MODULE_LICENSE(SN9C102_MODULE_LICENSE); @@ -106,8 +108,7 @@ MODULE_PARM_DESC(debug, "\n1 = critical errors" "\n2 = significant informations" "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." + "\nLevel 3 is useful for testing only." "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." "\n"); #endif @@ -121,8 +122,8 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; @@ -209,25 +210,41 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) /*****************************************************************************/ -int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index) +/* + Write a sequence of count value/register pairs. Returns -1 after the first + failed write, or 0 for no errors. +*/ +int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2], + int count) { struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; int i, res; - if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg)) - return -1; + for (i = 0; i < count; i++) { + u8 index = valreg[i][1]; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - index, 0, buff, sizeof(buff), - SN9C102_CTRL_TIMEOUT*sizeof(buff)); - if (res < 0) { - DBG(3, "Failed to write registers (index 0x%02X, error %d)", - index, res); - return -1; - } + /* + index is a u8, so it must be <256 and can't be out of range. + If we put in a check anyway, gcc annoys us with a warning + hat our check is useless. People get all uppity when they + see warnings in the kernel compile. + */ + + *buff = valreg[i][0]; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, + 0x41, index, 0, buff, 1, + SN9C102_CTRL_TIMEOUT); + + if (res < 0) { + DBG(3, "Failed to write a register (value 0x%02X, " + "index 0x%02X, error %d)", *buff, index, res); + return -1; + } - for (i = 0; i < sizeof(buff); i++) - cam->reg[index+i] = buff[i]; + cam->reg[index] = *buff; + } return 0; } @@ -258,8 +275,8 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) } -/* NOTE: reading some registers always returns 0 */ -static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) +/* NOTE: with the SN9C10[123] reading some registers always returns 0 */ +int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) { struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; @@ -285,7 +302,8 @@ int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) static int -sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) +sn9c102_i2c_wait(struct sn9c102_device* cam, + const struct sn9c102_sensor* sensor) { int i, r; @@ -306,7 +324,7 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) static int sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { int r , err = 0; @@ -328,7 +346,7 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, static int sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { int r; r = sn9c102_read_reg(cam, 0x08); @@ -338,12 +356,12 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, u8 data1, - u8 n, u8 buffer[]) + const struct sn9c102_sensor* sensor, u8 data0, + u8 data1, u8 n, u8 buffer[]) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; - int err = 0, res; + int i = 0, err = 0, res; /* Write cycle */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | @@ -388,7 +406,8 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, } if (buffer) - memcpy(buffer, data, sizeof(buffer)); + for (i = 0; i < n && i < 5; i++) + buffer[n-i-1] = data[4-i]; return (int)data[4]; } @@ -396,7 +415,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, u8 data0, + const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) { struct usb_device* udev = cam->usbdev; @@ -435,7 +454,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, int sn9c102_i2c_try_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address) + const struct sn9c102_sensor* sensor, u8 address) { return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, address, 1, NULL); @@ -444,7 +463,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam, int sn9c102_i2c_try_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address, u8 value) + const struct sn9c102_sensor* sensor, u8 address, u8 value) { return sn9c102_i2c_try_raw_write(cam, sensor, 3, sensor->i2c_slave_id, address, @@ -485,18 +504,43 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam) static void* sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) { - char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; - size_t soflen = 0, i; + static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; + const char *m = mem; + size_t soflen = 0, i, j; soflen = sn9c102_sof_length(cam); - for (i = 0; (len >= soflen) && (i <= len - soflen); i++) - if (!memcmp(mem + i, sof_header, sizeof(sof_header))) { - memcpy(cam->sof_header, mem + i, - sizeof(sn9c102_sof_header_t)); - /* Skip the header */ - return mem + i + soflen; + for (i = 0; i < len; i++) { + size_t b; + + /* Read the variable part of the header */ + if (unlikely(cam->sof.bytesread >= sizeof(marker))) { + cam->sof.header[cam->sof.bytesread] = *(m+i); + if (++cam->sof.bytesread == soflen) { + cam->sof.bytesread = 0; + return mem + i; } + continue; + } + + /* Search for the SOF marker (fixed part) in the header */ + for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) { + if (unlikely(i+j) == len) + return NULL; + if (*(m+i+j) == marker[cam->sof.bytesread]) { + cam->sof.header[cam->sof.bytesread] = *(m+i+j); + if (++cam->sof.bytesread == sizeof(marker)) { + PDBGG("Bytes to analyze: %zd. SOF " + "starts at byte #%zd", len, i); + i += j+1; + break; + } + } else { + cam->sof.bytesread = 0; + break; + } + } + } return NULL; } @@ -505,7 +549,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) static void* sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) { - char eof_header[4][4] = { + static const u8 eof_header[4][4] = { {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x80, 0x00, 0x00, 0x00}, @@ -513,10 +557,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) }; size_t i, j; + /* The EOF header does not exist in compressed data */ if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - return NULL; /* EOF header does not exist in compressed data */ + return NULL; + /* + The EOF header might cross the packet boundary, but this is not a + problem, since the end of a frame is determined by checking its size + in the first place. + */ for (i = 0; (len >= 4) && (i <= len - 4); i++) for (j = 0; j < ARRAY_SIZE(eof_header); j++) if (!memcmp(mem + i, eof_header[j], 4)) @@ -529,7 +579,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) static void sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) { - static u8 jpeg_header[589] = { + static const u8 jpeg_header[589] = { 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, @@ -612,16 +662,6 @@ sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) } -static void -sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f) -{ - static const u8 eoi_marker[2] = {0xff, 0xd9}; - - memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker)); - f->buf.bytesused += sizeof(eoi_marker); -} - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) #else @@ -643,6 +683,7 @@ static void sn9c102_urb_complete(struct urb *urb) cam->stream = STREAM_OFF; if ((*f)) (*f)->state = F_QUEUED; + cam->sof.bytesread = 0; DBG(3, "Stream interrupted by application"); wake_up(&cam->wait_stream); } @@ -680,6 +721,7 @@ static void sn9c102_urb_complete(struct urb *urb) if (status) { DBG(3, "Error in isochronous frame"); (*f)->state = F_ERROR; + cam->sof.bytesread = 0; continue; } @@ -696,13 +738,13 @@ end_of_frame: if (eof) img = (eof > pos) ? eof - pos - 1 : 0; - if ((*f)->buf.bytesused+img > imagesize) { + if ((*f)->buf.bytesused + img > imagesize) { u32 b; b = (*f)->buf.bytesused + img - imagesize; img = imagesize - (*f)->buf.bytesused; - DBG(3, "Expected EOF not found: " - "video frame cut"); + PDBGG("Expected EOF not found: video " + "frame cut"); if (eof) DBG(3, "Exceeded limit: +%u " "bytes", (unsigned)(b)); @@ -723,11 +765,6 @@ end_of_frame: V4L2_PIX_FMT_JPEG) && eof)) { u32 b; - if (cam->sensor.pix_format.pixelformat - == V4L2_PIX_FMT_JPEG) - sn9c102_write_eoimarker(cam, - (*f)); - b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; @@ -745,7 +782,7 @@ end_of_frame: spin_unlock(&cam->queue_lock); memcpy(cam->sysfs.frame_header, - cam->sof_header, soflen); + cam->sof.header, soflen); DBG(3, "Video frame captured: %lu " "bytes", (unsigned long)(b)); @@ -795,7 +832,13 @@ start_of_frame: V4L2_PIX_FMT_SN9C10X || cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) { - eof = sof - soflen; + if (sof - pos >= soflen) { + eof = sof - soflen; + } else { /* remove header */ + eof = pos; + (*f)->buf.bytesused -= + (soflen - (sof - pos)); + } goto end_of_frame; } else { DBG(3, "SOF before expected EOF after " @@ -882,6 +925,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) } cam->frame_current = NULL; + cam->sof.bytesread = 0; for (i = 0; i < SN9C102_URBS; i++) { err = usb_submit_urb(cam->urb[i], GFP_KERNEL); @@ -963,9 +1007,9 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count) if (len < 6) { strncpy(str, buff, len); - str[len+1] = '\0'; + str[len] = '\0'; } else { - strncpy(str, buff, 4); + strncpy(str, buff, 6); str[6] = '\0'; } @@ -1066,7 +1110,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) count = sprintf(buf, "%d\n", val); - DBG(3, "Read bytes: %zd", count); + DBG(3, "Read bytes: %zd, value: %d", count, val); mutex_unlock(&sn9c102_sysfs_lock); @@ -1201,7 +1245,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) count = sprintf(buf, "%d\n", val); - DBG(3, "Read bytes: %zd", count); + DBG(3, "Read bytes: %zd, value: %d", count, val); mutex_unlock(&sn9c102_sysfs_lock); @@ -1375,35 +1419,35 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO, static int sn9c102_create_sysfs(struct sn9c102_device* cam) { - struct video_device *v4ldev = cam->v4ldev; + struct class_device *classdev = &(cam->v4ldev->class_dev); int err = 0; - if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) + if ((err = class_device_create_file(classdev, &class_device_attr_reg))) goto err_out; - if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) + if ((err = class_device_create_file(classdev, &class_device_attr_val))) goto err_reg; - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_frame_header))) goto err_val; if (cam->sensor.sysfs_ops) { - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_i2c_reg))) goto err_frame_header; - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_i2c_val))) goto err_i2c_reg; } if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_green))) goto err_i2c_val; } else { - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_blue))) goto err_i2c_val; - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_red))) goto err_blue; } @@ -1411,19 +1455,19 @@ static int sn9c102_create_sysfs(struct sn9c102_device* cam) return 0; err_blue: - video_device_remove_file(v4ldev, &class_device_attr_blue); + class_device_remove_file(classdev, &class_device_attr_blue); err_i2c_val: if (cam->sensor.sysfs_ops) - video_device_remove_file(v4ldev, &class_device_attr_i2c_val); + class_device_remove_file(classdev, &class_device_attr_i2c_val); err_i2c_reg: if (cam->sensor.sysfs_ops) - video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); + class_device_remove_file(classdev, &class_device_attr_i2c_reg); err_frame_header: - video_device_remove_file(v4ldev, &class_device_attr_frame_header); + class_device_remove_file(classdev, &class_device_attr_frame_header); err_val: - video_device_remove_file(v4ldev, &class_device_attr_val); + class_device_remove_file(classdev, &class_device_attr_val); err_reg: - video_device_remove_file(v4ldev, &class_device_attr_reg); + class_device_remove_file(classdev, &class_device_attr_reg); err_out: return err; } @@ -1481,10 +1525,10 @@ sn9c102_set_compression(struct sn9c102_device* cam, case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: - if (compression->quality == 0) + if (compression->quality == 0) err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); - else if (compression->quality == 1) + else if (compression->quality == 1) err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); break; @@ -1493,10 +1537,10 @@ sn9c102_set_compression(struct sn9c102_device* cam, if (compression->quality == 0) { for (i = 0; i <= 63; i++) { err += sn9c102_write_reg(cam, - SN9C102_Y_QTABLE0[i], + SN9C102_Y_QTABLE1[i], 0x100 + i); err += sn9c102_write_reg(cam, - SN9C102_UV_QTABLE0[i], + SN9C102_UV_QTABLE1[i], 0x140 + i); } err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, @@ -1601,9 +1645,13 @@ static int sn9c102_init(struct sn9c102_device* cam) if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102 || cam->bridge == BRIDGE_SN9C103) { + if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) + s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8; cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; } else { + if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG; cam->compression.quality = cam->reg[0x18] & 0x40 ? 0 : 1; err += sn9c102_set_compression(cam, &cam->compression); @@ -1809,7 +1857,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) DBG(3, "Close and open the device again to choose " "the read method"); mutex_unlock(&cam->fileop_mutex); - return -EINVAL; + return -EBUSY; } if (cam->io == IO_NONE) { @@ -1849,16 +1897,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) return err; } } else { - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; } else if (timeout == 0 && !(cam->state & DEV_DISCONNECTED)) { DBG(1, "Video frame timeout elapsed"); @@ -2005,7 +2053,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) return -EIO; } - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { + mutex_unlock(&cam->fileop_mutex); + return -EACCES; + } + + if (cam->io != IO_MMAP || size != PAGE_ALIGN(cam->frame[0].buf.length)) { mutex_unlock(&cam->fileop_mutex); return -EINVAL; @@ -2271,7 +2324,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_CROP failed. " "Unmap the buffers first."); - return -EINVAL; + return -EBUSY; } /* Preserve R,G or B origin */ @@ -2414,8 +2467,8 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: @@ -2449,8 +2502,10 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X || - pfmt->pixelformat==V4L2_PIX_FMT_JPEG) + pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ? + V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB; + pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X || + pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ? 0 : (pfmt->width * pfmt->priv) / 8; pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->field = V4L2_FIELD_NONE; @@ -2525,9 +2580,9 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: - if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; + if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: @@ -2537,7 +2592,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, break; } pix->priv = pfmt->priv; /* bpp */ - pix->colorspace = pfmt->colorspace; + pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ? + V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB; pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || pix->pixelformat == V4L2_PIX_FMT_JPEG) ? 0 : (pix->width * pix->priv) / 8; @@ -2555,7 +2611,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_FMT failed. Unmap the " "buffers first."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -2670,14 +2726,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg) if (cam->io == IO_READ) { DBG(3, "Close and open the device again to choose the mmap " "I/O method"); - return -EINVAL; + return -EBUSY; } for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " "still mapped."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -2789,15 +2845,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, if (err) return err; } else { - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) - return timeout; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; else if (timeout == 0 && !(cam->state & DEV_DISCONNECTED)) { DBG(1, "Video frame timeout elapsed"); @@ -2841,9 +2897,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg) if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) return -EINVAL; - if (list_empty(&cam->inqueue)) - return -EINVAL; - cam->stream = STREAM_ON; DBG(3, "Stream on"); @@ -3127,14 +3180,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, static const struct file_operations sn9c102_fops = { .owner = THIS_MODULE, - .open = sn9c102_open, + .open = sn9c102_open, .release = sn9c102_release, - .ioctl = sn9c102_ioctl, + .ioctl = sn9c102_ioctl, .compat_ioctl = v4l_compat_ioctl32, - .read = sn9c102_read, - .poll = sn9c102_poll, - .mmap = sn9c102_mmap, - .llseek = no_llseek, + .read = sn9c102_read, + .poll = sn9c102_poll, + .mmap = sn9c102_mmap, + .llseek = no_llseek, }; /*****************************************************************************/ @@ -3170,8 +3223,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) r = sn9c102_read_reg(cam, 0x00); if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { - DBG(1, "Sorry, this is not a SN9C1xx based camera " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + DBG(1, "Sorry, this is not a SN9C1xx-based camera " + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); err = -ENODEV; goto fail; } @@ -3181,23 +3234,23 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) case BRIDGE_SN9C101: case BRIDGE_SN9C102: DBG(2, "SN9C10[12] PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C103: DBG(2, "SN9C103 PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C105: DBG(2, "SN9C105 PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C120: DBG(2, "SN9C120 PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; } - for (i = 0; sn9c102_sensor_table[i]; i++) { + for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) { err = sn9c102_sensor_table[i](cam); if (!err) break; @@ -3208,7 +3261,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(3, "Support for %s maintained by %s", cam->sensor.name, cam->sensor.maintainer); } else { - DBG(1, "No supported image sensor detected"); + DBG(1, "No supported image sensor detected for this bridge"); err = -ENODEV; goto fail; } @@ -3264,6 +3317,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) "device controlling. Error #%d", err); #else DBG(2, "Optional device control through 'sysfs' interface disabled"); + DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' " + "configuration option to enable it."); #endif usb_set_intfdata(intf, cam); diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h index 3a682eca6..916054faf 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -86,19 +86,28 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, /* SN9C105 */ + { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, /* SN9C120 */ + { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, @@ -114,12 +123,15 @@ static const struct usb_device_id sn9c102_id_table[] = { Functions must return 0 on success, the appropriate error otherwise. */ extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); +extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam); extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); +extern int sn9c102_probe_mi0360(struct sn9c102_device* cam); extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); +extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); /* @@ -128,15 +140,17 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); the order of the list below, from top to bottom. */ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { + &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ + &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ + &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ + &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ - NULL, }; #endif /* _SN9C102_DEVTABLE_H_ */ diff --git a/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c index 7ae368f60..eaf9ad0dc 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -22,19 +22,13 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor hv7131d; - - static int hv7131d_init(struct sn9c102_device* cam) { - int err = 0; + int err; - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x0e, 0x18); - err += sn9c102_write_reg(cam, 0xf2, 0x19); + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x60, 0x17}, + {0x0e, 0x18}, {0xf2, 0x19}); err += sn9c102_i2c_write(cam, 0x01, 0x04); err += sn9c102_i2c_write(cam, 0x02, 0x00); @@ -150,10 +144,10 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor hv7131d = { +static const struct sn9c102_sensor hv7131d = { .name = "HV7131D", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, @@ -250,20 +244,17 @@ static struct sn9c102_sensor hv7131d = { int sn9c102_probe_hv7131d(struct sn9c102_device* cam) { - int r0 = 0, r1 = 0, err = 0; + int r0 = 0, r1 = 0, err; - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) - return -EIO; + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17}); r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00); r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01); - if (r0 < 0 || r1 < 0) + if (err || r0 < 0 || r1 < 0) return -EIO; - if (r0 != 0x00 && r1 != 0x04) + if (r0 != 0x00 || r1 != 0x04) return -ENODEV; sn9c102_attach_sensor(cam, &hv7131d); diff --git a/linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c new file mode 100644 index 000000000..0fc401223 --- /dev/null +++ b/linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c @@ -0,0 +1,362 @@ +/*************************************************************************** + * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera * + * Controllers * + * * + * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * 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. * + ***************************************************************************/ + +#include "sn9c102_sensor.h" + + +static int hv7131r_init(struct sn9c102_device* cam) +{ + int err = 0; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04}, + {0x20, 0x05}, {0x20, 0x06}, + {0x03, 0x10}, {0x00, 0x14}, + {0x60, 0x17}, {0x0a, 0x18}, + {0xf0, 0x19}, {0x1d, 0x1a}, + {0x10, 0x1b}, {0x02, 0x1c}, + {0x03, 0x1d}, {0x0f, 0x1e}, + {0x0c, 0x1f}, {0x00, 0x20}, + {0x10, 0x21}, {0x20, 0x22}, + {0x30, 0x23}, {0x40, 0x24}, + {0x50, 0x25}, {0x60, 0x26}, + {0x70, 0x27}, {0x80, 0x28}, + {0x90, 0x29}, {0xa0, 0x2a}, + {0xb0, 0x2b}, {0xc0, 0x2c}, + {0xd0, 0x2d}, {0xe0, 0x2e}, + {0xf0, 0x2f}, {0xff, 0x30}); + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, + {0x00, 0x03}, {0x1a, 0x04}, + {0x44, 0x05}, {0x3e, 0x06}, + {0x1a, 0x07}, {0x03, 0x10}, + {0x08, 0x14}, {0xa3, 0x17}, + {0x4b, 0x18}, {0x00, 0x19}, + {0x1d, 0x1a}, {0x10, 0x1b}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x29, 0x21}, + {0x40, 0x22}, {0x54, 0x23}, + {0x66, 0x24}, {0x76, 0x25}, + {0x85, 0x26}, {0x94, 0x27}, + {0xa1, 0x28}, {0xae, 0x29}, + {0xbb, 0x2a}, {0xc7, 0x2b}, + {0xd3, 0x2c}, {0xde, 0x2d}, + {0xea, 0x2e}, {0xf4, 0x2f}, + {0xff, 0x30}, {0x00, 0x3F}, + {0xC7, 0x40}, {0x01, 0x41}, + {0x44, 0x42}, {0x00, 0x43}, + {0x44, 0x44}, {0x00, 0x45}, + {0x44, 0x46}, {0x00, 0x47}, + {0xC7, 0x48}, {0x01, 0x49}, + {0xC7, 0x4A}, {0x01, 0x4B}, + {0xC7, 0x4C}, {0x01, 0x4D}, + {0x44, 0x4E}, {0x00, 0x4F}, + {0x44, 0x50}, {0x00, 0x51}, + {0x44, 0x52}, {0x00, 0x53}, + {0xC7, 0x54}, {0x01, 0x55}, + {0xC7, 0x56}, {0x01, 0x57}, + {0xC7, 0x58}, {0x01, 0x59}, + {0x44, 0x5A}, {0x00, 0x5B}, + {0x44, 0x5C}, {0x00, 0x5D}, + {0x44, 0x5E}, {0x00, 0x5F}, + {0xC7, 0x60}, {0x01, 0x61}, + {0xC7, 0x62}, {0x01, 0x63}, + {0xC7, 0x64}, {0x01, 0x65}, + {0x44, 0x66}, {0x00, 0x67}, + {0x44, 0x68}, {0x00, 0x69}, + {0x44, 0x6A}, {0x00, 0x6B}, + {0xC7, 0x6C}, {0x01, 0x6D}, + {0xC7, 0x6E}, {0x01, 0x6F}, + {0xC7, 0x70}, {0x01, 0x71}, + {0x44, 0x72}, {0x00, 0x73}, + {0x44, 0x74}, {0x00, 0x75}, + {0x44, 0x76}, {0x00, 0x77}, + {0xC7, 0x78}, {0x01, 0x79}, + {0xC7, 0x7A}, {0x01, 0x7B}, + {0xC7, 0x7C}, {0x01, 0x7D}, + {0x44, 0x7E}, {0x00, 0x7F}, + {0x14, 0x84}, {0x00, 0x85}, + {0x27, 0x86}, {0x00, 0x87}, + {0x07, 0x88}, {0x00, 0x89}, + {0xEC, 0x8A}, {0x0f, 0x8B}, + {0xD8, 0x8C}, {0x0f, 0x8D}, + {0x3D, 0x8E}, {0x00, 0x8F}, + {0x3D, 0x90}, {0x00, 0x91}, + {0xCD, 0x92}, {0x0f, 0x93}, + {0xf7, 0x94}, {0x0f, 0x95}, + {0x0C, 0x96}, {0x00, 0x97}, + {0x00, 0x98}, {0x66, 0x99}, + {0x05, 0x9A}, {0x00, 0x9B}, + {0x04, 0x9C}, {0x00, 0x9D}, + {0x08, 0x9E}, {0x00, 0x9F}, + {0x2D, 0xC0}, {0x2D, 0xC1}, + {0x3A, 0xC2}, {0x05, 0xC3}, + {0x04, 0xC4}, {0x3F, 0xC5}, + {0x00, 0xC6}, {0x00, 0xC7}, + {0x50, 0xC8}, {0x3C, 0xC9}, + {0x28, 0xCA}, {0xD8, 0xCB}, + {0x14, 0xCC}, {0xEC, 0xCD}, + {0x32, 0xCE}, {0xDD, 0xCF}, + {0x32, 0xD0}, {0xDD, 0xD1}, + {0x6A, 0xD2}, {0x50, 0xD3}, + {0x00, 0xD4}, {0x00, 0xD5}, + {0x00, 0xD6}); + break; + default: + break; + } + + err += sn9c102_i2c_write(cam, 0x20, 0x00); + err += sn9c102_i2c_write(cam, 0x21, 0xd6); + err += sn9c102_i2c_write(cam, 0x25, 0x06); + + return err; +} + + +static int hv7131r_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_GAIN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0) + return -EIO; + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0) + return -EIO; + ctrl->value = ctrl->value & 0x3f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0) + return -EIO; + ctrl->value = ctrl->value & 0x3f; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0) + return -EIO; + ctrl->value = ctrl->value & 0x3f; + return 0; + case V4L2_CID_BLACK_LEVEL: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0) + return -EIO; + ctrl->value = (ctrl->value & 0x08) ? 1 : 0; + return 0; + default: + return -EINVAL; + } +} + + +static int hv7131r_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x30, ctrl->value); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x31, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x33, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x32, ctrl->value); + break; + case V4L2_CID_BLACK_LEVEL: + { + int r = sn9c102_i2c_read(cam, 0x01); + if (r < 0) + return -EIO; + err += sn9c102_i2c_write(cam, 0x01, + (ctrl->value<<3) | (r&0xf7)); + } + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int hv7131r_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int hv7131r_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { + err += sn9c102_write_reg(cam, 0xa0, 0x19); + err += sn9c102_i2c_write(cam, 0x01, 0x04); + } else { + err += sn9c102_write_reg(cam, 0x30, 0x19); + err += sn9c102_i2c_write(cam, 0x01, 0x04); + } + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { + err += sn9c102_write_reg(cam, 0xa5, 0x17); + err += sn9c102_i2c_write(cam, 0x01, 0x24); + } else { + err += sn9c102_write_reg(cam, 0xa3, 0x17); + err += sn9c102_i2c_write(cam, 0x01, 0x04); + } + break; + default: + break; + } + + return err; +} + + +static const struct sn9c102_sensor hv7131r = { + .name = "HV7131R", + .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", + .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x11, + .init = &hv7131r_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x40, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x08, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x1a, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x2f, + .flags = 0, + }, + { + .id = V4L2_CID_BLACK_LEVEL, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto black level compensation", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .get_ctrl = &hv7131r_get_ctrl, + .set_ctrl = &hv7131r_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &hv7131r_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &hv7131r_set_pix_format +}; + + +int sn9c102_probe_hv7131r(struct sn9c102_device* cam) +{ + int devid, err; + + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02}, + {0x34, 0x01}, {0x20, 0x17}, + {0x34, 0x01}, {0x46, 0x01}); + + devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00); + if (err || devid < 0) + return -EIO; + + if (devid != 0x02) + return -ENODEV; + + sn9c102_attach_sensor(cam, &hv7131r); + + return 0; +} diff --git a/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c b/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c index a33d1bc10..00b134ca0 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -22,36 +22,30 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor mi0343; -static u8 mi0343_i2c_data[5+1]; - - static int mi0343_init(struct sn9c102_device* cam) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x0a, 0x14); - err += sn9c102_write_reg(cam, 0x40, 0x01); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x07, 0x18); - err += sn9c102_write_reg(cam, 0xa0, 0x19); - - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x03, 0x01, 0xe1, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x04, 0x02, 0x81, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x05, 0x00, 0x17, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x06, 0x00, 0x11, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x62, 0x04, 0x9a, 0, 0); + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x0a, 0x14}, {0x40, 0x01}, + {0x20, 0x17}, {0x07, 0x18}, + {0xa0, 0x19}); + + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x01, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x00, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, + 0x01, 0xe1, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, + 0x02, 0x81, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, + 0x00, 0x17, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, + 0x00, 0x11, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62, + 0x04, 0x9a, 0, 0); return err; } @@ -60,43 +54,46 @@ static int mi0343_init(struct sn9c102_device* cam) static int mi0343_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + u8 data[2]; + switch (ctrl->id) { case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x09, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, + data) < 0) return -EIO; - ctrl->value = mi0343_i2c_data[2]; + ctrl->value = data[0]; return 0; case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x35, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, + data) < 0) return -EIO; break; case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; + ctrl->value = data[1] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; + ctrl->value = data[1] & 0x80 ? 1 : 0; return 0; case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2d, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, + data) < 0) return -EIO; break; case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2c, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, + data) < 0) return -EIO; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2e, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, + data) < 0) return -EIO; break; default: @@ -108,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, case V4L2_CID_RED_BALANCE: case V4L2_CID_BLUE_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); + ctrl->value = data[1] | (data[0] << 8); if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) ctrl->value -= 0x10; else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) @@ -124,6 +121,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, static int mi0343_set_ctrl(struct sn9c102_device* cam, const struct v4l2_control* ctrl) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); u16 reg = 0; int err = 0; @@ -143,50 +141,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam, switch (ctrl->id) { case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x09, ctrl->value, 0x00, 0, 0); break; case V4L2_CID_GAIN: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x35, reg >> 8, reg & 0xff, 0, 0); break; case V4L2_CID_HFLIP: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, ctrl->value ? 0x40:0x00, ctrl->value ? 0x20:0x00, 0, 0); break; case V4L2_CID_VFLIP: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, ctrl->value ? 0x80:0x00, ctrl->value ? 0x80:0x00, 0, 0); break; case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2d, reg >> 8, reg & 0xff, 0, 0); break; case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2c, reg >> 8, reg & 0xff, 0, 0); break; case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2b, reg >> 8, reg & 0xff, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2e, reg >> 8, reg & 0xff, 0, 0); break; @@ -216,16 +206,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam, static int mi0343_set_pix_format(struct sn9c102_device* cam, const struct v4l2_pix_format* pix) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0a, 0x00, 0x03, 0, 0); err += sn9c102_write_reg(cam, 0x20, 0x19); } else { - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0a, 0x00, 0x05, 0, 0); err += sn9c102_write_reg(cam, 0xa0, 0x19); } @@ -234,10 +223,10 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor mi0343 = { +static const struct sn9c102_sensor mi0343 = { .name = "MI-0343", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, .i2c_slave_id = 0x5d, @@ -343,19 +332,17 @@ static struct sn9c102_sensor mi0343 = { int sn9c102_probe_mi0343(struct sn9c102_device* cam) { - int err = 0; + u8 data[2]; - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) + if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) return -EIO; if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, - 2, mi0343_i2c_data) < 0) + 2, data) < 0) return -EIO; - if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) + if (data[1] != 0x42 || data[0] != 0xe3) return -ENODEV; sn9c102_attach_sensor(cam, &mi0343); diff --git a/linux/drivers/media/video/sn9c102/sn9c102_mi0360.c b/linux/drivers/media/video/sn9c102/sn9c102_mi0360.c new file mode 100644 index 000000000..f8d81d82e --- /dev/null +++ b/linux/drivers/media/video/sn9c102/sn9c102_mi0360.c @@ -0,0 +1,452 @@ +/*************************************************************************** + * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera * + * Controllers * + * * + * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * 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. * + ***************************************************************************/ + +#include "sn9c102_sensor.h" + + +static int mi0360_init(struct sn9c102_device* cam) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x0a, 0x14}, {0x40, 0x01}, + {0x20, 0x17}, {0x07, 0x18}, + {0xa0, 0x19}, {0x02, 0x1c}, + {0x03, 0x1d}, {0x0f, 0x1e}, + {0x0c, 0x1f}, {0x00, 0x20}, + {0x10, 0x21}, {0x20, 0x22}, + {0x30, 0x23}, {0x40, 0x24}, + {0x50, 0x25}, {0x60, 0x26}, + {0x70, 0x27}, {0x80, 0x28}, + {0x90, 0x29}, {0xa0, 0x2a}, + {0xb0, 0x2b}, {0xc0, 0x2c}, + {0xd0, 0x2d}, {0xe0, 0x2e}, + {0xf0, 0x2f}, {0xff, 0x30}); + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, + {0x00, 0x03}, {0x1a, 0x04}, + {0x50, 0x05}, {0x20, 0x06}, + {0x10, 0x07}, {0x03, 0x10}, + {0x08, 0x14}, {0xa2, 0x17}, + {0x47, 0x18}, {0x00, 0x19}, + {0x1d, 0x1a}, {0x10, 0x1b}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x29, 0x21}, + {0x40, 0x22}, {0x54, 0x23}, + {0x66, 0x24}, {0x76, 0x25}, + {0x85, 0x26}, {0x94, 0x27}, + {0xa1, 0x28}, {0xae, 0x29}, + {0xbb, 0x2a}, {0xc7, 0x2b}, + {0xd3, 0x2c}, {0xde, 0x2d}, + {0xea, 0x2e}, {0xf4, 0x2f}, + {0xff, 0x30}, {0x00, 0x3F}, + {0xC7, 0x40}, {0x01, 0x41}, + {0x44, 0x42}, {0x00, 0x43}, + {0x44, 0x44}, {0x00, 0x45}, + {0x44, 0x46}, {0x00, 0x47}, + {0xC7, 0x48}, {0x01, 0x49}, + {0xC7, 0x4A}, {0x01, 0x4B}, + {0xC7, 0x4C}, {0x01, 0x4D}, + {0x44, 0x4E}, {0x00, 0x4F}, + {0x44, 0x50}, {0x00, 0x51}, + {0x44, 0x52}, {0x00, 0x53}, + {0xC7, 0x54}, {0x01, 0x55}, + {0xC7, 0x56}, {0x01, 0x57}, + {0xC7, 0x58}, {0x01, 0x59}, + {0x44, 0x5A}, {0x00, 0x5B}, + {0x44, 0x5C}, {0x00, 0x5D}, + {0x44, 0x5E}, {0x00, 0x5F}, + {0xC7, 0x60}, {0x01, 0x61}, + {0xC7, 0x62}, {0x01, 0x63}, + {0xC7, 0x64}, {0x01, 0x65}, + {0x44, 0x66}, {0x00, 0x67}, + {0x44, 0x68}, {0x00, 0x69}, + {0x44, 0x6A}, {0x00, 0x6B}, + {0xC7, 0x6C}, {0x01, 0x6D}, + {0xC7, 0x6E}, {0x01, 0x6F}, + {0xC7, 0x70}, {0x01, 0x71}, + {0x44, 0x72}, {0x00, 0x73}, + {0x44, 0x74}, {0x00, 0x75}, + {0x44, 0x76}, {0x00, 0x77}, + {0xC7, 0x78}, {0x01, 0x79}, + {0xC7, 0x7A}, {0x01, 0x7B}, + {0xC7, 0x7C}, {0x01, 0x7D}, + {0x44, 0x7E}, {0x00, 0x7F}, + {0x14, 0x84}, {0x00, 0x85}, + {0x27, 0x86}, {0x00, 0x87}, + {0x07, 0x88}, {0x00, 0x89}, + {0xEC, 0x8A}, {0x0f, 0x8B}, + {0xD8, 0x8C}, {0x0f, 0x8D}, + {0x3D, 0x8E}, {0x00, 0x8F}, + {0x3D, 0x90}, {0x00, 0x91}, + {0xCD, 0x92}, {0x0f, 0x93}, + {0xf7, 0x94}, {0x0f, 0x95}, + {0x0C, 0x96}, {0x00, 0x97}, + {0x00, 0x98}, {0x66, 0x99}, + {0x05, 0x9A}, {0x00, 0x9B}, + {0x04, 0x9C}, {0x00, 0x9D}, + {0x08, 0x9E}, {0x00, 0x9F}, + {0x2D, 0xC0}, {0x2D, 0xC1}, + {0x3A, 0xC2}, {0x05, 0xC3}, + {0x04, 0xC4}, {0x3F, 0xC5}, + {0x00, 0xC6}, {0x00, 0xC7}, + {0x50, 0xC8}, {0x3C, 0xC9}, + {0x28, 0xCA}, {0xD8, 0xCB}, + {0x14, 0xCC}, {0xEC, 0xCD}, + {0x32, 0xCE}, {0xDD, 0xCF}, + {0x32, 0xD0}, {0xDD, 0xD1}, + {0x6A, 0xD2}, {0x50, 0xD3}, + {0x00, 0xD4}, {0x00, 0xD5}, + {0x00, 0xD6}); + break; + default: + break; + } + + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x01, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x00, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, + 0x01, 0xe1, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, + 0x02, 0x81, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, + 0x00, 0x17, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, + 0x00, 0x11, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62, + 0x04, 0x9a, 0, 0); + + return err; +} + + +static int mi0360_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + u8 data[2]; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, + data) < 0) + return -EIO; + ctrl->value = data[0]; + return 0; + case V4L2_CID_GAIN: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, + data) < 0) + return -EIO; + ctrl->value = data[1]; + return 0; + case V4L2_CID_RED_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, + data) < 0) + return -EIO; + ctrl->value = data[1]; + return 0; + case V4L2_CID_BLUE_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, + data) < 0) + return -EIO; + ctrl->value = data[1]; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, + data) < 0) + return -EIO; + ctrl->value = data[1]; + return 0; + case V4L2_CID_HFLIP: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) + return -EIO; + ctrl->value = data[1] & 0x20 ? 1 : 0; + return 0; + case V4L2_CID_VFLIP: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) + return -EIO; + ctrl->value = data[1] & 0x80 ? 1 : 0; + return 0; + default: + return -EINVAL; + } + + return 0; +} + + +static int mi0360_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x09, ctrl->value, 0x00, + 0, 0); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x35, 0x03, ctrl->value, + 0, 0); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2c, 0x03, ctrl->value, + 0, 0); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2d, 0x03, ctrl->value, + 0, 0); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2b, 0x03, ctrl->value, + 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2e, 0x03, ctrl->value, + 0, 0); + break; + case V4L2_CID_HFLIP: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x20, ctrl->value ? 0x40:0x00, + ctrl->value ? 0x20:0x00, + 0, 0); + break; + case V4L2_CID_VFLIP: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x20, ctrl->value ? 0x80:0x00, + ctrl->value ? 0x80:0x00, + 0, 0); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int mi0360_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; + break; + default: + break; + } + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int mi0360_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x0a, 0x00, 0x05, 0, 0); + err += sn9c102_write_reg(cam, 0x60, 0x19); + if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || + sn9c102_get_bridge(cam) == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, 0xa6, 0x17); + } else { + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x0a, 0x00, 0x02, 0, 0); + err += sn9c102_write_reg(cam, 0x20, 0x19); + if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || + sn9c102_get_bridge(cam) == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, 0xa2, 0x17); + } + + return err; +} + + +static const struct sn9c102_sensor mi0360 = { + .name = "MI-0360", + .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", + .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x5d, + .init = &mi0360_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x25, + .flags = 0, + }, + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x0f, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x32, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x25, + .flags = 0, + }, + }, + .get_ctrl = &mi0360_get_ctrl, + .set_ctrl = &mi0360_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &mi0360_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &mi0360_set_pix_format +}; + + +int sn9c102_probe_mi0360(struct sn9c102_device* cam) +{ + + u8 data[2]; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) + return -EIO; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, + {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) + return -EIO; + break; + default: + break; + } + + if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00, + 2, data) < 0) + return -EIO; + + if (data[0] != 0x82 || data[1] != 0x43) + return -ENODEV; + + sn9c102_attach_sensor(cam, &mi0360); + + return 0; +} diff --git a/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c b/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c index 7df09ff38..e68323478 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -22,9 +22,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor ov7630; - - static int ov7630_init(struct sn9c102_device* cam) { int err = 0; @@ -32,21 +29,19 @@ static int ov7630_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x0f, 0x18); - err += sn9c102_write_reg(cam, 0x50, 0x19); + err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, + {0x0f, 0x18}, {0x50, 0x19}); err += sn9c102_i2c_write(cam, 0x12, 0x8d); err += sn9c102_i2c_write(cam, 0x12, 0x0d); err += sn9c102_i2c_write(cam, 0x11, 0x00); - err += sn9c102_i2c_write(cam, 0x15, 0x34); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1c); - err += sn9c102_i2c_write(cam, 0x18, 0xbd); - err += sn9c102_i2c_write(cam, 0x19, 0x06); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); + err += sn9c102_i2c_write(cam, 0x15, 0x35); + err += sn9c102_i2c_write(cam, 0x16, 0x03); + err += sn9c102_i2c_write(cam, 0x17, 0x1c); + err += sn9c102_i2c_write(cam, 0x18, 0xbd); + err += sn9c102_i2c_write(cam, 0x19, 0x06); + err += sn9c102_i2c_write(cam, 0x1a, 0xf6); + err += sn9c102_i2c_write(cam, 0x1b, 0x04); err += sn9c102_i2c_write(cam, 0x20, 0x44); err += sn9c102_i2c_write(cam, 0x23, 0xee); err += sn9c102_i2c_write(cam, 0x26, 0xa0); @@ -67,40 +62,23 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x7d, 0xf7); break; case BRIDGE_SN9C103: - err += sn9c102_write_reg(cam, 0x00, 0x02); - err += sn9c102_write_reg(cam, 0x00, 0x03); - err += sn9c102_write_reg(cam, 0x1a, 0x04); - err += sn9c102_write_reg(cam, 0x20, 0x05); - err += sn9c102_write_reg(cam, 0x20, 0x06); - err += sn9c102_write_reg(cam, 0x20, 0x07); - err += sn9c102_write_reg(cam, 0x03, 0x10); - err += sn9c102_write_reg(cam, 0x0a, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x0f, 0x18); - err += sn9c102_write_reg(cam, 0x50, 0x19); - err += sn9c102_write_reg(cam, 0x1d, 0x1a); - err += sn9c102_write_reg(cam, 0x10, 0x1b); - err += sn9c102_write_reg(cam, 0x02, 0x1c); - err += sn9c102_write_reg(cam, 0x03, 0x1d); - err += sn9c102_write_reg(cam, 0x0f, 0x1e); - err += sn9c102_write_reg(cam, 0x0c, 0x1f); - err += sn9c102_write_reg(cam, 0x00, 0x20); - err += sn9c102_write_reg(cam, 0x10, 0x21); - err += sn9c102_write_reg(cam, 0x20, 0x22); - err += sn9c102_write_reg(cam, 0x30, 0x23); - err += sn9c102_write_reg(cam, 0x40, 0x24); - err += sn9c102_write_reg(cam, 0x50, 0x25); - err += sn9c102_write_reg(cam, 0x60, 0x26); - err += sn9c102_write_reg(cam, 0x70, 0x27); - err += sn9c102_write_reg(cam, 0x80, 0x28); - err += sn9c102_write_reg(cam, 0x90, 0x29); - err += sn9c102_write_reg(cam, 0xa0, 0x2a); - err += sn9c102_write_reg(cam, 0xb0, 0x2b); - err += sn9c102_write_reg(cam, 0xc0, 0x2c); - err += sn9c102_write_reg(cam, 0xd0, 0x2d); - err += sn9c102_write_reg(cam, 0xe0, 0x2e); - err += sn9c102_write_reg(cam, 0xf0, 0x2f); - err += sn9c102_write_reg(cam, 0xff, 0x30); + err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, + {0x1a, 0x04}, {0x20, 0x05}, + {0x20, 0x06}, {0x20, 0x07}, + {0x03, 0x10}, {0x0a, 0x14}, + {0x60, 0x17}, {0x0f, 0x18}, + {0x50, 0x19}, {0x1d, 0x1a}, + {0x10, 0x1b}, {0x02, 0x1c}, + {0x03, 0x1d}, {0x0f, 0x1e}, + {0x0c, 0x1f}, {0x00, 0x20}, + {0x10, 0x21}, {0x20, 0x22}, + {0x30, 0x23}, {0x40, 0x24}, + {0x50, 0x25}, {0x60, 0x26}, + {0x70, 0x27}, {0x80, 0x28}, + {0x90, 0x29}, {0xa0, 0x2a}, + {0xb0, 0x2b}, {0xc0, 0x2c}, + {0xd0, 0x2d}, {0xe0, 0x2e}, + {0xf0, 0x2f}, {0xff, 0x30}); err += sn9c102_i2c_write(cam, 0x12, 0x8d); err += sn9c102_i2c_write(cam, 0x12, 0x0d); @@ -108,23 +86,23 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x11, 0x01); err += sn9c102_i2c_write(cam, 0x1b, 0x04); err += sn9c102_i2c_write(cam, 0x20, 0x44); - err += sn9c102_i2c_write(cam, 0x23, 0xee); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0x9a); + err += sn9c102_i2c_write(cam, 0x23, 0xee); + err += sn9c102_i2c_write(cam, 0x26, 0xa0); + err += sn9c102_i2c_write(cam, 0x27, 0x9a); err += sn9c102_i2c_write(cam, 0x28, 0x20); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2f, 0x3d); - err += sn9c102_i2c_write(cam, 0x30, 0x24); - err += sn9c102_i2c_write(cam, 0x32, 0x86); - err += sn9c102_i2c_write(cam, 0x60, 0xa9); - err += sn9c102_i2c_write(cam, 0x61, 0x42); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x88); - err += sn9c102_i2c_write(cam, 0x70, 0x0b); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x74, 0x21); - err += sn9c102_i2c_write(cam, 0x7d, 0xf7); + err += sn9c102_i2c_write(cam, 0x29, 0x30); + err += sn9c102_i2c_write(cam, 0x2f, 0x3d); + err += sn9c102_i2c_write(cam, 0x30, 0x24); + err += sn9c102_i2c_write(cam, 0x32, 0x86); + err += sn9c102_i2c_write(cam, 0x60, 0xa9); + err += sn9c102_i2c_write(cam, 0x61, 0x42); + err += sn9c102_i2c_write(cam, 0x65, 0x00); + err += sn9c102_i2c_write(cam, 0x69, 0x38); + err += sn9c102_i2c_write(cam, 0x6f, 0x88); + err += sn9c102_i2c_write(cam, 0x70, 0x0b); + err += sn9c102_i2c_write(cam, 0x71, 0x00); + err += sn9c102_i2c_write(cam, 0x74, 0x21); + err += sn9c102_i2c_write(cam, 0x7d, 0xf7); break; default: break; @@ -273,7 +251,7 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor ov7630 = { +static const struct sn9c102_sensor ov7630 = { .name = "OV7630", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, @@ -428,20 +406,16 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17}); break; case BRIDGE_SN9C103: /* do _not_ change anything! */ - err += sn9c102_write_reg(cam, 0x09, 0x01); - err += sn9c102_write_reg(cam, 0x42, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - err += sn9c102_write_reg(cam, 0x44, 0x02); + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01}, + {0x28, 0x17}, {0x44, 0x02}); pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); - if (err || pid < 0) { /* try a different initialization */ - err = sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - } + if (err || pid < 0) /* try a different initialization */ + err += sn9c102_write_const_regs(cam, {0x01, 0x01}, + {0x00, 0x01}); break; default: break; diff --git a/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c b/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c index d670c24d4..4b6474048 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c @@ -22,166 +22,90 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor ov7660; - - static int ov7660_init(struct sn9c102_device* cam) { int err = 0; - err += sn9c102_write_reg(cam, 0x40, 0x02); - err += sn9c102_write_reg(cam, 0x00, 0x03); - err += sn9c102_write_reg(cam, 0x1a, 0x04); - err += sn9c102_write_reg(cam, 0x03, 0x10); - err += sn9c102_write_reg(cam, 0x08, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x8b, 0x18); - err += sn9c102_write_reg(cam, 0x00, 0x19); - err += sn9c102_write_reg(cam, 0x1d, 0x1a); - err += sn9c102_write_reg(cam, 0x10, 0x1b); - err += sn9c102_write_reg(cam, 0x02, 0x1c); - err += sn9c102_write_reg(cam, 0x03, 0x1d); - err += sn9c102_write_reg(cam, 0x0f, 0x1e); - err += sn9c102_write_reg(cam, 0x0c, 0x1f); - err += sn9c102_write_reg(cam, 0x00, 0x20); - err += sn9c102_write_reg(cam, 0x29, 0x21); - err += sn9c102_write_reg(cam, 0x40, 0x22); - err += sn9c102_write_reg(cam, 0x54, 0x23); - err += sn9c102_write_reg(cam, 0x66, 0x24); - err += sn9c102_write_reg(cam, 0x76, 0x25); - err += sn9c102_write_reg(cam, 0x85, 0x26); - err += sn9c102_write_reg(cam, 0x94, 0x27); - err += sn9c102_write_reg(cam, 0xa1, 0x28); - err += sn9c102_write_reg(cam, 0xae, 0x29); - err += sn9c102_write_reg(cam, 0xbb, 0x2a); - err += sn9c102_write_reg(cam, 0xc7, 0x2b); - err += sn9c102_write_reg(cam, 0xd3, 0x2c); - err += sn9c102_write_reg(cam, 0xde, 0x2d); - err += sn9c102_write_reg(cam, 0xea, 0x2e); - err += sn9c102_write_reg(cam, 0xf4, 0x2f); - err += sn9c102_write_reg(cam, 0xff, 0x30); - err += sn9c102_write_reg(cam, 0x00, 0x3F); - err += sn9c102_write_reg(cam, 0xC7, 0x40); - err += sn9c102_write_reg(cam, 0x01, 0x41); - err += sn9c102_write_reg(cam, 0x44, 0x42); - err += sn9c102_write_reg(cam, 0x00, 0x43); - err += sn9c102_write_reg(cam, 0x44, 0x44); - err += sn9c102_write_reg(cam, 0x00, 0x45); - err += sn9c102_write_reg(cam, 0x44, 0x46); - err += sn9c102_write_reg(cam, 0x00, 0x47); - err += sn9c102_write_reg(cam, 0xC7, 0x48); - err += sn9c102_write_reg(cam, 0x01, 0x49); - err += sn9c102_write_reg(cam, 0xC7, 0x4A); - err += sn9c102_write_reg(cam, 0x01, 0x4B); - err += sn9c102_write_reg(cam, 0xC7, 0x4C); - err += sn9c102_write_reg(cam, 0x01, 0x4D); - err += sn9c102_write_reg(cam, 0x44, 0x4E); - err += sn9c102_write_reg(cam, 0x00, 0x4F); - err += sn9c102_write_reg(cam, 0x44, 0x50); - err += sn9c102_write_reg(cam, 0x00, 0x51); - err += sn9c102_write_reg(cam, 0x44, 0x52); - err += sn9c102_write_reg(cam, 0x00, 0x53); - err += sn9c102_write_reg(cam, 0xC7, 0x54); - err += sn9c102_write_reg(cam, 0x01, 0x55); - err += sn9c102_write_reg(cam, 0xC7, 0x56); - err += sn9c102_write_reg(cam, 0x01, 0x57); - err += sn9c102_write_reg(cam, 0xC7, 0x58); - err += sn9c102_write_reg(cam, 0x01, 0x59); - err += sn9c102_write_reg(cam, 0x44, 0x5A); - err += sn9c102_write_reg(cam, 0x00, 0x5B); - err += sn9c102_write_reg(cam, 0x44, 0x5C); - err += sn9c102_write_reg(cam, 0x00, 0x5D); - err += sn9c102_write_reg(cam, 0x44, 0x5E); - err += sn9c102_write_reg(cam, 0x00, 0x5F); - err += sn9c102_write_reg(cam, 0xC7, 0x60); - err += sn9c102_write_reg(cam, 0x01, 0x61); - err += sn9c102_write_reg(cam, 0xC7, 0x62); - err += sn9c102_write_reg(cam, 0x01, 0x63); - err += sn9c102_write_reg(cam, 0xC7, 0x64); - err += sn9c102_write_reg(cam, 0x01, 0x65); - err += sn9c102_write_reg(cam, 0x44, 0x66); - err += sn9c102_write_reg(cam, 0x00, 0x67); - err += sn9c102_write_reg(cam, 0x44, 0x68); - err += sn9c102_write_reg(cam, 0x00, 0x69); - err += sn9c102_write_reg(cam, 0x44, 0x6A); - err += sn9c102_write_reg(cam, 0x00, 0x6B); - err += sn9c102_write_reg(cam, 0xC7, 0x6C); - err += sn9c102_write_reg(cam, 0x01, 0x6D); - err += sn9c102_write_reg(cam, 0xC7, 0x6E); - err += sn9c102_write_reg(cam, 0x01, 0x6F); - err += sn9c102_write_reg(cam, 0xC7, 0x70); - err += sn9c102_write_reg(cam, 0x01, 0x71); - err += sn9c102_write_reg(cam, 0x44, 0x72); - err += sn9c102_write_reg(cam, 0x00, 0x73); - err += sn9c102_write_reg(cam, 0x44, 0x74); - err += sn9c102_write_reg(cam, 0x00, 0x75); - err += sn9c102_write_reg(cam, 0x44, 0x76); - err += sn9c102_write_reg(cam, 0x00, 0x77); - err += sn9c102_write_reg(cam, 0xC7, 0x78); - err += sn9c102_write_reg(cam, 0x01, 0x79); - err += sn9c102_write_reg(cam, 0xC7, 0x7A); - err += sn9c102_write_reg(cam, 0x01, 0x7B); - err += sn9c102_write_reg(cam, 0xC7, 0x7C); - err += sn9c102_write_reg(cam, 0x01, 0x7D); - err += sn9c102_write_reg(cam, 0x44, 0x7E); - err += sn9c102_write_reg(cam, 0x00, 0x7F); - err += sn9c102_write_reg(cam, 0x14, 0x84); - err += sn9c102_write_reg(cam, 0x00, 0x85); - err += sn9c102_write_reg(cam, 0x27, 0x86); - err += sn9c102_write_reg(cam, 0x00, 0x87); - err += sn9c102_write_reg(cam, 0x07, 0x88); - err += sn9c102_write_reg(cam, 0x00, 0x89); - err += sn9c102_write_reg(cam, 0xEC, 0x8A); - err += sn9c102_write_reg(cam, 0x0f, 0x8B); - err += sn9c102_write_reg(cam, 0xD8, 0x8C); - err += sn9c102_write_reg(cam, 0x0f, 0x8D); - err += sn9c102_write_reg(cam, 0x3D, 0x8E); - err += sn9c102_write_reg(cam, 0x00, 0x8F); - err += sn9c102_write_reg(cam, 0x3D, 0x90); - err += sn9c102_write_reg(cam, 0x00, 0x91); - err += sn9c102_write_reg(cam, 0xCD, 0x92); - err += sn9c102_write_reg(cam, 0x0f, 0x93); - err += sn9c102_write_reg(cam, 0xf7, 0x94); - err += sn9c102_write_reg(cam, 0x0f, 0x95); - err += sn9c102_write_reg(cam, 0x0C, 0x96); - err += sn9c102_write_reg(cam, 0x00, 0x97); - err += sn9c102_write_reg(cam, 0x00, 0x98); - err += sn9c102_write_reg(cam, 0x66, 0x99); - err += sn9c102_write_reg(cam, 0x05, 0x9A); - err += sn9c102_write_reg(cam, 0x00, 0x9B); - err += sn9c102_write_reg(cam, 0x04, 0x9C); - err += sn9c102_write_reg(cam, 0x00, 0x9D); - err += sn9c102_write_reg(cam, 0x08, 0x9E); - err += sn9c102_write_reg(cam, 0x00, 0x9F); - err += sn9c102_write_reg(cam, 0x2D, 0xC0); - err += sn9c102_write_reg(cam, 0x2D, 0xC1); - err += sn9c102_write_reg(cam, 0x3A, 0xC2); - err += sn9c102_write_reg(cam, 0x05, 0xC3); - err += sn9c102_write_reg(cam, 0x04, 0xC4); - err += sn9c102_write_reg(cam, 0x3F, 0xC5); - err += sn9c102_write_reg(cam, 0x00, 0xC6); - err += sn9c102_write_reg(cam, 0x00, 0xC7); - err += sn9c102_write_reg(cam, 0x50, 0xC8); - err += sn9c102_write_reg(cam, 0x3C, 0xC9); - err += sn9c102_write_reg(cam, 0x28, 0xCA); - err += sn9c102_write_reg(cam, 0xD8, 0xCB); - err += sn9c102_write_reg(cam, 0x14, 0xCC); - err += sn9c102_write_reg(cam, 0xEC, 0xCD); - err += sn9c102_write_reg(cam, 0x32, 0xCE); - err += sn9c102_write_reg(cam, 0xDD, 0xCF); - err += sn9c102_write_reg(cam, 0x32, 0xD0); - err += sn9c102_write_reg(cam, 0xDD, 0xD1); - err += sn9c102_write_reg(cam, 0x6A, 0xD2); - err += sn9c102_write_reg(cam, 0x50, 0xD3); - err += sn9c102_write_reg(cam, 0x00, 0xD4); - err += sn9c102_write_reg(cam, 0x00, 0xD5); - err += sn9c102_write_reg(cam, 0x00, 0xD6); + err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03}, + {0x1a, 0x04}, {0x03, 0x10}, + {0x08, 0x14}, {0x20, 0x17}, + {0x8b, 0x18}, {0x00, 0x19}, + {0x1d, 0x1a}, {0x10, 0x1b}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x29, 0x21}, + {0x40, 0x22}, {0x54, 0x23}, + {0x66, 0x24}, {0x76, 0x25}, + {0x85, 0x26}, {0x94, 0x27}, + {0xa1, 0x28}, {0xae, 0x29}, + {0xbb, 0x2a}, {0xc7, 0x2b}, + {0xd3, 0x2c}, {0xde, 0x2d}, + {0xea, 0x2e}, {0xf4, 0x2f}, + {0xff, 0x30}, {0x00, 0x3F}, + {0xC7, 0x40}, {0x01, 0x41}, + {0x44, 0x42}, {0x00, 0x43}, + {0x44, 0x44}, {0x00, 0x45}, + {0x44, 0x46}, {0x00, 0x47}, + {0xC7, 0x48}, {0x01, 0x49}, + {0xC7, 0x4A}, {0x01, 0x4B}, + {0xC7, 0x4C}, {0x01, 0x4D}, + {0x44, 0x4E}, {0x00, 0x4F}, + {0x44, 0x50}, {0x00, 0x51}, + {0x44, 0x52}, {0x00, 0x53}, + {0xC7, 0x54}, {0x01, 0x55}, + {0xC7, 0x56}, {0x01, 0x57}, + {0xC7, 0x58}, {0x01, 0x59}, + {0x44, 0x5A}, {0x00, 0x5B}, + {0x44, 0x5C}, {0x00, 0x5D}, + {0x44, 0x5E}, {0x00, 0x5F}, + {0xC7, 0x60}, {0x01, 0x61}, + {0xC7, 0x62}, {0x01, 0x63}, + {0xC7, 0x64}, {0x01, 0x65}, + {0x44, 0x66}, {0x00, 0x67}, + {0x44, 0x68}, {0x00, 0x69}, + {0x44, 0x6A}, {0x00, 0x6B}, + {0xC7, 0x6C}, {0x01, 0x6D}, + {0xC7, 0x6E}, {0x01, 0x6F}, + {0xC7, 0x70}, {0x01, 0x71}, + {0x44, 0x72}, {0x00, 0x73}, + {0x44, 0x74}, {0x00, 0x75}, + {0x44, 0x76}, {0x00, 0x77}, + {0xC7, 0x78}, {0x01, 0x79}, + {0xC7, 0x7A}, {0x01, 0x7B}, + {0xC7, 0x7C}, {0x01, 0x7D}, + {0x44, 0x7E}, {0x00, 0x7F}, + {0x14, 0x84}, {0x00, 0x85}, + {0x27, 0x86}, {0x00, 0x87}, + {0x07, 0x88}, {0x00, 0x89}, + {0xEC, 0x8A}, {0x0f, 0x8B}, + {0xD8, 0x8C}, {0x0f, 0x8D}, + {0x3D, 0x8E}, {0x00, 0x8F}, + {0x3D, 0x90}, {0x00, 0x91}, + {0xCD, 0x92}, {0x0f, 0x93}, + {0xf7, 0x94}, {0x0f, 0x95}, + {0x0C, 0x96}, {0x00, 0x97}, + {0x00, 0x98}, {0x66, 0x99}, + {0x05, 0x9A}, {0x00, 0x9B}, + {0x04, 0x9C}, {0x00, 0x9D}, + {0x08, 0x9E}, {0x00, 0x9F}, + {0x2D, 0xC0}, {0x2D, 0xC1}, + {0x3A, 0xC2}, {0x05, 0xC3}, + {0x04, 0xC4}, {0x3F, 0xC5}, + {0x00, 0xC6}, {0x00, 0xC7}, + {0x50, 0xC8}, {0x3C, 0xC9}, + {0x28, 0xCA}, {0xD8, 0xCB}, + {0x14, 0xCC}, {0xEC, 0xCD}, + {0x32, 0xCE}, {0xDD, 0xCF}, + {0x32, 0xD0}, {0xDD, 0xD1}, + {0x6A, 0xD2}, {0x50, 0xD3}, + {0x00, 0xD4}, {0x00, 0xD5}, + {0x00, 0xD6}); err += sn9c102_i2c_write(cam, 0x12, 0x80); err += sn9c102_i2c_write(cam, 0x11, 0x09); err += sn9c102_i2c_write(cam, 0x00, 0x0A); - err += sn9c102_i2c_write(cam, 0x01, 0x78); - err += sn9c102_i2c_write(cam, 0x02, 0x90); + err += sn9c102_i2c_write(cam, 0x01, 0x80); + err += sn9c102_i2c_write(cam, 0x02, 0x80); err += sn9c102_i2c_write(cam, 0x03, 0x00); err += sn9c102_i2c_write(cam, 0x04, 0x00); err += sn9c102_i2c_write(cam, 0x05, 0x08); @@ -198,7 +122,7 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x10, 0x20); err += sn9c102_i2c_write(cam, 0x11, 0x03); err += sn9c102_i2c_write(cam, 0x12, 0x05); - err += sn9c102_i2c_write(cam, 0x13, 0xF8); + err += sn9c102_i2c_write(cam, 0x13, 0xC7); err += sn9c102_i2c_write(cam, 0x14, 0x2C); err += sn9c102_i2c_write(cam, 0x15, 0x00); err += sn9c102_i2c_write(cam, 0x16, 0x02); @@ -238,7 +162,7 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x38, 0x02); err += sn9c102_i2c_write(cam, 0x39, 0x43); err += sn9c102_i2c_write(cam, 0x3A, 0x00); - err += sn9c102_i2c_write(cam, 0x3B, 0x02); + err += sn9c102_i2c_write(cam, 0x3B, 0x0A); err += sn9c102_i2c_write(cam, 0x3C, 0x6C); err += sn9c102_i2c_write(cam, 0x3D, 0x99); err += sn9c102_i2c_write(cam, 0x3E, 0x0E); @@ -357,25 +281,34 @@ static int ov7660_get_ctrl(struct sn9c102_device* cam, return -EIO; break; case V4L2_CID_DO_WHITE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x02); + if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0) + return -EIO; ctrl->value = (ctrl->value & 0x04) ? 1 : 0; break; case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x05); + if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0) + return -EIO; ctrl->value &= 0x7f; break; case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x06); + if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0) + return -EIO; ctrl->value &= 0x7f; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x07); + if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0) + return -EIO; ctrl->value &= 0x7f; break; + case SN9C102_V4L2_CID_BAND_FILTER: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0) + return -EIO; + ctrl->value &= 0x08; + break; case V4L2_CID_GAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) return -EIO; - ctrl->value &= 0x7f; + ctrl->value &= 0x1f; break; case V4L2_CID_AUTOGAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) @@ -411,12 +344,15 @@ static int ov7660_set_ctrl(struct sn9c102_device* cam, case SN9C102_V4L2_CID_GREEN_BALANCE: err += sn9c102_write_reg(cam, ctrl->value, 0x07); break; + case SN9C102_V4L2_CID_BAND_FILTER: + err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b); + break; case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); + err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value); break; case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value | - (ctrl->value << 1)); + err += sn9c102_i2c_write(cam, 0x13, 0xc0 | + (ctrl->value * 0x07)); break; default: return -EINVAL; @@ -462,7 +398,7 @@ static int ov7660_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor ov7660 = { +static const struct sn9c102_sensor ov7660 = { .name = "OV7660", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, @@ -477,9 +413,9 @@ static struct sn9c102_sensor ov7660 = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "global gain", .minimum = 0x00, - .maximum = 0x7f, + .maximum = 0x1f, .step = 0x01, - .default_value = 0x0a, + .default_value = 0x09, .flags = 0, }, { @@ -489,7 +425,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0xff, .step = 0x01, - .default_value = 0x50, + .default_value = 0x27, .flags = 0, }, { @@ -509,7 +445,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x1f, + .default_value = 0x14, .flags = 0, }, { @@ -519,7 +455,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x1e, + .default_value = 0x14, .flags = 0, }, { @@ -529,7 +465,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x01, .step = 0x01, - .default_value = 0x00, + .default_value = 0x01, .flags = 0, }, { @@ -539,7 +475,17 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x20, + .default_value = 0x14, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_BAND_FILTER, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "band filter", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, .flags = 0, }, }, @@ -572,13 +518,11 @@ static struct sn9c102_sensor ov7660 = { int sn9c102_probe_ov7660(struct sn9c102_device* cam) { - int pid, ver, err = 0; + int pid, ver, err; - err += sn9c102_write_reg(cam, 0x01, 0xf1); - err += sn9c102_write_reg(cam, 0x00, 0xf1); - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); + err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, + {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17}); pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a); ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b); @@ -586,6 +530,7 @@ int sn9c102_probe_ov7660(struct sn9c102_device* cam) return -EIO; if (pid != 0x76 || ver != 0x60) return -ENODEV; + sn9c102_attach_sensor(cam, &ov7660); return 0; diff --git a/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c b/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c index 8d79a5fae..360f2a848 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -23,19 +23,13 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor pas106b; - - static int pas106b_init(struct sn9c102_device* cam) { int err = 0; - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x20, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x20, 0x19}, {0x09, 0x18}); err += sn9c102_i2c_write(cam, 0x02, 0x0c); err += sn9c102_i2c_write(cam, 0x05, 0x5a); @@ -169,10 +163,10 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor pas106b = { +static const struct sn9c102_sensor pas106b = { .name = "PAS106B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, @@ -279,22 +273,21 @@ static struct sn9c102_sensor pas106b = { int sn9c102_probe_pas106b(struct sn9c102_device* cam) { - int r0 = 0, r1 = 0, err = 0; + int r0 = 0, r1 = 0; unsigned int pid = 0; /* Minimal initialization to enable the I2C communication NOTE: do NOT change the values! */ - err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ - err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */ - err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ - if (err) + if (sn9c102_write_const_regs(cam, + {0x01, 0x01}, /* sensor power down */ + {0x00, 0x01}, /* sensor power on */ + {0x28, 0x17})) /* sensor clock at 24 MHz */ return -EIO; r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00); r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01); - if (r0 < 0 || r1 < 0) return -EIO; diff --git a/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index 7894f01b5..ca4a1506e 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -28,9 +28,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor pas202bcb; - - static int pas202bcb_init(struct sn9c102_device* cam) { int err = 0; @@ -38,47 +35,28 @@ static int pas202bcb_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x30, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x30, 0x19}, {0x09, 0x18}); break; case BRIDGE_SN9C103: - err += sn9c102_write_reg(cam, 0x00, 0x02); - err += sn9c102_write_reg(cam, 0x00, 0x03); - err += sn9c102_write_reg(cam, 0x1a, 0x04); - err += sn9c102_write_reg(cam, 0x20, 0x05); - err += sn9c102_write_reg(cam, 0x20, 0x06); - err += sn9c102_write_reg(cam, 0x20, 0x07); - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x30, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); - err += sn9c102_write_reg(cam, 0x02, 0x1c); - err += sn9c102_write_reg(cam, 0x03, 0x1d); - err += sn9c102_write_reg(cam, 0x0f, 0x1e); - err += sn9c102_write_reg(cam, 0x0c, 0x1f); - err += sn9c102_write_reg(cam, 0x00, 0x20); - err += sn9c102_write_reg(cam, 0x10, 0x21); - err += sn9c102_write_reg(cam, 0x20, 0x22); - err += sn9c102_write_reg(cam, 0x30, 0x23); - err += sn9c102_write_reg(cam, 0x40, 0x24); - err += sn9c102_write_reg(cam, 0x50, 0x25); - err += sn9c102_write_reg(cam, 0x60, 0x26); - err += sn9c102_write_reg(cam, 0x70, 0x27); - err += sn9c102_write_reg(cam, 0x80, 0x28); - err += sn9c102_write_reg(cam, 0x90, 0x29); - err += sn9c102_write_reg(cam, 0xa0, 0x2a); - err += sn9c102_write_reg(cam, 0xb0, 0x2b); - err += sn9c102_write_reg(cam, 0xc0, 0x2c); - err += sn9c102_write_reg(cam, 0xd0, 0x2d); - err += sn9c102_write_reg(cam, 0xe0, 0x2e); - err += sn9c102_write_reg(cam, 0xf0, 0x2f); - err += sn9c102_write_reg(cam, 0xff, 0x30); + err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, + {0x1a, 0x04}, {0x20, 0x05}, + {0x20, 0x06}, {0x20, 0x07}, + {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x30, 0x19}, {0x09, 0x18}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x10, 0x21}, + {0x20, 0x22}, {0x30, 0x23}, + {0x40, 0x24}, {0x50, 0x25}, + {0x60, 0x26}, {0x70, 0x27}, + {0x80, 0x28}, {0x90, 0x29}, + {0xa0, 0x2a}, {0xb0, 0x2b}, + {0xc0, 0x2c}, {0xd0, 0x2d}, + {0xe0, 0x2e}, {0xf0, 0x2f}, + {0xff, 0x30}); break; default: break; @@ -218,7 +196,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam, } -static struct sn9c102_sensor pas202bcb = { +static const struct sn9c102_sensor pas202bcb = { .name = "PAS202BCB", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, @@ -328,15 +306,14 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */ - err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */ - err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */ + err = sn9c102_write_const_regs(cam, + {0x01, 0x01}, /* power down */ + {0x40, 0x01}, /* power on */ + {0x28, 0x17});/* clock 24 MHz */ break; case BRIDGE_SN9C103: /* do _not_ change anything! */ - err += sn9c102_write_reg(cam, 0x09, 0x01); - err += sn9c102_write_reg(cam, 0x44, 0x01); - err += sn9c102_write_reg(cam, 0x44, 0x02); - err += sn9c102_write_reg(cam, 0x29, 0x17); + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01}, + {0x44, 0x02}, {0x29, 0x17}); break; default: break; diff --git a/linux/drivers/media/video/sn9c102/sn9c102_sensor.h b/linux/drivers/media/video/sn9c102/sn9c102_sensor.h index 4fceceab6..d5fffc569 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/linux/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -22,12 +22,12 @@ #define _SN9C102_SENSOR_H_ #include <linux/usb.h> -#include "compat.h" -#include <linux/videodev.h> +#include <linux/videodev2.h> #include <linux/device.h> #include <linux/stddef.h> #include <linux/errno.h> #include <asm/types.h> +#include "compat.h" struct sn9c102_device; struct sn9c102_sensor; @@ -75,7 +75,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); /* Attach a probed sensor to the camera. */ extern void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor); + const struct sn9c102_sensor* sensor); /* Read/write routines: they always return -1 on error, 0 or the read value @@ -86,10 +86,11 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, */ /* The "try" I2C I/O versions are used when probing the sensor */ -extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address, u8 value); -extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address); +extern int sn9c102_i2c_try_write(struct sn9c102_device*, + const struct sn9c102_sensor*, u8 address, + u8 value); +extern int sn9c102_i2c_try_read(struct sn9c102_device*, + const struct sn9c102_sensor*, u8 address); /* These must be used if and only if the sensor doesn't implement the standard @@ -103,21 +104,31 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, byte. */ extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, + const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5); extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, - u8 data1, u8 n, u8 buffer[]); + const struct sn9c102_sensor* sensor, + u8 data0, u8 data1, u8 n, u8 buffer[]); /* To be used after the sensor struct has been attached to the camera struct */ extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); /* I/O on registers in the bridge. Could be used by the sensor methods too */ -extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index); -extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); +extern int sn9c102_read_reg(struct sn9c102_device*, u16 index); extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); +extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); +extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], + int count); +/* + Write multiple registers with constant values. For example: + sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); + Register adresses must be < 256. +*/ +#define sn9c102_write_const_regs(sn9c102_device, data...) \ + ({ const static u8 _valreg[][2] = {data}; \ + sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) /*****************************************************************************/ diff --git a/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index 90023ad63..e7d2de2ba 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -22,21 +22,14 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor tas5110c1b; - - static int tas5110c1b_init(struct sn9c102_device* cam) { int err = 0; - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x44, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x0a, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x06, 0x18); - err += sn9c102_write_reg(cam, 0xfb, 0x19); + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01}, + {0x00, 0x10}, {0x00, 0x11}, + {0x0a, 0x14}, {0x60, 0x17}, + {0x06, 0x18}, {0xfb, 0x19}); err += sn9c102_i2c_write(cam, 0xc0, 0x80); @@ -95,10 +88,10 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5110c1b = { +static const struct sn9c102_sensor tas5110c1b = { .name = "TAS5110C1B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_3WIRES, @@ -146,7 +139,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) const struct usb_device_id tas5110c1b_id_table[] = { { USB_DEVICE(0x0c45, 0x6001), }, { USB_DEVICE(0x0c45, 0x6005), }, - { USB_DEVICE(0x0c45, 0x6007), }, { USB_DEVICE(0x0c45, 0x60ab), }, { } }; diff --git a/linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c new file mode 100644 index 000000000..d32fdbccd --- /dev/null +++ b/linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c @@ -0,0 +1,118 @@ +/*************************************************************************** + * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera * + * Controllers * + * * + * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * 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. * + ***************************************************************************/ + +#include "sn9c102_sensor.h" + + +static int tas5110d_init(struct sn9c102_device* cam) +{ + int err; + + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01}, + {0x0a, 0x14}, {0x60, 0x17}, + {0x06, 0x18}, {0xfb, 0x19}); + + err += sn9c102_i2c_write(cam, 0x9a, 0xca); + + return err; +} + + +static int tas5110d_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + err += sn9c102_write_reg(cam, 0x14, 0x1a); + err += sn9c102_write_reg(cam, 0x0a, 0x1b); + + return err; +} + + +static int tas5110d_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x3b, 0x19); + else + err += sn9c102_write_reg(cam, 0xfb, 0x19); + + return err; +} + + +static const struct sn9c102_sensor tas5110d = { + .name = "TAS5110D", + .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, + .sysfs_ops = SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x61, + .init = &tas5110d_init, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + }, + .set_crop = &tas5110d_set_crop, + .pix_format = { + .width = 352, + .height = 288, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &tas5110d_set_pix_format +}; + + +int sn9c102_probe_tas5110d(struct sn9c102_device* cam) +{ + const struct usb_device_id tas5110d_id_table[] = { + { USB_DEVICE(0x0c45, 0x6007), }, + { } + }; + + if (!sn9c102_match_id(cam, tas5110d_id_table)) + return -ENODEV; + + sn9c102_attach_sensor(cam, &tas5110d); + + return 0; +} diff --git a/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index cb1b318bc..56fb1d575 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -22,21 +22,14 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor tas5130d1b; - - static int tas5130d1b_init(struct sn9c102_device* cam) { - int err = 0; + int err; - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x04, 0x01); - err += sn9c102_write_reg(cam, 0x01, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x07, 0x18); + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17}, + {0x04, 0x01}, {0x01, 0x10}, + {0x00, 0x11}, {0x00, 0x14}, + {0x60, 0x17}, {0x07, 0x18}); return err; } @@ -96,10 +89,10 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5130d1b = { +static const struct sn9c102_sensor tas5130d1b = { .name = "TAS5130D1B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_3WIRES, diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 849309fff..3e9ca9ace 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -46,7 +46,6 @@ #include "compat.h" #include <linux/videodev.h> #include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 109eb44a9..90ba0384e 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -466,7 +466,6 @@ static void set_audio(struct tuner *t) char* mode; t->tda827x_lpsel = 0; - mode = "xx"; if (t->std & V4L2_STD_MN) { t->sgIF = 92; t->tda8290_easy_mode = 0x01; @@ -496,8 +495,12 @@ static void set_audio(struct tuner *t) t->sgIF = 20; t->tda8290_easy_mode = 0x40; mode = "LC"; + } else { + t->sgIF = 124; + t->tda8290_easy_mode = 0x10; + mode = "xx"; } - tuner_dbg("setting tda8290 to system %s\n", mode); + tuner_dbg("setting tda8290 to system %s\n", mode); } static void set_tv_freq(struct i2c_client *c, unsigned int freq) @@ -640,6 +643,7 @@ int tda8290_init(struct i2c_client *c) t->has_signal = has_signal; t->standby = standby; t->tda827x_lpsel = 0; + t->mode = V4L2_TUNER_ANALOG_TV; tda8290_init_tuner(c); tda8290_init_if(c); diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index c7fbfc1b3..12abefad7 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -28,7 +28,6 @@ #include <linux/videodev.h> #include <media/v4l2-common.h> #include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> #include <linux/init.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) diff --git a/linux/drivers/media/video/tea5761.c b/linux/drivers/media/video/tea5761.c index fc800f656..a14b3d57b 100644 --- a/linux/drivers/media/video/tea5761.c +++ b/linux/drivers/media/video/tea5761.c @@ -3,7 +3,7 @@ * I2C address is allways 0x20 (0x10 at 7-bit mode). * * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab@infradead.org) - * This code is placed under the terms of the GNUv2 General Public License + * This code is placed under the terms of the GNUv2 General Public License * */ diff --git a/linux/drivers/media/video/tuner-simple.c b/linux/drivers/media/video/tuner-simple.c index 16469d905..a4718b2f0 100644 --- a/linux/drivers/media/video/tuner-simple.c +++ b/linux/drivers/media/video/tuner-simple.c @@ -63,9 +63,9 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); sound 2 33.16 - - NICAM 33.05 33.05 39.80 */ -#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ -#define PHILIPS_MF_SET_PAL_L 0x03 // France -#define PHILIPS_MF_SET_PAL_L2 0x02 // L' +#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ +#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */ +#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */ /* Control byte */ @@ -230,9 +230,13 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ - cb &= ~0x02; - if (t->std & V4L2_STD_SECAM) - cb |= 0x02; + cb &= ~0x03; + if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM + cb |= PHILIPS_MF_SET_STD_L; + else if (t->std & V4L2_STD_SECAM_LC) + cb |= PHILIPS_MF_SET_STD_LC; + else /* V4L2_STD_B|V4L2_STD_GH */ + cb |= PHILIPS_MF_SET_STD_BG; break; case TUNER_TEMIC_4046FM5: diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index cc885951e..210db55e6 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -26,9 +26,7 @@ #include "compat.h" #include <linux/videodev.h> #include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/kthread.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) #include <linux/freezer.h> diff --git a/linux/drivers/media/video/usbvideo/Kconfig b/linux/drivers/media/video/usbvideo/Kconfig index a0fd82b92..e4cb99c1f 100644 --- a/linux/drivers/media/video/usbvideo/Kconfig +++ b/linux/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL + depends on VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica @@ -39,7 +39,7 @@ config USB_KONICAWC config USB_QUICKCAM_MESSENGER tristate "USB Logitech Quickcam Messenger" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y or M here to enable support for the USB Logitech Quickcam diff --git a/linux/drivers/media/video/usbvideo/usbvideo.c b/linux/drivers/media/video/usbvideo/usbvideo.c index ec47f3244..e4981f41c 100644 --- a/linux/drivers/media/video/usbvideo/usbvideo.c +++ b/linux/drivers/media/video/usbvideo/usbvideo.c @@ -20,7 +20,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/mm.h> -#include <linux/smp_lock.h> #include <linux/vmalloc.h> #include <linux/init.h> #include <linux/spinlock.h> diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c index 6fb2c2633..750731da1 100644 --- a/linux/drivers/media/video/usbvideo/vicam.c +++ b/linux/drivers/media/video/usbvideo/vicam.c @@ -28,7 +28,7 @@ * * Portions of this code were also copied from usbvideo.c * - * Special thanks to the the whole team at Sourceforge for help making + * 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 diff --git a/linux/drivers/media/video/usbvision/Kconfig b/linux/drivers/media/video/usbvision/Kconfig index c43a5d899..fc24ef05b 100644 --- a/linux/drivers/media/video/usbvision/Kconfig +++ b/linux/drivers/media/video/usbvision/Kconfig @@ -1,6 +1,6 @@ config VIDEO_USBVISION tristate "USB video devices based on Nogatech NT1003/1004/1005" - depends on I2C && VIDEO_V4L2 && USB + depends on I2C && VIDEO_V4L2 select VIDEO_TUNER select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO ---help--- diff --git a/linux/drivers/media/video/usbvision/usbvision-cards.c b/linux/drivers/media/video/usbvision/usbvision-cards.c index b23672ad9..ecb10b296 100644 --- a/linux/drivers/media/video/usbvision/usbvision-cards.c +++ b/linux/drivers/media/video/usbvision/usbvision-cards.c @@ -1,6 +1,6 @@ /* - * USBVISION.H - * usbvision header file + * usbvision-cards.c + * usbvision cards definition file * * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> * @@ -24,152 +24,1064 @@ #include <linux/list.h> -#include <linux/i2c.h> #include "compat.h" #include <media/v4l2-dev.h> #include <media/tuner.h> #include "usbvision.h" +#include "usbvision-cards.h" /* Supported Devices: A table for usbvision.c*/ struct usbvision_device_data_st usbvision_device_data[] = { - {0xfff0, 0xfff0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"}, - {0x0a6f, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"}, - {0x050d, 0x0106, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USB VideoBus II Adapter"}, - {0x050d, 0x0207, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Belkin Components USB VideoBus"}, - {0x050d, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USB VideoBus II"}, - {0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"}, - {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"}, - {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"}, - {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"}, - {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Hauppauge WinTV USB Live (PAL B/G)"}, - {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Live Pro (NTSC M/N)"}, - {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"}, - {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"}, - {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"}, - {0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"}, - {0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"}, - {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTV USB (NTSC M/N)"}, - {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL B/G)"}, - {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL I)"}, - {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL/SECAM L)"}, - {0x0573, 0x4d04, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL D/K)"}, - {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (NTSC FM)"}, - {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL B/G FM)"}, - {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL I FM)"}, - {0x0573, 0x4d14, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTV USB (PAL D/K FM)"}, - {0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (NTSC M/N)"}, - {0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (NTSC M/N)"}, - {0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)"}, - {0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (NTSC M/N)"}, - {0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL B/G)"}, - {0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL I)"}, - {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL/SECAM L)"}, - {0x0573, 0x4d24, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL D/K)"}, - {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)"}, - {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)"}, - {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL B/G)"}, - {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL B/G,D/K)"}, - {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL I,D/K)"}, - {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (NTSC M/N FM)"}, - {0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL B/G FM)"}, - {0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL I FM)"}, - {0x0573, 0x4d34, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL D/K FM)"}, - {0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)"}, - {0x0573, 0x4d36, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (Temic PAL B/G FM)"}, - {0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)"}, - {0x0573, 0x4d38, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTV USB Pro (NTSC M/N FM)"}, - {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"}, - {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"}, - {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"}, - {0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"}, - {0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"}, - {0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"}, - {0x07f8, 0x9104, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Eskape Labs MyTV2Go"}, - {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"}, - {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"}, - {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"}, - {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"}, - {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"}, - {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, - {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"}, - {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, - {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"}, - {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"}, - {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"}, - {0x2400, 0x4200, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, - {} /* Terminating entry */ + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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 = -1, + .Y_Offset = -1, + .ModelString = "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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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)", + }, + [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", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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", + }, + [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)", + }, + [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_PHILIPS_PAL, + .X_Offset = 0, + .Y_Offset = 3, + .Dvi_yuv_override = 1, + .Dvi_yuv = 7, + .ModelString = "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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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", + }, + [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", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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", + }, + [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)", + }, + [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)", + }, + [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", + }, + [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", + }, }; +const int usbvision_device_data_size=ARRAY_SIZE(usbvision_device_data); /* Supported Devices */ struct usb_device_id usbvision_table [] = { - { USB_DEVICE(0xfff0, 0xfff0) }, /* Custom Dummy USBVision Device */ - { USB_DEVICE(0x0a6f, 0x0400) }, /* Xanboo */ - { USB_DEVICE(0x050d, 0x0106) }, /* Belkin USB VideoBus II Adapter */ - { USB_DEVICE(0x050d, 0x0207) }, /* Belkin Components USB VideoBus */ - { USB_DEVICE(0x050d, 0x0208) }, /* Belkin USB VideoBus II */ - { USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */ - { USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 resp. HAMA USB */ - { USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */ - { USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */ - { USB_DEVICE(0x0573, 0x2d00) }, /* Hauppauge WinTV USB Live (PAL B/G) */ - { USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge WinTV USB Live Pro (NTSC M/N) */ - { USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */ - { USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */ - { USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */ - { USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */ - { USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */ - { USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTV USB (NTSC M/N) */ - { USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTV USB (PAL B/G) */ - { USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTV USB (PAL I) */ - { USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTV USB (PAL/SECAM L) */ - { USB_DEVICE(0x0573, 0x4d04) }, /* Hauppauge WinTV USB (PAL D/K) */ - { USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTV USB (NTSC FM) */ - { USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTV USB (PAL B/G FM) */ - { USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTV USB (PAL I FM) */ - { USB_DEVICE(0x0573, 0x4d14) }, /* Hauppauge WinTV USB (PAL D/K FM) */ - { USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppauge WinTV USB Pro (NTSC M/N) */ - { USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppauge WinTV USB Pro (NTSC M/N) */ - { USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L) */ - { USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTV USB Pro (NTSC M/N) */ - { USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTV USB Pro (PAL B/G) */ - { USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTV USB Pro (PAL I) */ - { USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTV USB Pro (PAL/SECAM L) */ - { USB_DEVICE(0x0573, 0x4d24) }, /* Hauppauge WinTV USB Pro (PAL D/K) */ - { USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) */ - { USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) */ - { USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTV USB Pro (PAL B/G) */ - { USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTV USB Pro (PAL B/G,D/K) */ - { USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTV USB Pro (PAL I,D/K) */ - { USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTV USB Pro (NTSC M/N FM) */ - { USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTV USB Pro (PAL B/G FM) */ - { USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTV USB Pro (PAL I FM) */ - { USB_DEVICE(0x0573, 0x4d34) }, /* Hauppauge WinTV USB Pro (PAL D/K FM) */ - { USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM) */ - { USB_DEVICE(0x0573, 0x4d36) }, /* Hauppauge WinTV USB Pro (Temic PAL B/G FM) */ - { USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM) */ - { USB_DEVICE(0x0573, 0x4d38) }, /* Hauppauge WinTV USB Pro (NTSC M/N FM) */ - { USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */ - { USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */ - { USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */ - { USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */ - { USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */ - { USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */ - { USB_DEVICE(0x07f8, 0x9104) }, /* Eskape Labs MyTV2Go */ - { USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */ - { USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */ - { USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */ - { USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */ - { USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ - { USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ - { USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ - { USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ - { USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */ - { USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */ - { USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */ - { USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */ - - { } /* Terminating entry */ + { 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(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 }, }; MODULE_DEVICE_TABLE (usb, usbvision_table); diff --git a/linux/drivers/media/video/usbvision/usbvision-cards.h b/linux/drivers/media/video/usbvision/usbvision-cards.h new file mode 100644 index 000000000..512c5cee4 --- /dev/null +++ b/linux/drivers/media/video/usbvision/usbvision-cards.h @@ -0,0 +1,66 @@ +#define XANBOO 0 +#define BELKIN_VIDEOBUS_II 1 +#define BELKIN_VIDEOBUS 2 +#define BELKIN_USB_VIDEOBUS_II 3 +#define ECHOFX_INTERVIEW_LITE 4 +#define USBGEAR_USBG_V1 5 +#define D_LINK_V100 6 +#define X10_USB_CAMERA 7 +#define HPG_WINTV_LIVE_PAL_BG 8 +#define HPG_WINTV_LIVE_PRO_NTSC_MN 9 +#define ZORAN_PMD_NOGATECH 10 +#define NOGATECH_USB_TV_NTSC_FM 11 +#define PNY_USB_TV_NTSC_FM 12 +#define PV_PLAYTV_USB_PRO_PAL_FM 13 +#define ZT_721 14 +#define HPG_WINTV_NTSC_MN 15 +#define HPG_WINTV_PAL_BG 16 +#define HPG_WINTV_PAL_I 17 +#define HPG_WINTV_PAL_SECAM_L 18 +#define HPG_WINTV_PAL_D_K 19 +#define HPG_WINTV_NTSC_FM 20 +#define HPG_WINTV_PAL_BG_FM 21 +#define HPG_WINTV_PAL_I_FM 22 +#define HPG_WINTV_PAL_D_K_FM 23 +#define HPG_WINTV_PRO_NTSC_MN 24 +#define HPG_WINTV_PRO_NTSC_MN_V2 25 +#define HPG_WINTV_PRO_PAL 26 +#define HPG_WINTV_PRO_NTSC_MN_V3 27 +#define HPG_WINTV_PRO_PAL_BG 28 +#define HPG_WINTV_PRO_PAL_I 29 +#define HPG_WINTV_PRO_PAL_SECAM_L 30 +#define HPG_WINTV_PRO_PAL_D_K 31 +#define HPG_WINTV_PRO_PAL_SECAM 32 +#define HPG_WINTV_PRO_PAL_SECAM_V2 33 +#define HPG_WINTV_PRO_PAL_BG_V2 34 +#define HPG_WINTV_PRO_PAL_BG_D_K 35 +#define HPG_WINTV_PRO_PAL_I_D_K 36 +#define HPG_WINTV_PRO_NTSC_MN_FM 37 +#define HPG_WINTV_PRO_PAL_BG_FM 38 +#define HPG_WINTV_PRO_PAL_I_FM 39 +#define HPG_WINTV_PRO_PAL_D_K_FM 40 +#define HPG_WINTV_PRO_TEMIC_PAL_FM 41 +#define HPG_WINTV_PRO_TEMIC_PAL_BG_FM 42 +#define HPG_WINTV_PRO_PAL_FM 43 +#define HPG_WINTV_PRO_NTSC_MN_FM_V2 44 +#define CAMTEL_TVB330 45 +#define DIGITAL_VIDEO_CREATOR_I 46 +#define GLOBAL_VILLAGE_GV_007_NTSC 47 +#define DAZZLE_DVC_50_REV_1_NTSC 48 +#define DAZZLE_DVC_80_REV_1_PAL 49 +#define DAZZLE_DVC_90_REV_1_SECAM 50 +#define ESKAPE_LABS_MYTV2GO 51 +#define PINNA_PCTV_USB_PAL 52 +#define PINNA_PCTV_USB_SECAM 53 +#define PINNA_PCTV_USB_PAL_FM 54 +#define MIRO_PCTV_USB 55 +#define PINNA_PCTV_USB_NTSC_FM 56 +#define PINNA_PCTV_USB_PAL_FM_V2 57 +#define PINNA_PCTV_USB_NTSC_FM_V2 58 +#define PINNA_PCTV_USB_PAL_FM_V3 59 +#define PINNA_LINX_VD_IN_CAB_NTSC 60 +#define PINNA_LINX_VD_IN_CAB_PAL 61 +#define PINNA_PCTV_BUNGEE_PAL_FM 62 +#define HPG_WINTV 63 + +extern const int usbvision_device_data_size; diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 2d8dc023d..536c6c767 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -31,7 +31,6 @@ #include <linux/utsname.h> #include "compat.h" #include <linux/highmem.h> -#include <linux/smp_lock.h> #include <linux/videodev.h> #include <linux/vmalloc.h> #include <linux/module.h> @@ -1798,7 +1797,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma format = ISOC_MODE_YUV420; } value[0] = 0x0A; //TODO: See the effect of the filter - value[1] = format; + 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 | @@ -1887,10 +1886,10 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, frameRate = FRAMERATE_MAX; } - if (usbvision->tvnorm->id & V4L2_STD_625_50) { + if (usbvision->tvnormId & V4L2_STD_625_50) { frameDrop = frameRate * 32 / 25 - 1; } - else if (usbvision->tvnorm->id & V4L2_STD_525_60) { + else if (usbvision->tvnormId & V4L2_STD_525_60) { frameDrop = frameRate * 32 / 30 - 1; } @@ -2103,8 +2102,8 @@ int usbvision_set_input(struct usb_usbvision *usbvision) return 0; /* Set input format expected from decoder*/ - if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) { - value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff; + 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) { /* SAA7113 uses 8 bit output */ value[0] = USBVISION_8_422_SYNC; @@ -2123,7 +2122,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) } - if (usbvision->tvnorm->id & V4L2_STD_PAL) { + if (usbvision->tvnormId & V4L2_STD_PAL) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; @@ -2132,7 +2131,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) value[5] = 0x00; //0x0060 -> 96 Input video h offset value[6] = 0x16; value[7] = 0x00; //0x0016 -> 22 Input video v offset - } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { + } else if (usbvision->tvnormId & V4L2_STD_SECAM) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; @@ -2175,8 +2174,8 @@ 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 >= 0){ - dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff; + 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 */ @@ -2309,7 +2308,7 @@ static void call_usbvision_power_off(struct work_struct *work) PDEBUG(DBG_FUNC, ""); down_interruptible(&usbvision->lock); if(usbvision->user == 0) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); + usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index e942b1bf2..e91add952 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -1,8 +1,8 @@ /* - * I2C_ALGO_USB.C + * usbvision_i2c.c * i2c algorithm for USB-I2C Bridges * - * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> + * Copyright (c) 1999-2007 Joerg Heckenbach <joerg@heckenbach-aw.de> * Dwaine Garden <dwainegarden@rogers.com> * * This module is part of usbvision driver project. @@ -42,7 +42,6 @@ #include "usbvision.h" #define DBG_I2C 1<<0 -#define DBG_ALGO 1<<1 static int i2c_debug = 0; @@ -52,22 +51,22 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define PDEBUG(level, fmt, args...) \ if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) -static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, +static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len); -static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, +static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len); static inline int try_write_address(struct i2c_adapter *i2c_adap, unsigned char addr, int retries) { - void *data; + struct usb_usbvision *usbvision; int i, ret = -1; char buf[4]; - data = i2c_get_adapdata(i2c_adap); + usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); buf[0] = 0x00; for (i = 0; i <= retries; i++) { - ret = (usbvision_i2c_write(data, addr, buf, 1)); + ret = (usbvision_i2c_write(usbvision, addr, buf, 1)); if (ret == 1) break; /* success! */ udelay(5); @@ -76,8 +75,8 @@ static inline int try_write_address(struct i2c_adapter *i2c_adap, udelay(10); } if (i) { - PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_ALGO,"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; } @@ -85,13 +84,13 @@ static inline int try_write_address(struct i2c_adapter *i2c_adap, static inline int try_read_address(struct i2c_adapter *i2c_adap, unsigned char addr, int retries) { - void *data; + struct usb_usbvision *usbvision; int i, ret = -1; char buf[4]; - data = i2c_get_adapdata(i2c_adap); + usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); for (i = 0; i <= retries; i++) { - ret = (usbvision_i2c_read(data, addr, buf, 1)); + ret = (usbvision_i2c_read(usbvision, addr, buf, 1)); if (ret == 1) break; /* success! */ udelay(5); @@ -100,8 +99,8 @@ static inline int try_read_address(struct i2c_adapter *i2c_adap, udelay(10); } if (i) { - PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_ALGO,"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; } @@ -155,32 +154,32 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, } static int -usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { struct i2c_msg *pmsg; - void *data; + struct usb_usbvision *usbvision; int i, ret; unsigned char addr; - data = i2c_get_adapdata(i2c_adap); + usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); for (i = 0; i < num; i++) { pmsg = &msgs[i]; ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); if (ret != 0) { - PDEBUG(DBG_ALGO,"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(data, addr, pmsg->buf, pmsg->len)); + ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len)); if (ret < pmsg->len) { return (ret < 0) ? ret : -EREMOTEIO; } } else { /* write bytes from buffer */ - ret = (usbvision_i2c_write(data, addr, pmsg->buf, pmsg->len)); + ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len)); if (ret < pmsg->len) { return (ret < 0) ? ret : -EREMOTEIO; } @@ -194,7 +193,7 @@ static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned return 0; } -static u32 usb_func(struct i2c_adapter *adap) +static u32 functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; } @@ -213,7 +212,7 @@ static void dec_use(struct i2c_adapter *adap) /* -----exported algorithm data: ------------------------------------- */ -static struct i2c_algorithm i2c_usb_algo = { +static struct i2c_algorithm usbvision_algo = { #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,30)) .owner = THIS_MODULE, #endif @@ -221,10 +220,10 @@ static struct i2c_algorithm i2c_usb_algo = { .name = "USB algorithm", .id = I2C_ALGO_BIT, /* FIXME */ #endif - .master_xfer = usb_xfer, + .master_xfer = usbvision_i2c_xfer, .smbus_xfer = NULL, .algo_control = algo_control, - .functionality = usb_func, + .functionality = functionality, }; @@ -234,44 +233,32 @@ static struct i2c_algorithm i2c_usb_algo = { static int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) { PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); - PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]"); + PDEBUG(DBG_I2C, "ALGO debugging is enabled [i2c]"); /* register new adapter to i2c module... */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) - adap->id |= i2c_usb_algo.id; + adap->id |= usbvision_algo.id; #endif - adap->algo = &i2c_usb_algo; + adap->algo = &usbvision_algo; adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ i2c_add_adapter(adap); - PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name); + PDEBUG(DBG_I2C,"i2c bus for %s registered", adap->name); return 0; } - -int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap) -{ - - i2c_del_adapter(adap); - - PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name); - - return 0; -} - - /* ----------------------------------------------------------------------- */ /* usbvision specific I2C functions */ /* ----------------------------------------------------------------------- */ static struct i2c_adapter i2c_adap_template; static struct i2c_client i2c_client_template; -int usbvision_init_i2c(struct usb_usbvision *usbvision) +int usbvision_i2c_register(struct usb_usbvision *usbvision) { memcpy(&usbvision->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); @@ -289,7 +276,7 @@ int usbvision_init_i2c(struct usb_usbvision *usbvision) usbvision->i2c_client.adapter = &usbvision->i2c_adap; if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { - printk(KERN_ERR "usbvision_init_i2c: can't write reg\n"); + printk(KERN_ERR "usbvision_register: can't write reg\n"); return -EBUSY; } @@ -311,6 +298,16 @@ int usbvision_init_i2c(struct usb_usbvision *usbvision) return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); } +int usbvision_i2c_unregister(struct usb_usbvision *usbvision) +{ + + i2c_del_adapter(&(usbvision->i2c_adap)); + + PDEBUG(DBG_I2C,"i2c bus for %s unregistered", usbvision->i2c_adap.name); + + return 0; +} + void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, void *arg) { @@ -324,19 +321,12 @@ static int attach_inform(struct i2c_client *client) usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); switch (client->addr << 1) { - case 0x43: - case 0x4b: - { - struct tuner_setup tun_setup; - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = TUNER_TDA9887; - tun_setup.addr = client->addr; - - call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); - + case 0x42 << 1: + case 0x43 << 1: + case 0x4a << 1: + case 0x4b << 1: + PDEBUG(DBG_I2C,"attach_inform: tda9887 detected."); break; - } case 0x42: PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); break; @@ -373,11 +363,7 @@ static int detach_inform(struct i2c_client *client) { struct usb_usbvision *usbvision; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - usbvision = (struct usb_usbvision *)client->adapter->data; -#else usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); -#endif PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); return 0; @@ -508,7 +494,7 @@ static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, return len; } -static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, +static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len) { char *bufPtr = buf; @@ -516,7 +502,6 @@ static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, int wrcount = 0; int count; int maxLen = 4; - struct usb_usbvision *usbvision = (struct usb_usbvision *) data; while (len > 0) { count = (len > maxLen) ? maxLen : len; @@ -531,14 +516,13 @@ static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, return wrcount; } -static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, +static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len) { char temp[4]; int retval, i; int rdcount = 0; int count; - struct usb_usbvision *usbvision = (struct usb_usbvision *) data; while (len > 0) { count = (len > 3) ? 4 : len; diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 89aedd783..6d644bb6d 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -36,7 +36,8 @@ * - use submit_urb for all setup packets * - Fix memory settings for nt1004. It is 4 times as big as the * nt1003 memory. - * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one? + * - Add audio on endpoint 3 for nt1004 chip. + * Seems impossible, needs a codec interface. Which one? * - Clean up the driver. * - optimization for performance. * - Add Videotext capability (VBI). Working on it..... @@ -53,7 +54,6 @@ #include <linux/utsname.h> #include "compat.h" #include <linux/highmem.h> -#include <linux/smp_lock.h> #include <linux/videodev.h> #include <linux/vmalloc.h> #include <linux/module.h> @@ -83,8 +83,10 @@ #endif #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" @@ -92,20 +94,25 @@ #define USBVISION_DRIVER_VERSION_MAJOR 0 #define USBVISION_DRIVER_VERSION_MINOR 9 #define USBVISION_DRIVER_VERSION_PATCHLEVEL 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_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 ENABLE_HEXDUMP 0 /* Enable if you need it */ #ifdef USBVISION_DEBUG #define PDEBUG(level, fmt, args...) \ - if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) + if (video_debug & (level)) \ + info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\ + ## args) #else #define PDEBUG(level, fmt, args...) do {} while(0) #endif -#define DBG_IOCTL 1<<0 #define DBG_IO 1<<1 #define DBG_PROBE 1<<2 #define DBG_MMAP 1<<3 @@ -115,7 +122,8 @@ #define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; -static int usbvision_nr = 0; // sequential number of usbvision device +/* sequential number of usbvision device */ +static int usbvision_nr = 0; static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, @@ -128,57 +136,54 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } }; -/* supported tv norms */ -static struct usbvision_tvnorm tvnorms[] = { - { - .name = "PAL", - .id = V4L2_STD_PAL, - }, { - .name = "NTSC", - .id = V4L2_STD_NTSC, - }, { - .name = "SECAM", - .id = V4L2_STD_SECAM, - }, { - .name = "PAL-M", - .id = V4L2_STD_PAL_M, - } -}; - -#define TVNORMS ARRAY_SIZE(tvnorms) - -// Function prototypes +/* Function prototypes */ static void usbvision_release(struct usb_usbvision *usbvision); -// Default initalization of device driver parameters -static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint -static int video_debug = 0; // Set the default Debug Mode of the device driver -static int PowerOnAtOpen = 1; // Set the default device to power on at startup -static int video_nr = -1; // Sequential Number of Video Device -static int radio_nr = -1; // Sequential Number of Radio Device -static int vbi_nr = -1; // Sequential Number of VBI Device -static char *CustomDevice=NULL; // Set as nothing.... - -// Grab parameters for the device driver - -#if defined(module_param) // Showing parameters under SYSFS +/* Default initalization of device driver parameters */ +/* Set the default format for ISOC endpoint */ +static int isocMode = ISOC_MODE_COMPRESS; +/* Set the default Debug Mode of the device driver */ +static int video_debug = 0; +/* Set the default device to power on at startup */ +static int PowerOnAtOpen = 1; +/* Sequential Number of Video Device */ +static int video_nr = -1; +/* Sequential Number of Radio Device */ +static int radio_nr = -1; +/* Sequential Number of VBI Device */ +static int vbi_nr = -1; + +/* Grab parameters for the device driver */ + +/* Showing parameters under SYSFS */ +#if defined(module_param) module_param(isocMode, int, 0444); module_param(video_debug, int, 0444); module_param(PowerOnAtOpen, int, 0444); module_param(video_nr, int, 0444); module_param(radio_nr, int, 0444); module_param(vbi_nr, int, 0444); -module_param(CustomDevice, charp, 0444); -#else // Old Style +#else +/* Old Style */ MODULE_PARAM(isocMode, "i"); -MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver -MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive -MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup -MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. -MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...) -MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...) -MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...) -MODULE_PARM(CustomDevice, "s"); // .... CustomDevice +/* Grab the Debug Mode of the device driver */ +MODULE_PARM(video_debug, "i"); +/* Grab the compression to be adaptive */ +MODULE_PARM(adjustCompression, "i"); +/* Grab the device to power on at startup */ +MODULE_PARM(PowerOnAtOpen, "i"); +/* To help people with Black and White output with using s-video input. + Some cables and input device are wired differently. */ +MODULE_PARM(SwitchSVideoInput, "i"); +/* video_nr option allows to specify a certain /dev/videoX device + (like /dev/video0 or /dev/video1 ...) */ +MODULE_PARM(video_nr, "i"); +/* radio_nr option allows to specify a certain /dev/radioX device + (like /dev/radio0 or /dev/radio1 ...) */ +MODULE_PARM(radio_nr, "i"); +/* vbi_nr option allows to specify a certain /dev/vbiX device + (like /dev/vbi0 or /dev/vbi1 ...) */ +MODULE_PARM(vbi_nr, "i"); #endif MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); @@ -187,7 +192,6 @@ MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device 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)"); MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); -MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device. Default: null"); // Misc stuff @@ -200,12 +204,13 @@ MODULE_ALIAS(DRIVER_ALIAS); #endif -/****************************************************************************************/ -/* SYSFS Code - Copied from the stv680.c usb module. */ -/* Device information is located at /sys/class/video4linux/video0 */ -/* Device parameters information is located at /sys/module/usbvision */ -/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */ -/****************************************************************************************/ +/*****************************************************************************/ +/* SYSFS Code - Copied from the stv680.c usb module. */ +/* Device information is located at /sys/class/video4linux/video0 */ +/* Device parameters information is located at /sys/module/usbvision */ +/* Device USB Information is located at */ +/* /sys/bus/usb/drivers/USBVision Video Grabber */ +/*****************************************************************************/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) @@ -213,7 +218,8 @@ MODULE_ALIAS(DRIVER_ALIAS); static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); return video_get_drvdata(vdev); } @@ -225,15 +231,18 @@ static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t show_model(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString); + return sprintf(buf, "%s\n", + usbvision_device_data[usbvision->DevModel].ModelString); } static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static ssize_t show_hue(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; @@ -246,7 +255,8 @@ static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_contrast(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; @@ -259,7 +269,8 @@ static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static ssize_t show_brightness(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; @@ -272,7 +283,8 @@ static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static ssize_t show_saturation(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; @@ -285,23 +297,28 @@ static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static ssize_t show_streaming(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); + return sprintf(buf, "%s\n", + YES_NO(usbvision->streaming==Stream_On?1:0)); } static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); static ssize_t show_compression(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); + return sprintf(buf, "%s\n", + YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); } static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); static ssize_t show_device_bridge(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%d\n", usbvision->bridgeType); } @@ -396,7 +413,8 @@ static int usbvision_v4l2_open(struct video_device *dev, int flags) static int usbvision_v4l2_open(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); #endif int errCode = 0; @@ -414,7 +432,8 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) /* Allocate memory for the scratch ring buffer */ errCode = usbvision_scratch_alloc(usbvision); if (isocMode==ISOC_MODE_COMPRESS) { - /* Allocate intermediate decompression buffers only if needed */ + /* Allocate intermediate decompression buffers + only if needed */ errCode = usbvision_decompress_alloc(usbvision); } if (errCode) { @@ -429,7 +448,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) down(&usbvision->lock); if (usbvision->power == 0) { usbvision_power_on(usbvision); - usbvision_init_i2c(usbvision); + usbvision_i2c_register(usbvision); } /* Send init sequence only once, it's large! */ @@ -445,13 +464,12 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) if (!errCode) { usbvision_begin_streaming(usbvision); errCode = usbvision_init_isoc(usbvision); - /* device needs to be initialized before isoc transfer */ + /* device must be initialized before isoc transfer */ usbvision_muxsel(usbvision,0); usbvision->user++; - } - else { + } else { if (PowerOnAtOpen) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); + usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; } @@ -488,7 +506,8 @@ static void usbvision_v4l2_close(struct video_device *dev) static int usbvision_v4l2_close(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); #endif PDEBUG(DBG_IO, "close"); @@ -506,7 +525,8 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) usbvision->user--; if (PowerOnAtOpen) { - /* power off in a little while to avoid off/on every close/open short sequences */ + /* power off in a little while + to avoid off/on every close/open short sequences */ usbvision_set_powerOffTimer(usbvision); usbvision->initialized = 0; } @@ -536,574 +556,586 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) * This is part of Video 4 Linux API. The procedure handles ioctl() calls. * */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) -static int usbvision_v4l2_do_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int vidioc_g_register (struct file *file, void *priv, + struct v4l2_register *reg) { - struct usb_usbvision *usbvision = (struct usb_usbvision *) dev; -#else -static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int errCode; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + /* NT100x has a 8-bit register space */ + errCode = usbvision_read_reg(usbvision, reg->reg&0xff); + if (errCode < 0) { + err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", + __FUNCTION__, errCode); + return errCode; + } + return 0; +} + +static int vidioc_s_register (struct file *file, void *priv, + struct v4l2_register *reg) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); -#endif + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int errCode; - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EFAULT; + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + /* NT100x has a 8-bit register space */ + reg->val = (u8)usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + if (reg->val < 0) { + err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", + __FUNCTION__, errCode); + return errCode; + } + return 0; +} +#endif - switch (cmd) { +static int vidioc_querycap (struct file *file, void *priv, + struct v4l2_capability *vc) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + + strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); + strlcpy(vc->card, + usbvision_device_data[usbvision->DevModel].ModelString, + sizeof(vc->card)); + strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, + sizeof(vc->bus_info)); + vc->version = USBVISION_DRIVER_VERSION; + vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING | + (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); + return 0; +} -#ifdef CONFIG_VIDEO_ADV_DEBUG - /* ioctls to allow direct acces to the NT100x registers */ - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - int errCode; - - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - /* NT100x has a 8-bit register space */ - if (cmd == VIDIOC_DBG_G_REGISTER) - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - else - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (errCode < 0) { - err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__, - cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode); - return errCode; - } - if (cmd == VIDIOC_DBG_S_REGISTER) - reg->val = (u8)errCode; +static int vidioc_enum_input (struct file *file, void *priv, + struct v4l2_input *vi) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int chan; - PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", - cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', - (unsigned int)reg->reg, (unsigned int)reg->val); - return 0; - } -#endif - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *vc=arg; - - memset(vc, 0, sizeof(*vc)); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, - sizeof(vc->card)); - strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, - sizeof(vc->bus_info)); - vc->version = USBVISION_DRIVER_VERSION; - vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); - return 0; - } - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *vi = arg; - int chan; - - if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) - return -EINVAL; - if (usbvision->have_tuner) { - chan = vi->index; - } - else { - chan = vi->index + 1; //skip Television string - } - switch(chan) { - case 0: - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "White Video Input"); - } - else { - strcpy(vi->name, "Television"); - vi->type = V4L2_INPUT_TYPE_TUNER; - vi->audioset = 1; - vi->tuner = chan; - vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM; - } - break; - case 1: - vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "Green Video Input"); - } - 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) { - strcpy(vi->name, "Yellow Video Input"); - } - else { - strcpy(vi->name, "S-Video Input"); - } - vi->std = V4L2_STD_PAL; - break; - case 3: - vi->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(vi->name, "Red Video Input"); - vi->std = V4L2_STD_PAL; - break; - } - PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x", - vi->name, vi->index, vi->tuner,vi->type,(int)vi->std); - return 0; - } - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; - unsigned int i; - int ret; - - i = e->index; - if (i >= TVNORMS) - return -EINVAL; - ret = v4l2_video_std_construct(e, tvnorms[e->index].id, - tvnorms[e->index].name); - e->index = i; - if (ret < 0) - return ret; - return 0; + if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) + return -EINVAL; + if (usbvision->have_tuner) { + chan = vi->index; + } else { + chan = vi->index + 1; /*skip Television string*/ + } + /* Determine the requested input characteristics + specific for each usbvision card model */ + switch(chan) { + case 0: + if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + strcpy(vi->name, "White Video Input"); + } else { + strcpy(vi->name, "Television"); + vi->type = V4L2_INPUT_TYPE_TUNER; + vi->audioset = 1; + vi->tuner = chan; + vi->std = USBVISION_NORMS; } - case VIDIOC_G_INPUT: - { - int *input = arg; - *input = usbvision->ctl_input; - return 0; + break; + case 1: + vi->type = V4L2_INPUT_TYPE_CAMERA; + if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + strcpy(vi->name, "Green Video Input"); + } else { + strcpy(vi->name, "Composite Video Input"); } - case VIDIOC_S_INPUT: - { - int *input = arg; - if ((*input >= usbvision->video_inputs) || (*input < 0) ) - return -EINVAL; - usbvision->ctl_input = *input; - - down(&usbvision->lock); - usbvision_muxsel(usbvision, usbvision->ctl_input); - usbvision_set_input(usbvision); - usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); - up(&usbvision->lock); - return 0; + vi->std = V4L2_STD_PAL; + break; + case 2: + vi->type = V4L2_INPUT_TYPE_CAMERA; + if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + strcpy(vi->name, "Yellow Video Input"); + } else { + strcpy(vi->name, "S-Video Input"); } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; + vi->std = V4L2_STD_PAL; + break; + case 3: + vi->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(vi->name, "Red Video Input"); + vi->std = V4L2_STD_PAL; + break; + } + return 0; +} - *id = usbvision->tvnorm->id; +static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); - return 0; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - unsigned int i; - - for (i = 0; i < TVNORMS; i++) - if (*id == tvnorms[i].id) - break; - if (i == TVNORMS) - for (i = 0; i < TVNORMS; i++) - if (*id & tvnorms[i].id) - break; - if (i == TVNORMS) - return -EINVAL; - - down(&usbvision->lock); - usbvision->tvnorm = &tvnorms[i]; - - call_i2c_clients(usbvision, VIDIOC_S_STD, - &usbvision->tvnorm->id); + *input = usbvision->ctl_input; + return 0; +} - up(&usbvision->lock); +static int vidioc_s_input (struct file *file, void *priv, unsigned int input) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - - if (!usbvision->have_tuner || vt->index) // Only tuner 0 - return -EINVAL; - strcpy(vt->name, "Television"); - /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); - - PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *freq = arg; - - freq->tuner = 0; // Only one tuner - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = usbvision->freq; - PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency); - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *freq = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || freq->tuner) - return -EINVAL; - - usbvision->freq = freq->frequency; - call_i2c_clients(usbvision, cmd, freq); - PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *v = arg; - memset(v,0, sizeof(v)); - strcpy(v->name, "TV"); - PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO"); - return 0; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *v = arg; - if(v->index) { - return -EINVAL; - } - PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO"); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - int id=ctrl->id; + if ((input >= usbvision->video_inputs) || (input < 0) ) + return -EINVAL; + usbvision->ctl_input = input; - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; + down(&usbvision->lock); + usbvision_muxsel(usbvision, usbvision->ctl_input); + usbvision_set_input(usbvision); + usbvision_set_output(usbvision, + usbvision->curwidth, + usbvision->curheight); + up(&usbvision->lock); + return 0; +} - call_i2c_clients(usbvision, cmd, arg); +static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + usbvision->tvnormId=*id; - if (ctrl->type) - return 0; - else - return -EINVAL; + down(&usbvision->lock); + call_i2c_clients(usbvision, VIDIOC_S_STD, + &usbvision->tvnormId); + up(&usbvision->lock); - PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); - PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; + return 0; +} - PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); - return 0; - } - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *vr = arg; - int ret; +static int vidioc_g_tuner (struct file *file, void *priv, + struct v4l2_tuner *vt) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); + if (!usbvision->have_tuner || vt->index) // Only tuner 0 + return -EINVAL; + if(usbvision->radio) { + strcpy(vt->name, "Radio"); + vt->type = V4L2_TUNER_RADIO; + } else { + strcpy(vt->name, "Television"); + } + /* Let clients fill in the remainder of this struct */ + call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); - // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. - if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vr->memory != V4L2_MEMORY_MMAP)) - return -EINVAL; + return 0; +} - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) - return ret; - } +static int vidioc_s_tuner (struct file *file, void *priv, + struct v4l2_tuner *vt) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - vr->count = usbvision_frames_alloc(usbvision,vr->count); + // Only no or one tuner for now + if (!usbvision->have_tuner || vt->index) + return -EINVAL; + /* let clients handle this */ + call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - usbvision->curFrame = NULL; + return 0; +} - PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); - return 0; - } - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *vb = arg; - struct usbvision_frame *frame; +static int vidioc_g_frequency (struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) + freq->tuner = 0; // Only one tuner + if(usbvision->radio) { + freq->type = V4L2_TUNER_RADIO; + } else { + freq->type = V4L2_TUNER_ANALOG_TV; + } + freq->frequency = usbvision->freq; - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } - 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) - vb->flags |= V4L2_BUF_FLAG_QUEUED; - if(frame->grabstate >= FrameState_Done) - vb->flags |= V4L2_BUF_FLAG_DONE; - if(frame->grabstate == FrameState_Unused) - vb->flags |= V4L2_BUF_FLAG_MAPPED; - vb->memory = V4L2_MEMORY_MMAP; - - 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*usbvision->palette.bytes_per_pixel; - vb->timestamp = usbvision->frame[vb->index].timestamp; - vb->sequence = usbvision->frame[vb->index].sequence; - return 0; - } - case VIDIOC_QBUF: - { - struct v4l2_buffer *vb = arg; - struct usbvision_frame *frame; - unsigned long lock_flags; - - // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } - if(vb->index>=usbvision->num_frames) { - return -EINVAL; - } + return 0; +} - frame = &usbvision->frame[vb->index]; +static int vidioc_s_frequency (struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - if (frame->grabstate != FrameState_Unused) { - return -EAGAIN; - } + // Only no or one tuner for now + if (!usbvision->have_tuner || freq->tuner) + return -EINVAL; - /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; - frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ + usbvision->freq = freq->frequency; + call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq); - vb->flags &= ~V4L2_BUF_FLAG_DONE; + return 0; +} - /* set v4l2_format index */ - frame->v4l2_format = usbvision->palette; +static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + memset(a,0,sizeof(*a)); + if(usbvision->radio) { + strcpy(a->name,"Radio"); + } else { + strcpy(a->name, "TV"); + } - PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index); - return 0; - } - case VIDIOC_DQBUF: - { - struct v4l2_buffer *vb = arg; - int ret; - struct usbvision_frame *f; - unsigned long lock_flags; - - if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (list_empty(&(usbvision->outqueue))) { - if (usbvision->streaming == Stream_Idle) - return -EINVAL; - ret = wait_event_interruptible - (usbvision->wait_frame, - !list_empty(&(usbvision->outqueue))); - if (ret) - return ret; - } + return 0; +} - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - f = list_entry(usbvision->outqueue.next, - struct usbvision_frame, frame); - list_del(usbvision->outqueue.next); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - f->grabstate = FrameState_Unused; - - vb->memory = V4L2_MEMORY_MMAP; - vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; - vb->index = f->index; - vb->sequence = f->sequence; - vb->timestamp = f->timestamp; - vb->field = V4L2_FIELD_NONE; - vb->bytesused = f->scanlength; - - return 0; - } - case VIDIOC_STREAMON: - { - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; +static int vidioc_s_audio (struct file *file, void *fh, + struct v4l2_audio *a) +{ + if(a->index) { + return -EINVAL; + } - usbvision->streaming = Stream_On; + return 0; +} - call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); +static int vidioc_queryctrl (struct file *file, void *priv, + struct v4l2_queryctrl *ctrl) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int id=ctrl->id; - PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); + memset(ctrl,0,sizeof(*ctrl)); + ctrl->id=id; - return 0; - } - case VIDIOC_STREAMOFF: - { - int *type = arg; - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if(usbvision->streaming == Stream_On) { - usbvision_stream_interrupt(usbvision); - // Stop all video streamings - call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); - } - usbvision_empty_framequeues(usbvision); + call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl); - PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); - return 0; - } - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *vfd = arg; + if (!ctrl->type) + return -EINVAL; - if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { - return -EINVAL; - } - vfd->flags = 0; - vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); - vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; - memset(vfd->reserved, 0, sizeof(vfd->reserved)); - return 0; - } - case VIDIOC_G_FMT: - { - struct v4l2_format *vf = arg; - - switch (vf->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - vf->fmt.pix.width = usbvision->curwidth; - 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; - vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ - PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - default: - PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type); - return -EINVAL; - } - return 0; - } - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - { - struct v4l2_format *vf = arg; - int formatIdx,ret; - - switch(vf->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - /* 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]; - break; - } - } - /* robustness */ - if(formatIdx == 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); - - vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; - - if(cmd == VIDIOC_TRY_FMT) { - PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - - /* stop io in case it is already in progress */ - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) - return ret; - } - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - - usbvision->curFrame = NULL; - - // by now we are committed to the new data... - down(&usbvision->lock); - usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); - up(&usbvision->lock); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - default: - return -EINVAL; - } - } - default: - return -ENOIOCTLCMD; + return 0; +} + +static int vidioc_g_ctrl (struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); + + return 0; +} + +static int vidioc_s_ctrl (struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); + + return 0; +} + +static int vidioc_reqbufs (struct file *file, + void *priv, struct v4l2_requestbuffers *vr) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int ret; + + RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); + + /* Check input validity: + the user must do a VIDEO CAPTURE and MMAP method. */ + if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (vr->memory != V4L2_MEMORY_MMAP)) + return -EINVAL; + + if(usbvision->streaming == Stream_On) { + if ((ret = usbvision_stream_interrupt(usbvision))) + return ret; } + + usbvision_frames_free(usbvision); + usbvision_empty_framequeues(usbvision); + vr->count = usbvision_frames_alloc(usbvision,vr->count); + + usbvision->curFrame = NULL; + return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) -static int usbvision_v4l2_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +static int vidioc_querybuf (struct file *file, + void *priv, struct v4l2_buffer *vb) { - return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + struct usbvision_frame *frame; + + /* FIXME : must control + that buffers are mapped (VIDIOC_REQBUFS has been called) */ + if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { + return -EINVAL; + } + 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) + vb->flags |= V4L2_BUF_FLAG_QUEUED; + if(frame->grabstate >= FrameState_Done) + vb->flags |= V4L2_BUF_FLAG_DONE; + if(frame->grabstate == FrameState_Unused) + vb->flags |= V4L2_BUF_FLAG_MAPPED; + vb->memory = V4L2_MEMORY_MMAP; + + 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* + usbvision->palette.bytes_per_pixel; + vb->timestamp = usbvision->frame[vb->index].timestamp; + vb->sequence = usbvision->frame[vb->index].sequence; + return 0; } -#else -static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + +static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + struct usbvision_frame *frame; + unsigned long lock_flags; + + /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ + if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { + return -EINVAL; + } + if(vb->index>=usbvision->num_frames) { + return -EINVAL; + } + + frame = &usbvision->frame[vb->index]; + + if (frame->grabstate != FrameState_Unused) { + return -EAGAIN; + } + + /* Mark it as ready and enqueue frame */ + frame->grabstate = FrameState_Ready; + frame->scanstate = ScanState_Scanning; + frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ + + vb->flags &= ~V4L2_BUF_FLAG_DONE; + + /* set v4l2_format index */ + frame->v4l2_format = usbvision->palette; + + spin_lock_irqsave(&usbvision->queue_lock, lock_flags); + list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); + spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + + return 0; +} + +static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) { - return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int ret; + struct usbvision_frame *f; + unsigned long lock_flags; + + if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (list_empty(&(usbvision->outqueue))) { + if (usbvision->streaming == Stream_Idle) + return -EINVAL; + ret = wait_event_interruptible + (usbvision->wait_frame, + !list_empty(&(usbvision->outqueue))); + if (ret) + return ret; + } + + spin_lock_irqsave(&usbvision->queue_lock, lock_flags); + f = list_entry(usbvision->outqueue.next, + struct usbvision_frame, frame); + list_del(usbvision->outqueue.next); + spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + + f->grabstate = FrameState_Unused; + + vb->memory = V4L2_MEMORY_MMAP; + vb->flags = V4L2_BUF_FLAG_MAPPED | + V4L2_BUF_FLAG_QUEUED | + V4L2_BUF_FLAG_DONE; + vb->index = f->index; + vb->sequence = f->sequence; + vb->timestamp = f->timestamp; + vb->field = V4L2_FIELD_NONE; + vb->bytesused = f->scanlength; + + return 0; } -#endif +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; + + usbvision->streaming = Stream_On; + call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); + + return 0; +} + +static int vidioc_streamoff(struct file *file, + void *priv, enum v4l2_buf_type type) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if(usbvision->streaming == Stream_On) { + usbvision_stream_interrupt(usbvision); + /* Stop all video streamings */ + call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); + } + usbvision_empty_framequeues(usbvision); + + return 0; +} + +static int vidioc_enum_fmt_cap (struct file *file, void *priv, + struct v4l2_fmtdesc *vfd) +{ + if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { + return -EINVAL; + } + vfd->flags = 0; + vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); + vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; + memset(vfd->reserved, 0, sizeof(vfd->reserved)); + return 0; +} + +static int vidioc_g_fmt_cap (struct file *file, void *priv, + struct v4l2_format *vf) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + vf->fmt.pix.width = usbvision->curwidth; + 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; + vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ + + return 0; +} + +static int vidioc_try_fmt_cap (struct file *file, void *priv, + struct v4l2_format *vf) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int formatIdx; + + /* 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]; + break; + } + } + /* robustness */ + if(formatIdx == 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); + + vf->fmt.pix.bytesperline = vf->fmt.pix.width* + usbvision->palette.bytes_per_pixel; + vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; + + return 0; +} + +static int vidioc_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *vf) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int ret; + + if( 0 != (ret=vidioc_try_fmt_cap (file, priv, vf)) ) { + return ret; + } + + /* stop io in case it is already in progress */ + if(usbvision->streaming == Stream_On) { + if ((ret = usbvision_stream_interrupt(usbvision))) + return ret; + } + usbvision_frames_free(usbvision); + usbvision_empty_framequeues(usbvision); + + usbvision->curFrame = NULL; + + /* by now we are committed to the new data... */ + down(&usbvision->lock); + usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); + up(&usbvision->lock); + + return 0; +} #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) static long usbvision_v4l2_read(struct video_device *dev, char *buf, @@ -1115,7 +1147,8 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); int noblock = file->f_flags & O_NONBLOCK; #endif unsigned long lock_flags; @@ -1123,16 +1156,18 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, int ret,i; struct usbvision_frame *frame; - PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); + PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, + (unsigned long)count, noblock); if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) return -EFAULT; - /* 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. */ + /* 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) { - /* First, allocate some frames to work with if this has not been done with - VIDIOC_REQBUF */ + /* 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); @@ -1144,21 +1179,24 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); } - /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ + /* Then, enqueue as many frames as possible + (like a user of VIDIOC_QBUF would do) */ for(i=0;i<usbvision->num_frames;i++) { frame = &usbvision->frame[i]; if(frame->grabstate == FrameState_Unused) { /* Mark it as ready and enqueue frame */ frame->grabstate = FrameState_Ready; frame->scanstate = ScanState_Scanning; - frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ + /* Accumulated in usbvision_parse_data() */ + frame->scanlength = 0; /* set v4l2_format index */ frame->v4l2_format = usbvision->palette; spin_lock_irqsave(&usbvision->queue_lock, lock_flags); list_add_tail(&frame->frame, &usbvision->inqueue); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + spin_unlock_irqrestore(&usbvision->queue_lock, + lock_flags); } } @@ -1186,8 +1224,9 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, return 0; } - PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__, - frame->index, frame->bytes_read, frame->scanlength); + PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", + __FUNCTION__, + frame->index, frame->bytes_read, frame->scanlength); /* copy bytes to user space; we allow for partials reads */ if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) @@ -1198,10 +1237,11 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, } frame->bytes_read += count; - PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__, - (unsigned long)count, frame->bytes_read); + PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", + __FUNCTION__, + (unsigned long)count, frame->bytes_read); - // For now, forget the frame if it has not been read in one shot. + /* 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 */ frame->bytes_read = 0; @@ -1220,7 +1260,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) u32 i; struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); PDEBUG(DBG_MMAP, "mmap"); @@ -1238,11 +1279,13 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) } for (i = 0; i < usbvision->num_frames; i++) { - if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff) + if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == + vma->vm_pgoff) break; } if (i == usbvision->num_frames) { - PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); + PDEBUG(DBG_MMAP, + "mmap: user supplied mapping address is out of range"); up(&usbvision->lock); return -EINVAL; } @@ -1281,9 +1324,9 @@ static int usbvision_radio_open(struct video_device *dev, int flags) static int usbvision_radio_open(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); #endif - struct v4l2_frequency freq; int errCode = 0; PDEBUG(DBG_IO, "%s:", __FUNCTION__); @@ -1302,7 +1345,7 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) usbvision_reset_powerOffTimer(usbvision); if (usbvision->power == 0) { usbvision_power_on(usbvision); - usbvision_init_i2c(usbvision); + usbvision_i2c_register(usbvision); } } @@ -1316,8 +1359,6 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) // If so far no errors then we shall start the radio usbvision->radio = 1; call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); - freq.frequency = 1517; //SWR3 @ 94.8MHz - call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq); usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); usbvision->user++; } @@ -1327,7 +1368,7 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) MOD_DEC_USE_COUNT; #endif if (PowerOnAtOpen) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); + usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; } @@ -1345,7 +1386,8 @@ static void usbvision_radio_close(struct video_device *dev) static int usbvision_radio_close(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); int errCode = 0; #endif @@ -1385,149 +1427,6 @@ static int usbvision_radio_close(struct inode *inode, struct file *file) #endif } -static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EIO; - - switch (cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *vc=arg; - - memset(vc, 0, sizeof(*vc)); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, - sizeof(vc->card)); - strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, - sizeof(vc->bus_info)); - vc->version = USBVISION_DRIVER_VERSION; - vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - PDEBUG(DBG_IO, "VIDIOC_QUERYCAP"); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - int id=ctrl->id; - - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; - - call_i2c_clients(usbvision, cmd, arg); - PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); - - if (ctrl->type) - return 0; - else - return -EINVAL; - - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); - PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); - PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - - if (t->index > 0) - return -EINVAL; - - memset(t,0,sizeof(*t)); - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - - /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,t); - PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - - PDEBUG(DBG_IO, "VIDIOC_S_TUNER"); - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; - - memset(a,0,sizeof(*a)); - strcpy(a->name,"Radio"); - PDEBUG(DBG_IO, "VIDIOC_G_AUDIO"); - return 0; - } - case VIDIOC_S_AUDIO: - case VIDIOC_S_INPUT: - case VIDIOC_S_STD: - return 0; - - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - memset(f,0,sizeof(*f)); - - f->type = V4L2_TUNER_RADIO; - f->frequency = usbvision->freq; - call_i2c_clients(usbvision, cmd, f); - PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency); - - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (f->tuner != 0) - return -EINVAL; - usbvision->freq = f->frequency; - call_i2c_clients(usbvision, cmd, f); - PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency); - - return 0; - } - default: - { - PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd); - return -ENOIOCTLCMD; - } - } - return 0; -} - - -static int usbvision_radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl); -} - - /* * Here comes the stuff for vbi on usbvision based devices * @@ -1541,7 +1440,7 @@ static int usbvision_vbi_open(struct inode *inode, struct file *file) { #endif /* TODO */ - return -EINVAL; + return -ENODEV; } @@ -1554,14 +1453,14 @@ static int usbvision_vbi_close(struct inode *inode, struct file *file) { #endif /* TODO */ - return -EINVAL; + return -ENODEV; } static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { /* TODO */ - return -EINVAL; + return -ENOIOCTLCMD; } static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, @@ -1584,7 +1483,7 @@ static struct video_device usbvision_video_template = { .close = usbvision_v4l2_close, .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, - .ioctl = usbvision_v4l2_ioctl, + .ioctl = video_ioctl2, .minor = -1, }; #else @@ -1596,8 +1495,13 @@ static const struct file_operations usbvision_fops = { .release = usbvision_v4l2_close, .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, - .ioctl = usbvision_v4l2_ioctl, + .ioctl = video_ioctl2, .llseek = no_llseek, +/* .poll = video_poll, */ + .mmap = usbvision_v4l2_mmap, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) + .compat_ioctl = v4l_compat_ioctl32, +#endif }; static struct video_device usbvision_video_template = { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,31) @@ -1611,6 +1515,39 @@ static struct video_device usbvision_video_template = { .release = video_device_release, #endif .minor = -1, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, + .vidioc_g_fmt_cap = vidioc_g_fmt_cap, + .vidioc_try_fmt_cap = vidioc_try_fmt_cap, + .vidioc_s_fmt_cap = vidioc_s_fmt_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_g_audio = vidioc_s_audio, + .vidioc_g_ctrl = vidioc_g_ctrl, + .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, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif + .tvnorms = USBVISION_NORMS, + .current_norm = V4L2_STD_PAL }; #endif @@ -1619,14 +1556,12 @@ static struct video_device usbvision_video_template = { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) static struct video_device usbvision_radio_template= { - type: VID_TYPE_TUNER, - hardware: VID_HARDWARE_USBVISION, - open: usbvision_radio_open, - close: usbvision_radio_close, - read: usbvision_radio_read, // just returns -EINVAL - write: usbvision_radio_write, // just returns -EINVAL - ioctl: usbvision_radio_ioctl, - minor: -1, + .type = VID_TYPE_TUNER, + .hardware = VID_HARDWARE_USBVISION, + .open = usbvision_radio_open, + .close = usbvision_radio_close, + .ioctl = video_ioctl2, + .minor -1, }; #else static const struct file_operations usbvision_radio_fops = { @@ -1635,8 +1570,11 @@ static const struct file_operations usbvision_radio_fops = { #endif .open = usbvision_radio_open, .release = usbvision_radio_close, - .ioctl = usbvision_radio_ioctl, + .ioctl = video_ioctl2, .llseek = no_llseek, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) + .compat_ioctl = v4l_compat_ioctl32, +#endif }; static struct video_device usbvision_radio_template= @@ -1648,14 +1586,29 @@ static struct video_device usbvision_radio_template= .hardware = VID_HARDWARE_USBVISION, .fops = &usbvision_radio_fops, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .release = video_device_release, .name = "usbvision-radio", + .release = video_device_release, #endif .minor = -1, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_g_audio = vidioc_s_audio, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + + .tvnorms = USBVISION_NORMS, + .current_norm = V4L2_STD_PAL }; #endif - // vbi template #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) static struct video_device usbvision_vbi_template= @@ -1676,6 +1629,9 @@ static const struct file_operations usbvision_vbi_fops = { .release = usbvision_vbi_close, .ioctl = usbvision_vbi_ioctl, .llseek = no_llseek, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) + .compat_ioctl = v4l_compat_ioctl32, +#endif }; static struct video_device usbvision_vbi_template= @@ -1726,14 +1682,14 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) { // vbi Device: if (usbvision->vbi) { - PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f); + PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", + usbvision->vbi->minor & 0x1f); if (usbvision->vbi->minor != -1) { video_unregister_device(usbvision->vbi); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) video_device_release(usbvision->vbi); #endif - } - else { + } else { video_device_release(usbvision->vbi); } usbvision->vbi = NULL; @@ -1741,14 +1697,14 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Radio Device: if (usbvision->rdev) { - PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f); + PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", + usbvision->rdev->minor & 0x1f); if (usbvision->rdev->minor != -1) { video_unregister_device(usbvision->rdev); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) video_device_release(usbvision->rdev); #endif - } - else { + } else { video_device_release(usbvision->rdev); } usbvision->rdev = NULL; @@ -1756,14 +1712,14 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Video Device: if (usbvision->vdev) { - PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f); + PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", + usbvision->vdev->minor & 0x1f); if (usbvision->vdev->minor != -1) { video_unregister_device(usbvision->vdev); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) video_device_release(usbvision->vdev); #endif - } - else { + } else { video_device_release(usbvision->vdev); } usbvision->vdev = NULL; @@ -1774,37 +1730,52 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) { // Video Device: - usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); + usbvision->vdev = usbvision_vdev_init(usbvision, + &usbvision_video_template, + "USBVision Video"); 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 /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f); + printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", + usbvision->nr,usbvision->vdev->minor & 0x1f); // Radio Device: if (usbvision_device_data[usbvision->DevModel].Radio) { // usbvision has radio - usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); + usbvision->rdev = usbvision_vdev_init(usbvision, + &usbvision_radio_template, + "USBVision Radio"); 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 /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f); + printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", + usbvision->nr, usbvision->rdev->minor & 0x1f); } // vbi Device: if (usbvision_device_data[usbvision->DevModel].vbi) { - usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); + usbvision->vbi = usbvision_vdev_init(usbvision, + &usbvision_vbi_template, + "USBVision VBI"); if (usbvision->vdev == NULL) { goto err_exit; } - if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { + if (video_register_device(usbvision->vbi, + VFL_TYPE_VBI, + vbi_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f); + printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", + usbvision->nr,usbvision->vbi->minor & 0x1f); } // all done return 0; @@ -1818,7 +1789,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) /* * usbvision_alloc() * - * This code allocates the struct usb_usbvision. It is filled with default values. + * This code allocates the struct usb_usbvision. + * It is filled with default values. * * Returns NULL on error, a pointer to usb_usbvision else. * @@ -1828,13 +1800,15 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) struct usb_usbvision *usbvision; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - if ((usbvision = kmalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { + if ((usbvision = kmalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == + NULL) { goto err_exit; } memset(usbvision, 0, sizeof(struct usb_usbvision)); #else - if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { + if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == + NULL) { goto err_exit; } #endif @@ -1901,11 +1875,11 @@ static void usbvision_release(struct usb_usbvision *usbvision) } -/******************************** usb interface *****************************************/ +/*********************** usb interface **********************************/ static void usbvision_configure_video(struct usb_usbvision *usbvision) { - int model,i; + int model; if (usbvision == NULL) return; @@ -1913,27 +1887,25 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) model = usbvision->DevModel; usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; - if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) { - usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff; + if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) { + usbvision->Vin_Reg2_Preset = + usbvision_device_data[usbvision->DevModel].Vin_Reg2; } else { usbvision->Vin_Reg2_Preset = 0; } - for (i = 0; i < TVNORMS; i++) - if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) - break; - if (i == TVNORMS) - i = 0; - usbvision->tvnorm = &tvnorms[i]; /* set default norm */ + usbvision->tvnormId = usbvision_device_data[model].VideoNorm; usbvision->video_inputs = usbvision_device_data[model].VideoChannels; usbvision->ctl_input = 0; /* This should be here to make i2c clients to be able to register */ - usbvision_audio_off(usbvision); //first switch off audio + /* first switch off audio */ + usbvision_audio_off(usbvision); if (!PowerOnAtOpen) { - usbvision_power_on(usbvision); //and then power up the noisy tuner - usbvision_init_i2c(usbvision); + /* and then power up the noisy tuner */ + usbvision_power_on(usbvision); + usbvision_i2c_register(usbvision); } } @@ -1944,105 +1916,60 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) * if it looks like USBVISION video device * */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static void *usbvision_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) -{ - const struct usb_interface_descriptor *interface; -#else -static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) +static int __devinit usbvision_probe(struct usb_interface *intf, + const struct usb_device_id *devid) { struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf)); struct usb_interface *uif; __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; const struct usb_host_interface *interface; -#endif struct usb_usbvision *usbvision = NULL; const struct usb_endpoint_descriptor *endpoint; int model,i; PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", - dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); + dev->descriptor.idVendor, + dev->descriptor.idProduct, ifnum); - /* Is it an USBVISION video dev? */ - model = 0; - for(model = 0; usbvision_device_data[model].idVendor; model++) { - if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) { - continue; - } - if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) { - continue; - } - - printk(KERN_INFO "%s: %s found\n", __FUNCTION__, usbvision_device_data[model].ModelString); - break; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - if (usbvision_device_data[model].idVendor == 0) { - return NULL; //no matching device - } - 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]; - - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { - err("%s: USBVision interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); - err("%s: USBVision Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes); - return NULL; - } - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - err("%s: USBVision interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); - return NULL; + model = devid->driver_info; + 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", __FUNCTION__, + usbvision_device_data[model].ModelString); - MOD_INC_USE_COUNT; - - /* Allocate the usbvision device structure so that we can set some variables */ - if ((usbvision = usbvision_alloc(dev)) == NULL) { - err("%s: couldn't allocate USBVision struct", __FUNCTION__); - MOD_DEC_USE_COUNT; - return NULL; - } -#else - if (usbvision_device_data[model].idVendor == 0) { - return -ENODEV; //no matching device - } if (usbvision_device_data[model].Interface >= 0) { interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; - } - else { + } else { interface = &dev->actconfig->interface[ifnum]->altsetting[0]; } endpoint = &interface->endpoint[1].desc; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { - err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); - err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes); + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_ISOC) { + err("%s: interface %d. has non-ISO endpoint!", + __FUNCTION__, ifnum); + err("%s: Endpoint attributes %d", + __FUNCTION__, endpoint->bmAttributes); return -ENODEV; } - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_OUT) { + err("%s: interface %d. has ISO OUT endpoint!", + __FUNCTION__, ifnum); return -ENODEV; } - usb_get_dev(dev); - if ((usbvision = usbvision_alloc(dev)) == NULL) { err("%s: couldn't allocate USBVision struct", __FUNCTION__); return -ENOMEM; } -#endif + if (dev->descriptor.bNumConfigurations > 1) { usbvision->bridgeType = BRIDGE_NT1004; - } - else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") { + } else if (model == DAZZLE_DVC_90_REV_1_SECAM) { usbvision->bridgeType = BRIDGE_NT1005; - } - else { + } else { usbvision->bridgeType = BRIDGE_NT1003; } PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); @@ -2143,7 +2070,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) usbvision_stop_isoc(usbvision); if (usbvision->power) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); + usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); } usbvision->remove_pending = 1; // Now all ISO data will be ignored @@ -2156,11 +2083,11 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) up(&usbvision->lock); if (usbvision->user) { - printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__); + printk(KERN_INFO "%s: In use, disconnect pending\n", + __FUNCTION__); wake_up_interruptible(&usbvision->wait_frame); wake_up_interruptible(&usbvision->wait_stream); - } - else { + } else { usbvision_release(usbvision); } @@ -2172,7 +2099,8 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) } static struct usb_driver usbvision_driver = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,31)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,31)) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) .owner = THIS_MODULE, #endif .name = "usbvision", @@ -2182,124 +2110,6 @@ static struct usb_driver usbvision_driver = { }; /* - * customdevice_process() - * - * This procedure preprocesses CustomDevice parameter if any - * - */ -static void customdevice_process(void) -{ - usbvision_device_data[0]=usbvision_device_data[1]; - usbvision_table[0]=usbvision_table[1]; - - if(CustomDevice) - { - char *parse=CustomDevice; - - PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice); - - /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1" - usbvision_device_data[0].idVendor; - usbvision_device_data[0].idProduct; - usbvision_device_data[0].Interface; - usbvision_device_data[0].Codec; - usbvision_device_data[0].VideoChannels; - usbvision_device_data[0].VideoNorm; - usbvision_device_data[0].AudioChannels; - usbvision_device_data[0].Radio; - usbvision_device_data[0].Tuner; - usbvision_device_data[0].TunerType; - usbvision_device_data[0].Vin_Reg1; - usbvision_device_data[0].Vin_Reg2; - usbvision_device_data[0].X_Offset; - usbvision_device_data[0].Y_Offset; - usbvision_device_data[0].Dvi_yuv; - usbvision_device_data[0].ModelString; - */ - - rmspace(parse); - usbvision_device_data[0].ModelString="USBVISION Custom Device"; - - parse+=2; - sscanf(parse,"%x",&usbvision_device_data[0].idVendor); - goto2next(parse); - PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor); - parse+=2; - sscanf(parse,"%x",&usbvision_device_data[0].idProduct); - goto2next(parse); - PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct); - sscanf(parse,"%d",&usbvision_device_data[0].Interface); - goto2next(parse); - PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface); - sscanf(parse,"%d",&usbvision_device_data[0].Codec); - goto2next(parse); - PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec); - sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels); - goto2next(parse); - PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels); - - switch(*parse) - { - case 'P': - PDEBUG(DBG_PROBE, "VideoNorm=PAL"); - usbvision_device_data[0].VideoNorm=V4L2_STD_PAL; - break; - - case 'S': - PDEBUG(DBG_PROBE, "VideoNorm=SECAM"); - usbvision_device_data[0].VideoNorm=V4L2_STD_SECAM; - break; - - case 'N': - PDEBUG(DBG_PROBE, "VideoNorm=NTSC"); - usbvision_device_data[0].VideoNorm=V4L2_STD_NTSC; - break; - - default: - PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)"); - usbvision_device_data[0].VideoNorm=V4L2_STD_PAL; - break; - } - goto2next(parse); - - sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels); - goto2next(parse); - PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels); - sscanf(parse,"%d",&usbvision_device_data[0].Radio); - goto2next(parse); - PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio); - sscanf(parse,"%d",&usbvision_device_data[0].Tuner); - goto2next(parse); - PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner); - sscanf(parse,"%d",&usbvision_device_data[0].TunerType); - goto2next(parse); - PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType); - sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1); - goto2next(parse); - PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1); - sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2); - goto2next(parse); - PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2); - sscanf(parse,"%d",&usbvision_device_data[0].X_Offset); - goto2next(parse); - PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset); - sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset); - goto2next(parse); - PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset); - sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv); - PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv); - - //add to usbvision_table also - usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE; - usbvision_table[0].idVendor=usbvision_device_data[0].idVendor; - usbvision_table[0].idProduct=usbvision_device_data[0].idProduct; - - } -} - - - -/* * usbvision_init() * * This code is run to initialize the driver. @@ -2311,7 +2121,6 @@ static int __init usbvision_init(void) PDEBUG(DBG_PROBE, ""); - PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]"); PDEBUG(DBG_IO, "IO debugging is enabled [video]"); PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); @@ -2323,8 +2132,6 @@ static int __init usbvision_init(void) usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P } - customdevice_process(); - errCode = usb_register(&usbvision_driver); if (errCode == 0) { diff --git a/linux/drivers/media/video/usbvision/usbvision.h b/linux/drivers/media/video/usbvision/usbvision.h index bee7d06bc..29971a0a1 100644 --- a/linux/drivers/media/video/usbvision/usbvision.h +++ b/linux/drivers/media/video/usbvision/usbvision.h @@ -222,6 +222,8 @@ enum { #define I2C_USB_ADAP_MAX 16 +#define USBVISION_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_M) + /* ----------------------------------------------------------------- */ /* usbvision video structures */ /* ----------------------------------------------------------------- */ @@ -302,14 +304,6 @@ struct usbvision_frame_header { __u16 frameHeight; /* 10 - 11 after endian correction*/ }; -/* tvnorms */ -struct usbvision_tvnorm { - char *name; - v4l2_std_id id; - /* mode for saa7113h */ - int mode; -}; - struct usbvision_frame { char *data; /* Frame buffer */ struct usbvision_frame_header isocHeader; /* Header from stream */ @@ -342,23 +336,24 @@ struct usbvision_frame { #define BRIDGE_NT1005 1005 struct usbvision_device_data_st { - int idVendor; - int idProduct; - int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ - int Codec; - int VideoChannels; __u64 VideoNorm; - int AudioChannels; - int Radio; - int vbi; - int Tuner; - int TunerType; - int Vin_Reg1; - int Vin_Reg2; - int X_Offset; - int Y_Offset; - int Dvi_yuv; - char *ModelString; + 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; + 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; }; /* Declared on usbvision-cards.c */ @@ -445,7 +440,7 @@ struct usb_usbvision { struct v4l2_capability vcap; /* Video capabilities */ unsigned int ctl_input; /* selected input */ - struct usbvision_tvnorm *tvnorm; /* selected tv norm */ + v4l2_std_id tvnormId; /* selected tv norm */ unsigned char video_endp; /* 0x82 for USBVISION devices based */ // Decompression stuff: @@ -485,34 +480,11 @@ struct usb_usbvision { /* i2c-algo-usb declaration */ /* --------------------------------------------------------------- */ -int usbvision_i2c_usb_del_bus(struct i2c_adapter *); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static inline void *i2c_get_clientdata (struct i2c_client *dev) -{ - return dev->data; -} - -static inline void i2c_set_clientdata (struct i2c_client *dev, void *data) -{ - dev->data = data; -} - -static inline void *i2c_get_adapdata (struct i2c_adapter *dev) -{ - return dev->data; -} - -static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data) -{ - dev->data = data; -} -#endif - /* ----------------------------------------------------------------------- */ /* usbvision specific I2C functions */ /* ----------------------------------------------------------------------- */ -int usbvision_init_i2c(struct usb_usbvision *usbvision); +int usbvision_i2c_register(struct usb_usbvision *usbvision); +int usbvision_i2c_unregister(struct usb_usbvision *usbvision); void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); /* defined in usbvision-core.c */ diff --git a/linux/drivers/media/video/v4l1-compat.c b/linux/drivers/media/video/v4l1-compat.c index 2e42ee3a2..291419a6d 100644 --- a/linux/drivers/media/video/v4l1-compat.c +++ b/linux/drivers/media/video/v4l1-compat.c @@ -23,7 +23,6 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> -#include <linux/smp_lock.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/file.h> @@ -129,7 +128,7 @@ set_v4l_control(struct inode *inode, /* ----------------------------------------------------------------- */ -static int palette2pixelformat[] = { +const static unsigned int palette2pixelformat[] = { [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, @@ -147,7 +146,7 @@ static int palette2pixelformat[] = { [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P, }; -static unsigned int +static unsigned int __attribute_pure__ palette_to_pixelformat(unsigned int palette) { if (palette < ARRAY_SIZE(palette2pixelformat)) @@ -156,8 +155,8 @@ palette_to_pixelformat(unsigned int palette) return 0; } -static unsigned int -pixelformat_to_palette(int pixelformat) +static unsigned int __attribute_const__ +pixelformat_to_palette(unsigned int pixelformat) { int palette = 0; switch (pixelformat) @@ -629,6 +628,8 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSPICT: /* set tone controls & partial capture format */ { struct video_picture *pict = arg; + int mem_err = 0, ovl_err = 0; + memset(&fbuf2, 0, sizeof(fbuf2)); set_v4l_control(inode, file, @@ -641,33 +642,59 @@ v4l_compat_translate_ioctl(struct inode *inode, V4L2_CID_SATURATION, pict->colour, drv); set_v4l_control(inode, 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. + */ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) + /* 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: %d\n",err); - if (fmt2->fmt.pix.pixelformat != - palette_to_pixelformat(pict->palette)) { + mem_err = -1000; /* didn't even try */ + } else if (fmt2->fmt.pix.pixelformat != + palette_to_pixelformat(pict->palette)) { fmt2->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err); + mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2); + if (mem_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", + mem_err); } err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); - if (err < 0) + /* 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: %d\n",err); - if (fbuf2.fmt.pixelformat != - palette_to_pixelformat(pict->palette)) { + ovl_err = -1000; /* didn't even try */ + } else if (fbuf2.fmt.pixelformat != + palette_to_pixelformat(pict->palette)) { fbuf2.fmt.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); - if (err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err); - err = 0; /* likely fails for non-root */ + ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); + 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; break; } case VIDIOCGTUNER: /* get tuner information */ diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 0a45e19cb..5f4094f21 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -47,7 +47,6 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/smp_lock.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/errno.h> diff --git a/linux/drivers/media/video/video-buf.c b/linux/drivers/media/video/video-buf.c index 5564e20af..c053375bb 100644 --- a/linux/drivers/media/video/video-buf.c +++ b/linux/drivers/media/video/video-buf.c @@ -708,9 +708,7 @@ videobuf_qbuf(struct videobuf_queue *q, dprintk(1,"qbuf: memory type is wrong.\n"); goto done; } - if (buf->state == STATE_QUEUED || - buf->state == STATE_PREPARED || - buf->state == STATE_ACTIVE) { + if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) { dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; } diff --git a/linux/drivers/media/video/videocodec.c b/linux/drivers/media/video/videocodec.c index 290e64135..f2bbd7a4d 100644 --- a/linux/drivers/media/video/videocodec.c +++ b/linux/drivers/media/video/videocodec.c @@ -348,6 +348,9 @@ videocodec_build_table (void) kfree(videocodec_buf); videocodec_buf = kmalloc(size, GFP_KERNEL); + if (!videocodec_buf) + return 0; + i = 0; i += scnprintf(videocodec_buf + i, size - 1, "<S>lave or attached <M>aster name type flags magic "); diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c index acb3c4fbf..063f02159 100644 --- a/linux/drivers/media/video/videodev.c +++ b/linux/drivers/media/video/videodev.c @@ -30,7 +30,6 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/smp_lock.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/errno.h> @@ -457,13 +456,43 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, int ret = -EINVAL; if ( (vfd->debug & V4L2_DEBUG_IOCTL) && - !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) { + !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, 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 ------------------------------------- */ + if (cmd == VIDIOCGMBUF) { + struct video_mbuf *p=arg; + + memset(p,0,sizeof(p)); + + if (!vfd->vidiocgmbuf) + return ret; + ret=vfd->vidiocgmbuf(file, fh, p); + if (!ret) + dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", + p->size, p->frames, + (unsigned long)p->offsets); + return ret; + } + + /******************************************************** + 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') return v4l_compat_translate_ioctl(inode,file,cmd,arg, __video_do_ioctl); +#endif switch(cmd) { /* --- capabilities ------------------------------------------ */ @@ -815,24 +844,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_overlay(file, fh, *i); break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* --- streaming capture ------------------------------------- */ - case VIDIOCGMBUF: - { - struct video_mbuf *p=arg; - - memset(p,0,sizeof(p)); - - if (!vfd->vidiocgmbuf) - break; - ret=vfd->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 case VIDIOC_G_FBUF: { struct v4l2_framebuffer *p=arg; @@ -1427,6 +1438,11 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_PARM: { struct v4l2_streamparm *p=arg; + __u32 type=p->type; + + memset(p,0,sizeof(*p)); + p->type=type; + if (vfd->vidioc_g_parm) { ret=vfd->vidioc_g_parm(file, fh, p); } else { @@ -1438,8 +1454,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, v4l2_video_std_construct(&s, vfd->current_norm, v4l2_norm_to_name(vfd->current_norm)); - memset(p,0,sizeof(*p)); - p->parm.capture.timeperframe = s.frameperiod; ret=0; } diff --git a/linux/drivers/media/video/zc0301/Kconfig b/linux/drivers/media/video/zc0301/Kconfig index a859a6920..47cd93f9c 100644 --- a/linux/drivers/media/video/zc0301/Kconfig +++ b/linux/drivers/media/video/zc0301/Kconfig @@ -1,6 +1,6 @@ config USB_ZC0301 tristate "USB ZC0301[P] Image Processor and Control Chip support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on the ZC0301 or ZC0301P Image Processors and Control Chips. diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 4c46573c9..de85abc45 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -2037,7 +2037,7 @@ zoran_do_ioctl (struct inode *inode, * but moving the free code outside the munmap() handler fixes * all this... If someone knows why, please explain me (Ronald) */ - if (!!mutex_trylock(&zr->resource_lock)) { + if (mutex_trylock(&zr->resource_lock)) { /* we obtained it! Let's try to free some things */ if (fh->jpg_buffers.ready_to_be_freed) jpg_fbuffer_free(file); diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 88b1fec85..b72d153c5 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -797,6 +797,7 @@ static int zr364xx_probe(struct usb_interface *intf, { struct usb_device *udev = interface_to_usbdev(intf); struct zr364xx_camera *cam = NULL; + int err; DBG("probing..."); @@ -804,12 +805,11 @@ static int zr364xx_probe(struct usb_interface *intf, info("model %04x:%04x detected", udev->descriptor.idVendor, udev->descriptor.idProduct); - if ((cam = - kmalloc(sizeof(struct zr364xx_camera), GFP_KERNEL)) == NULL) { + cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); + if (cam == NULL) { info("cam: out of memory !"); - return -ENODEV; + return -ENOMEM; } - memset(cam, 0x00, sizeof(struct zr364xx_camera)); /* save the init method used by this camera */ cam->method = id->driver_info; @@ -817,7 +817,7 @@ static int zr364xx_probe(struct usb_interface *intf, if (cam->vdev == NULL) { info("cam->vdev: out of memory !"); kfree(cam); - return -ENODEV; + return -ENOMEM; } memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); video_set_drvdata(cam->vdev, cam); @@ -863,12 +863,13 @@ static int zr364xx_probe(struct usb_interface *intf, cam->brightness = 64; mutex_init(&cam->lock); - if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { + err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); + if (err) { info("video_register_device failed"); video_device_release(cam->vdev); kfree(cam->buffer); kfree(cam); - return -ENODEV; + return err; } usb_set_intfdata(intf, cam); @@ -910,7 +911,7 @@ static struct usb_driver zr364xx_driver = { static int __init zr364xx_init(void) { int retval; - retval = usb_register(&zr364xx_driver) < 0; + retval = usb_register(&zr364xx_driver); if (retval) info("usb_register failed!"); else |